1 | # Jenkins JS Builder
|
2 |
|
3 | > __[JIRA](https://issues.jenkins-ci.org/browse/JENKINS/component/21132)__
|
4 |
|
5 | __Table of Contents__:
|
6 | <p>
|
7 | <ul>
|
8 | <a href="#overview">Overview</a><br/>
|
9 | <a href="#features">Features</a><br/>
|
10 | <a href="#install">Install</a><br/>
|
11 | <a href="#general-usage">General Usage</a><br/>
|
12 | <a href="#predefined-gulp-tasks">Predefined Gulp Tasks</a><br/>
|
13 | <a href="#redefining-one-of-the-predefined-gulp-tasks">Redefining one of the predefined Gulp tasks</a><br/>
|
14 | <a href="#bundling-options">Bundling Options</a><br/>
|
15 | <a href="#setting-src-and-test-spec-paths">Setting 'src' and 'test' (spec) paths</a><br/>
|
16 | <a href="#command-line-options">Command line options</a><br/>
|
17 | <a href="#maven-integration">Maven Integration</a><br/>
|
18 | <a href="https://github.com/jenkinsci/js-samples">Sample Plugins (Jenkins - HPI)</a><br/>
|
19 | <a href="https://issues.jenkins-ci.org/browse/JENKINS/component/21132">JIRA</a><br/>
|
20 | </ul>
|
21 | </p>
|
22 |
|
23 | <hr/>
|
24 |
|
25 | # Overview
|
26 | [NPM] utility for building [CommonJS] module [bundle]s (and optionally making them __[js-modules]__ compatible).
|
27 |
|
28 | > See __[js-modules]__.
|
29 |
|
30 | The following diagram illustrates the basic flow (and components used) in the process of building a [CommonJS] module [bundle].
|
31 | It uses a number of popular JavaScript and maven tools ([CommonJS]/[node.js], [Browserify], [Gulp], [frontend-maven-plugin] and more).
|
32 |
|
33 | <p align="center">
|
34 | <a href="https://github.com/jenkinsci/js-modules" target="_blank">
|
35 | <img src="res/build_workflow.png" alt="Jenkins Module Bundle Build Workflow">
|
36 | </a>
|
37 | </p>
|
38 |
|
39 | The responsibilities of the components in the above diagram can be summarized as follows:
|
40 |
|
41 | * __[CommonJS]__: JavaScript module system (i.e. the expected format of JavaScript modules). This module system works with the nice/clean synchronous `require` syntax synonymous with [node.js] (for module loading) e.g. `var mathUtil = require('../util/mathUtil');`. This allows us to tap into the huge [NPM] JavaScript ecosystem.
|
42 | * __[Browserify]__: A build time utility ([NPM] package - executed as a [Gulp] "task") for "bundling" a graph of [CommonJS] style modules together, producing a single JavaScript file ([bundle]) that can be loaded (from a single request) in a browser. [Browserify] ensures that the `require` calls (see above) resolve properly to the correct module within the [bundle].
|
43 | * __[Gulp]__: A JavaScript build system ([NPM] package), analogous to what Maven is for Java i.e. executes "tasks" that eventually produce build artifacts. In this case, a JavaScript __[bundle]__ is produced via [Gulp]s execution of a [Browserify] "task".
|
44 | * __[frontend-maven-plugin]__: A Maven plugin that allows us to hook a [Gulp] "build" into a maven build e.g. for a Jenkins plugin. See <a href="#maven-integration">Maven Integration</a> below.
|
45 |
|
46 | # Features
|
47 | `js-builder` does a number of things:
|
48 |
|
49 | 1. Runs [Jasmine] tests/specs and produce a JUnit report that can be picked up by a top level Maven build.
|
50 | 1. Uses [Browserify] to produce a [CommonJS] module __[bundle]__ file from a "main" [CommonJS] module (see the `bundle` task below). The [bundle] file is typically placed somewhere on the filesystem that allows a higher level Maven build to pick it up and include it in e.g. a Jenkins plugin HPI file (so it can be loaded by the browser at runtime).
|
51 | 1. Pre-process a [LESS] fileset to a `.css` file that can be picked up by the top level Maven build and included in the e.g. a Jenkins plugin HPI file. See the Bundling Options section below.
|
52 |
|
53 | # Install
|
54 |
|
55 | ```
|
56 | npm install --save-dev @jenkins-cd/js-builder
|
57 | ```
|
58 |
|
59 | > This assumes you have [node.js] (minimum v4.0.0) installed on your local development environment.
|
60 |
|
61 | > Note this is only required if you intend developing [js-modules] compatible module bundles. Plugins using this should automatically handle all build aspects via maven (see later) i.e. __simple building of a plugin should require no machine level setup__.
|
62 |
|
63 | # General Usage
|
64 |
|
65 | Add a `gulpfile.js` (see [Gulp]) in the same folder as the `package.json`. Then use `js-builder` as follows:
|
66 |
|
67 | ```javascript
|
68 | var builder = require('@jenkins-cd/js-builder');
|
69 |
|
70 | builder.bundle('./src/main/js/myappbundle.js');
|
71 |
|
72 | ```
|
73 |
|
74 | After running the the `gulp` command from the command line, you will see an output something like the following.
|
75 |
|
76 | ```
|
77 | [17:16:33] Javascript bundle "myappbundle" will be available in Jenkins as adjunct "org.jenkins.ui.jsmodules.myappbundle".
|
78 | ```
|
79 |
|
80 | Or if run from a maven project where the `artifactId` is (e.g.) `jenkins-xyz-plugin`.
|
81 |
|
82 | ```
|
83 | [17:16:33] Javascript bundle "myappbundle" will be available in Jenkins as adjunct "org.jenkins.ui.jsmodules.jenkins_xyz_plugin.myappbundle".
|
84 | ```
|
85 |
|
86 | From this, you can deduce that the easiest way of using this JavaScript bundle in Jenkins is via the `<st:adjunct>` jelly tag.
|
87 |
|
88 | ```xml
|
89 | <st:adjunct includes="org.jenkins.ui.jsmodules.jenkins_xyz_plugin.myappbundle"/>
|
90 | ```
|
91 |
|
92 | The best place to learn how to use this utility as part of building Jenkins plugins is to see the
|
93 | [Sample Plugins](https://github.com/jenkinsci/js-samples) repository.
|
94 |
|
95 | # Predefined Gulp Tasks
|
96 |
|
97 | The following sections describe the available predefined [Gulp] tasks.
|
98 |
|
99 | > __Note__: If no task is specified (i.e. you just type `gulp` on its own), then the `bundle` and `test` tasks are auto-installed (i.e. auto-run) as the default tasks.
|
100 |
|
101 | ## 'bundle' Task
|
102 | Run the 'bundle' task. See detail on this in the <a href="#bundling">dedicated section titled "Bundling"</a> (below).
|
103 |
|
104 | ```
|
105 | gulp bundle
|
106 | ```
|
107 |
|
108 | ## 'test' Task
|
109 |
|
110 | Run tests. The default location for tests is the `spec` folder. The file names need to match the
|
111 | pattern "*-spec.js". The default location can be overridden by calling `builder.tests(<new-path>)`.
|
112 |
|
113 | ```
|
114 | gulp test
|
115 | ```
|
116 |
|
117 | > See [jenkins-js-test] for more on testing.
|
118 | > See <a href="#command-line-options">command line options</a> for `--skipTest` option.
|
119 | > See <a href="#command-line-options">command line options</a> for `--test` option (for running a single test spec).
|
120 |
|
121 | ## 'bundle:watch' Task
|
122 |
|
123 | Watch module source files (`index.js`, `./lib/**/*.js` and `./lib/**/*.hbs`) for change, auto-running the
|
124 | `bundle` task whenever changes are detected.
|
125 |
|
126 | Note that this task will not be run by default, so you need to specify it explicitly on the gulp command in
|
127 | order to run it e.g.
|
128 |
|
129 | ```
|
130 | gulp bundle:watch
|
131 | ```
|
132 |
|
133 | ## 'test:watch' Task
|
134 |
|
135 | Watch module source files changes (including test code) and rerun the tests e.g.
|
136 |
|
137 | ```
|
138 | gulp test:watch
|
139 | ```
|
140 |
|
141 | ## 'lint' Task
|
142 |
|
143 | Run linting - ESLint or JSHint. ESlint is the default if no `.eslintrc` or `.jshintrc` file is found
|
144 | (using [eslint-config-jenkins](https://www.npmjs.com/package/@jenkins-cd/eslint-config-jenkins)) in the working
|
145 | directory (`.eslintrc` is also searched for in parent directories).
|
146 |
|
147 | ```
|
148 | gulp lint
|
149 | ```
|
150 |
|
151 | > See <a href="#command-line-options">command line options</a> for `--skipLint`, `--continueOnLint` and `--fixLint` options.
|
152 |
|
153 | # Redefining one of the predefined Gulp tasks
|
154 |
|
155 | There are times when you need to break out and redefine one of the predefined gulp tasks (see previous section).
|
156 | To redefine a task, you simply call `defineTask` again e.g. to redefine the `test` task to use mocha:
|
157 |
|
158 | ```javascript
|
159 | builder.defineTask('test', function() {
|
160 | var mocha = require('gulp-mocha');
|
161 | var babel = require('babel-core/register');
|
162 |
|
163 | builder.gulp.src('src/test/js/*-spec.js')
|
164 | .pipe(mocha({
|
165 | compilers: {js: babel}
|
166 | })).on('error', function(e) {
|
167 | if (builder.isRetest()) {
|
168 | // ignore test failures if we are running test:watch.
|
169 | return;
|
170 | }
|
171 | throw e;
|
172 | });
|
173 | });
|
174 | ```
|
175 |
|
176 | # Bundling Options
|
177 |
|
178 | The following sections outline some options that can be specified on a `bundle` instance.
|
179 |
|
180 | ## Bundling CSS and LESS
|
181 |
|
182 | Note that bundling of __CSS__ or __LESS__ is also supported through a similar syntax e.g.
|
183 |
|
184 | ```javascript
|
185 | builder.bundle('src/main/css/bootstrap336/bootstrap.css');
|
186 | ```
|
187 |
|
188 | Or via [LESS]:
|
189 |
|
190 | ```javascript
|
191 | builder.bundle('src/main/css/bootstrap336/bootstrap_tweaked.less');
|
192 | ```
|
193 |
|
194 | The above commands will add all resources under `src/main/css/bootstrap336` to the plugin classpath, making
|
195 | them available as adjuncts e.g. using the bundled `bootstrap.css` referenced above would be as simple as
|
196 | adding the following to the relevant `.jelly` file (check the build output for the correct adjunct):
|
197 |
|
198 | ```xml
|
199 | <st:adjunct includes="org.jenkins.ui.jsmodules.bootstrap336.bootstrap"/>
|
200 | ```
|
201 |
|
202 | ## Generating a bundle to a specific directory
|
203 |
|
204 | By default, the bundle command will output the bundle to the `target/classes/org/jenkins/ui/jsmodules`, making
|
205 | the bundle loadable in Jenkins as an adjunct. See the <a href="#general-usage">General Usage</a> section earlier
|
206 | in this document.
|
207 |
|
208 | Outputting the generated bundle to somewhere else is just a matter of specifying it on the `bundle` instance
|
209 | via the `inDir` function e.g.
|
210 |
|
211 | ```javascript
|
212 | bundleSpec.inDir('<path-to-dir>');
|
213 | ```
|
214 |
|
215 | ## Minify bundle JavaScript
|
216 |
|
217 | This can be done by calling `minify` on `js-builder`:
|
218 |
|
219 | ```javascript
|
220 | bundleSpec.minify();
|
221 | ```
|
222 |
|
223 | Or, by passing `--minify` on the command line. This will result in the minification of all generated bundles.
|
224 |
|
225 | ```sh
|
226 | $ gulp --minify
|
227 | ```
|
228 |
|
229 | ## onPreBundle listeners
|
230 |
|
231 | There are times when you will need access to the underlying [Browserify] `bundler` just before the
|
232 | bundling process is executed (e.g. for adding transforms etc).
|
233 |
|
234 | To do this, you call the `onPreBundle` function. This function takes a `listener` function as an argument.
|
235 | This `listener` function, when called, receives the `bundle` as `this` and the `bundler` as the only argument to
|
236 | the supplied `listener`.
|
237 |
|
238 | ```javascript
|
239 | var builder = require('@jenkins-cd/js-builder');
|
240 |
|
241 | builder.onPreBundle(function(bundler) {
|
242 | var bundle = this;
|
243 |
|
244 | console.log('Adding the funky transform to bundler for bundle: ' + bundle.as);
|
245 | bundler.transform(myFunkyTransform);
|
246 | });
|
247 | ```
|
248 |
|
249 | # Setting 'src' and 'test' (spec) paths
|
250 | The default paths depend on whether or not running in a maven project.
|
251 |
|
252 | For a maven project, the default source and test/spec paths are:
|
253 |
|
254 | * __src__: `./src/main/js` and `./src/main/less` (used primarily by the `bundle:watch` task, watching these folders for source changes)
|
255 | * __test__: `./src/test/js` (used by the `test` task)
|
256 |
|
257 | Otherwise, they are:
|
258 |
|
259 | * __src__: `./js` and `./less` (used primarily by the `bundle:watch` task, watching these folders for source changes)
|
260 | * __test__: `./spec` (used by the `test` task)
|
261 |
|
262 |
|
263 |
|
264 | Changing these defaults is done through the `builder` instance e.g.:
|
265 |
|
266 | ```javascript
|
267 | var builder = require('@jenkins-cd/js-builder');
|
268 |
|
269 | builder.src('src/main/js');
|
270 | builder.tests('src/test/js');
|
271 | ```
|
272 |
|
273 | You can also specify an array of `src` folders e.g.
|
274 |
|
275 | ```javascript
|
276 | builder.src(['src/main/js', 'src/main/less']);
|
277 | ```
|
278 |
|
279 | # Command line options
|
280 |
|
281 | A number of `js-builder` options can be specified on the command line. If you are looking for
|
282 |
|
283 |
|
284 | ## `--h` (or `--help`)
|
285 |
|
286 | Get a link to this documentation.
|
287 |
|
288 | ```sh
|
289 | $ gulp --h
|
290 | ```
|
291 |
|
292 | ## `--minify`
|
293 |
|
294 | Passing `--minify` on the command line will result in the minification of all generated bundles.
|
295 |
|
296 | ```sh
|
297 | $ gulp --minify
|
298 | ```
|
299 |
|
300 | ## `--test`
|
301 |
|
302 | Run a single test.
|
303 |
|
304 | ```sh
|
305 | $ gulp --test configeditor
|
306 | ```
|
307 |
|
308 | The above example would run test specs matching the `**/configeditor*-spec.js` pattern (in the test source directory).
|
309 |
|
310 | ## Skip options: `--skipTest`, `--skipLint`, `--skipBundle`
|
311 |
|
312 | Skip one or more of the tasks/phases e.g.
|
313 |
|
314 | ```sh
|
315 | $ gulp --skipTest --skipLint
|
316 | ```
|
317 |
|
318 | ## Lint options: `--skipLint`, `--continueOnLint`, `--fixLint`
|
319 |
|
320 | Many of the more irritating formatting rule errors/warnings can be fixed automatically by running
|
321 | with the `--fixLint` option, making them a little less irritating e.g.
|
322 |
|
323 | ```sh
|
324 | $ gulp --fixLint
|
325 | ```
|
326 |
|
327 | Or if you are just running the `lint` task on it's own (explicitly):
|
328 |
|
329 | ```sh
|
330 | $ gulp lint --fixLint
|
331 | ```
|
332 |
|
333 | Alternatively, if you wish to run `lint` and see all of the lint errors, but not fail the build:
|
334 |
|
335 | ```sh
|
336 | $ gulp --continueOnLint
|
337 | ```
|
338 |
|
339 | And to skip linting completely:
|
340 |
|
341 | ```sh
|
342 | $ gulp --skipLint
|
343 | ```
|
344 |
|
345 | # Maven Integration
|
346 | Hooking a [Gulp] based build into a Maven build involves adding a few Maven `<profile>`s to the
|
347 | Maven project's `pom.xml`. For Jenkins plugins, the easiest way to get this integration is to simply
|
348 | have the plugin `pom.xml` depend on the Jenkins [plugin-pom]. For other project types, you'll need
|
349 | to copy those profiles locally (see [plugin-pom]).
|
350 |
|
351 | These integrations hook the [Gulp] build into the maven build lifecycles. A few `mvn` build
|
352 | switches are supported, as described in the following sections.
|
353 |
|
354 | ## `-DcleanNode`
|
355 |
|
356 | Cleans out the local node and NPM artifacts and resource (including the `node_modules` folder).
|
357 |
|
358 | ```
|
359 | $ mvn clean -DcleanNode
|
360 | ```
|
361 |
|
362 | ## `-DskipTests`
|
363 |
|
364 | This switch is a standard `mvn` switch and is honoured by the profiles defined in the [plugin-pom].
|
365 |
|
366 | ```
|
367 | $ mvn clean -DskipTests
|
368 | ```
|
369 |
|
370 | `-DskipTests` also skips linting. See `-DskipLint`
|
371 |
|
372 | ## `-DskipLint`
|
373 |
|
374 | Skip linting.
|
375 |
|
376 | ```
|
377 | $ mvn clean -DskipLint
|
378 | ```
|
379 |
|
380 | [bundle]: https://github.com/jenkinsci/js-modules/blob/master/FAQs.md#what-is-the-difference-between-a-module-and-a-bundle
|
381 | [js-modules]: https://github.com/jenkinsci/js-modules
|
382 | [js-builder]: https://github.com/jenkinsci/js-builder
|
383 | [jenkins-js-test]: https://github.com/jenkinsci/js-test
|
384 | [NPM]: https://www.npmjs.com/
|
385 | [CommonJS]: http://www.commonjs.org/
|
386 | [node.js]: https://nodejs.org/en/
|
387 | [Browserify]: http://browserify.org/
|
388 | [Gulp]: http://gulpjs.com/
|
389 | [frontend-maven-plugin]: https://github.com/eirslett/frontend-maven-plugin
|
390 | [intra-bundle]: https://github.com/jenkinsci/js-modules/blob/master/FAQs.md#what-does-module-loading-mean
|
391 | [inter-bundle]: https://github.com/jenkinsci/js-modules/blob/master/FAQs.md#what-does-module-loading-mean
|
392 | [io.js]: https://iojs.org
|
393 | [Framework lib]: https://github.com/jenkinsci/js-libs
|
394 | [LESS]: http://lesscss.org/
|
395 | [Handlebars]: http://handlebarsjs.com/
|
396 | [Jasmine]: http://jasmine.github.io/
|
397 | [Moment.js]: http://momentjs.com/
|
398 | [plugin-pom]: https://github.com/jenkinsci/plugin-pom
|