UNPKG

14 kBMarkdownView Raw
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
30The following diagram illustrates the basic flow (and components used) in the process of building a [CommonJS] module [bundle].
31It 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
39The 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
491. Runs [Jasmine] tests/specs and produce a JUnit report that can be picked up by a top level Maven build.
501. 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).
511. 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```
56npm 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
65Add a `gulpfile.js` (see [Gulp]) in the same folder as the `package.json`. Then use `js-builder` as follows:
66
67```javascript
68var builder = require('@jenkins-cd/js-builder');
69
70builder.bundle('./src/main/js/myappbundle.js');
71
72```
73
74After 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
80Or 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
86From 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
92The 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
97The 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
102Run the 'bundle' task. See detail on this in the <a href="#bundling">dedicated section titled "Bundling"</a> (below).
103
104```
105gulp bundle
106```
107
108## 'test' Task
109
110Run tests. The default location for tests is the `spec` folder. The file names need to match the
111pattern "*-spec.js". The default location can be overridden by calling `builder.tests(<new-path>)`.
112
113```
114gulp 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
123Watch module source files (`index.js`, `./lib/**/*.js` and `./lib/**/*.hbs`) for change, auto-running the
124`bundle` task whenever changes are detected.
125
126Note that this task will not be run by default, so you need to specify it explicitly on the gulp command in
127order to run it e.g.
128
129```
130gulp bundle:watch
131```
132
133## 'test:watch' Task
134
135Watch module source files changes (including test code) and rerun the tests e.g.
136
137```
138gulp test:watch
139```
140
141## 'lint' Task
142
143Run 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
145directory (`.eslintrc` is also searched for in parent directories).
146
147```
148gulp 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
155There are times when you need to break out and redefine one of the predefined gulp tasks (see previous section).
156To redefine a task, you simply call `defineTask` again e.g. to redefine the `test` task to use mocha:
157
158```javascript
159builder.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
178The following sections outline some options that can be specified on a `bundle` instance.
179
180## Bundling CSS and LESS
181
182Note that bundling of __CSS__ or __LESS__ is also supported through a similar syntax e.g.
183
184```javascript
185builder.bundle('src/main/css/bootstrap336/bootstrap.css');
186```
187
188Or via [LESS]:
189
190```javascript
191builder.bundle('src/main/css/bootstrap336/bootstrap_tweaked.less');
192```
193
194The above commands will add all resources under `src/main/css/bootstrap336` to the plugin classpath, making
195them available as adjuncts e.g. using the bundled `bootstrap.css` referenced above would be as simple as
196adding 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
204By default, the bundle command will output the bundle to the `target/classes/org/jenkins/ui/jsmodules`, making
205the bundle loadable in Jenkins as an adjunct. See the <a href="#general-usage">General Usage</a> section earlier
206in this document.
207
208Outputting the generated bundle to somewhere else is just a matter of specifying it on the `bundle` instance
209via the `inDir` function e.g.
210
211```javascript
212bundleSpec.inDir('<path-to-dir>');
213```
214
215## Minify bundle JavaScript
216
217This can be done by calling `minify` on `js-builder`:
218
219```javascript
220bundleSpec.minify();
221```
222
223Or, 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
231There are times when you will need access to the underlying [Browserify] `bundler` just before the
232bundling process is executed (e.g. for adding transforms etc).
233
234To do this, you call the `onPreBundle` function. This function takes a `listener` function as an argument.
235This `listener` function, when called, receives the `bundle` as `this` and the `bundler` as the only argument to
236the supplied `listener`.
237
238```javascript
239var builder = require('@jenkins-cd/js-builder');
240
241builder.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
250The default paths depend on whether or not running in a maven project.
251
252For 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
257Otherwise, 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
264Changing these defaults is done through the `builder` instance e.g.:
265
266```javascript
267var builder = require('@jenkins-cd/js-builder');
268
269builder.src('src/main/js');
270builder.tests('src/test/js');
271```
272
273You can also specify an array of `src` folders e.g.
274
275```javascript
276builder.src(['src/main/js', 'src/main/less']);
277```
278
279# Command line options
280
281A number of `js-builder` options can be specified on the command line. If you are looking for
282
283
284## `--h` (or `--help`)
285
286Get a link to this documentation.
287
288```sh
289$ gulp --h
290```
291
292## `--minify`
293
294Passing `--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
302Run a single test.
303
304```sh
305$ gulp --test configeditor
306```
307
308The 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
312Skip 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
320Many of the more irritating formatting rule errors/warnings can be fixed automatically by running
321with the `--fixLint` option, making them a little less irritating e.g.
322
323```sh
324$ gulp --fixLint
325```
326
327Or if you are just running the `lint` task on it's own (explicitly):
328
329```sh
330$ gulp lint --fixLint
331```
332
333Alternatively, 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
339And to skip linting completely:
340
341```sh
342$ gulp --skipLint
343```
344
345# Maven Integration
346Hooking a [Gulp] based build into a Maven build involves adding a few Maven `<profile>`s to the
347Maven project's `pom.xml`. For Jenkins plugins, the easiest way to get this integration is to simply
348have the plugin `pom.xml` depend on the Jenkins [plugin-pom]. For other project types, you'll need
349to copy those profiles locally (see [plugin-pom]).
350
351These integrations hook the [Gulp] build into the maven build lifecycles. A few `mvn` build
352switches are supported, as described in the following sections.
353
354## `-DcleanNode`
355
356Cleans 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
364This 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
374Skip 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