forked from wakaleo/jenkins-the-definitive-guide-book
-
Notifications
You must be signed in to change notification settings - Fork 0
/
ch10.xml
1974 lines (1967 loc) · 136 KB
/
ch10.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<?xml version="1.0"?>
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
<chapter id="chapter-advanced-builds">
<title>Advanced Builds</title>
<sect1 id="sect-advanced-builds-introduction">
<title>Introduction</title>
<para>In this chapter, we will look at some more advanced build job
setups. We will discuss parameterized builds, which allows Jenkins to
prompt the user for additional parameters that will be passed into the
build job, and multiconfiguration build jobs, which let you run a single
build job though a large number of variations. We will look at how to run
build jobs in parallel, and wait for the outcome of one or more build jobs
before continuing. And we will see how to implement build promotion
strategies and build pipelines so that Jenkins can be used not only as a
build server, but also as a deployment server.</para>
</sect1>
<sect1 id="sect-advanced-builds-parameterized">
<title>Parameterized Build Jobs</title>
<para>Parameterized<indexterm class="startofrange" id="ch10-param1" significance="normal"><primary>build jobs</primary><secondary>parameterized</secondary></indexterm><indexterm class="startofrange" id="ch10-param2" significance="normal"><primary>parameterized build jobs</primary></indexterm> builds are a powerful concept that enable you to add
another dimension to your build jobs.</para>
<para>The<indexterm id="I_indexterm10_d1e13891" significance="normal"><primary>plugins</primary><secondary>Parameterized Build</secondary></indexterm><indexterm id="I_indexterm10_d1e13896" significance="normal"><primary>Parameterized Build plugin</primary></indexterm> Parameterized Build plugin lets you configure parameters
for your build job, that can be either entered by the user when the build
job is triggered, or (as we will see later) from another build job.</para>
<para>For example, you might have a deployment build job, where you want
to choose the target environment in a drop-down list when you start the
build job. Or you may want to specify the version of the application you
want to deploy. Or, when running a build job involving web tests, you
might want to specify the browser to run your Selenium or WebDriver tests
in. You can even upload a file to be used by the build job.</para>
<para>Note that it is the job of the build script to analyze and process
the parameter values correctly—Jenkins simply provides a user interface
for users to enter values for the parameters, and passes these parameters
to the build script.</para>
<sect2>
<title>Creating a Parameterized Build Job</title>
<para>You<indexterm id="I_indexterm10_d1e13909" significance="normal"><primary>build jobs</primary><secondary>parameterized</secondary><tertiary>creating</tertiary></indexterm><indexterm id="I_indexterm10_d1e13916" significance="normal"><primary>parameterized build jobs</primary><secondary>creating</secondary></indexterm> install the Parameterized Build plugin as usual, via the
Plugin Manager screen. Once you have done this, configuring a
parameterized build job is straightforward. Just tick the “This build is
parameterized” option and click Add Parameter to add a new build job
parameter (see <xref linkend="fig-hudson-parameterized-build"/>). You
can add parameters to any sort of build, and you can add as many
parameters as you want for a given build job.</para>
<figure float="none" id="fig-hudson-parameterized-build">
<title>Creating a parameterized build job</title>
<mediaobject id="I_mediaobject10_d1e13927">
<imageobject role="print">
<imagedata fileref="figs/print/jtdg_1001.pdf" format="PDF" scale="90"/>
</imageobject>
<imageobject role="web">
<imagedata fileref="figs/web/jtdg_1001.png" format="PNG" scale="90"/>
</imageobject>
</mediaobject>
</figure>
<para>To add a parameter to your build job, just pick the parameter type
in the drop-down list. This will let you configure the details of your
parameter (see <xref linkend="fig-hudson-string-build-parameter"/>).
You can choose from several different <indexterm id="I_indexterm10_d1e13936" significance="normal"><primary>parameterized build jobs</primary><secondary>types of parameters</secondary></indexterm><indexterm id="I_indexterm10_d1e13941" significance="normal"><primary>build jobs</primary><secondary>parameterized</secondary><tertiary>types of parameters</tertiary></indexterm><indexterm id="I_indexterm10_d1e13948" significance="normal"><primary>String parameters</primary></indexterm>parameter types, such as Strings, Booleans, and drop-down
lists. Depending on the type you choose, you will have to enter slightly
different configuration values, but the basic process is identical. All
parameter types, with the exception of the File parameter, have a name
and a description, and most often a default value.</para>
<para>In <xref linkend="fig-hudson-enter-string-parameter"/>, for
example, we are adding a parameter called <literal moreinfo="none">version</literal> to
a deployment build job. The default value (<literal moreinfo="none">RELEASE</literal>)
will be initially displayed when Jenkins prompts the user for this
parameter, so if the user doesn’t change anything, this value will be
used.</para>
<figure float="0" id="fig-hudson-string-build-parameter">
<title>Adding a parameter to the build job</title>
<mediaobject id="I_mediaobject10_d1e13965">
<imageobject role="print">
<imagedata fileref="figs/print/jtdg_1002.pdf" format="PDF"/>
</imageobject>
<imageobject role="web">
<imagedata fileref="figs/web/jtdg_1002.png" format="PNG"/>
</imageobject>
</mediaobject>
</figure>
<para>When the user starts a parameterized build job (parameterized
build jobs are very often started manually), Jenkins will propose a page
where the user can enter values for each of the build job’s parameters
(see <xref linkend="fig-hudson-enter-string-parameter"/>).</para>
<figure float="0" id="fig-hudson-enter-string-parameter">
<title>Adding a parameter to the build job</title>
<mediaobject id="I_mediaobject10_d1e13977">
<imageobject role="print">
<imagedata fileref="figs/print/jtdg_1003.pdf" format="PDF"/>
</imageobject>
<imageobject role="web">
<imagedata fileref="figs/web/jtdg_1003.png" format="PNG"/>
</imageobject>
</mediaobject>
</figure>
</sect2>
<sect2>
<title>Adapting Your Builds to Work with Parameterized Build
Scripts</title>
<para>Once<indexterm class="startofrange" id="ch10-script" significance="normal"><primary>scripts</primary><secondary>parameterized</secondary></indexterm><indexterm class="startofrange" id="ch10-script2" significance="normal"><primary>parameterized build jobs</primary><secondary>build scripts for</secondary></indexterm><indexterm class="startofrange" id="ch10-script3" significance="normal"><primary>build jobs</primary><secondary>parameterized</secondary><tertiary>build scripts for</tertiary></indexterm><indexterm id="I_indexterm10_d1e14004" significance="normal"><primary>build scripts</primary><see>scripts</see></indexterm> you have added a parameter, you need to configure your
build scripts to use it. Choosing the parameter name well is important
here, as this is also the name of the variable that Jenkins will pass
through as an <indexterm id="I_indexterm10_d1e14010" significance="normal"><primary>environment variables</primary><secondary>build parameters as</secondary></indexterm>environment variable when it runs the build job. To
illustrate this, consider the very basic build job configuration in
<xref linkend="fig-hudson-parameterized-shell"/>, where we are simply
echoing the build parameter back out to the console. Note that, to make
the environment variables more portable across operating systems, it is
good practice to put them all in upper case.</para>
<figure float="0" id="fig-hudson-parameterized-shell">
<title>Demonstrating a build parameter</title>
<mediaobject id="I_mediaobject10_d1e14021">
<imageobject role="print">
<imagedata fileref="figs/print/jtdg_1004.pdf" format="PDF"/>
</imageobject>
<imageobject role="web">
<imagedata fileref="figs/web/jtdg_1004.png" format="PNG"/>
</imageobject>
</mediaobject>
</figure>
<para>When we run this, we get a console output along the following
lines:</para>
<screen format="linespecific">Started by user anonymous
Building on master
[workspace] $ /bin/sh -xe /var/folders/y+/y+a+wZ-jG6WKHEm9KwnSvE+++TI/-Tmp-/
jenkins5862957776458050998.sh
<userinput moreinfo="none">+ echo Version=1.2.3</userinput>
<userinput moreinfo="none">Version=1.2.3</userinput>
Notifying upstream projects of job completion
Finished: SUCCESS</screen>
<para>You can also use these environment variables from within your
build scripts. For example, in an Ant or Maven build, you can use the
special <literal moreinfo="none">env</literal> property to access the current
environment variables:</para>
<programlisting id="I_programlisting10_d1e14041" format="linespecific"><target name="printversion">
<property environment="env" />
<echo message="${env.VERSION}"/>
</target></programlisting>
<para>Another option is to pass the <indexterm id="I_indexterm10_d1e14045" significance="normal"><primary>properties</primary><secondary>build parameters as</secondary></indexterm>parameter into the build script as a property value. The
following is a more involved example from a Maven POM file. In this
example, Maven is configured to deploy a specific WAR file. We provide
the version of the WAR file to be deployed in the
<literal moreinfo="none">target.version</literal> property, which is used in the
dependency declaration, as shown below:</para>
<programlisting id="I_programlisting10_d1e14054" format="linespecific"> ...
<dependencies>
<dependency>
<groupId>com.wakaleo.gameoflife</groupId>
<artifactId>gameoflife-web</artifactId>
<type>war</type>
<version><userinput moreinfo="none">${target.version}</userinput></version>
</dependency>
</dependencies>
<properties>
<target.version>RELEASE</target.version>
...
</properties></programlisting>
<para>When we invoke Maven, we pass in the parameter as one of the build
properties (see <xref linkend="fig-hudson-inject-parameter-maven"/>).
We can then use a tool like Cargo to do the actual deployment—Maven will
download the requested version of the WAR file from the local Enterprise
Repository Manager, and deploy it to an application server.</para>
<figure float="none" id="fig-hudson-inject-parameter-maven">
<title>Adding a parameter to a Maven build job</title>
<mediaobject id="I_mediaobject10_d1e14066">
<imageobject role="print">
<imagedata fileref="figs/print/jtdg_1005.pdf" format="PDF"/>
</imageobject>
<imageobject role="web">
<imagedata fileref="figs/web/jtdg_1005.png" format="PNG"/>
</imageobject>
</mediaobject>
</figure>
<para>That, in a nutshell, is how you can integrate build job parameters
into your build. In addition to plain old String parameters, however,
there are a few more sophisticated parameter types, that we will look at
in the following <indexterm id="I_indexterm10_d1e14074" class="endofrange" startref="ch10-script" significance="normal"><primary/></indexterm><indexterm id="I_indexterm10_d1e14076" class="endofrange" startref="ch10-script2" significance="normal"><primary/></indexterm><indexterm id="I_indexterm10_d1e14078" class="endofrange" startref="ch10-script3" significance="normal"><primary/></indexterm>paragraphs (see <xref linkend="fig-hudson-build-parameter-types"/>).</para>
<figure float="0" id="fig-hudson-build-parameter-types">
<title>Many different types of parameters are available</title>
<mediaobject id="I_mediaobject10_d1e14086">
<imageobject role="print">
<imagedata fileref="figs/print/jtdg_1006.pdf" format="PDF"/>
</imageobject>
<imageobject role="web">
<imagedata fileref="figs/web/jtdg_1006.png" format="PNG"/>
</imageobject>
</mediaobject>
</figure>
</sect2>
<sect2>
<title>More Advanced Parameter Types</title>
<para><firstterm>Password parameters</firstterm> <indexterm id="I_indexterm10_d1e14098" significance="normal"><primary>Password parameters</primary></indexterm><indexterm class="startofrange" id="ch10-type1" significance="normal"><primary>parameterized build jobs</primary><secondary>types of parameters</secondary></indexterm><indexterm class="startofrange" id="ch10-type2" significance="normal"><primary>build jobs</primary><secondary>parameterized</secondary><tertiary>types of parameters</tertiary></indexterm>are, as you would expect, very similar to String
parameters, except that they are displayed as a password field.</para>
<para>There are many cases where you which to present a limited set of
parameter options. In a deployment build, you might want to let the user
choose one of a number of target servers. Or you may want to present a
list of supported browsers for a suite of acceptance tests.
<firstterm>Choice parameters</firstterm> let you define a set of values
that will be displayed as a drop-down list (see <xref linkend="fig-hudson-build-parameter-choice"/>). You need to provide a
list of possible values, one per line, starting with the default
value.</para>
<figure float="none" id="fig-hudson-build-parameter-choice">
<title>Configuring a Choice parameter</title>
<mediaobject id="I_mediaobject10_d1e14124">
<imageobject role="print">
<imagedata fileref="figs/print/jtdg_1007.pdf" format="PDF"/>
</imageobject>
<imageobject role="web">
<imagedata fileref="figs/web/jtdg_1007.png" format="PNG"/>
</imageobject>
</mediaobject>
</figure>
<para><firstterm>Boolean parameters</firstterm> <indexterm id="I_indexterm10_d1e14133" significance="normal"><primary>Boolean parameters</primary></indexterm>are, as you would expect, parameters that take a value of
<literal moreinfo="none">true</literal> or <literal moreinfo="none">false</literal>. They are presented
as checkboxes.</para>
<para>Two more exotic parameter types, which behave a little differently
to the others, are <firstterm>Run parameters</firstterm> and
<firstterm>File parameters</firstterm>.</para>
<para>Run parameters <indexterm id="I_indexterm10_d1e14153" significance="normal"><primary>Run parameters</primary></indexterm><indexterm id="I_indexterm10_d1e14156" significance="normal"><primary>build jobs</primary><secondary>run numbers for, as parameters</secondary></indexterm>let you select a particular run (or build) of a given
build job (see <xref linkend="fig-hudson-build-parameter-run-param"/>).
The user picks from a list of build run numbers. The URL of the
corresponding build run is stored in the specified parameter.</para>
<figure float="none" id="fig-hudson-build-parameter-run-param">
<title>Configuring a Run parameter</title>
<mediaobject id="I_mediaobject10_d1e14167">
<imageobject role="print">
<imagedata fileref="figs/print/jtdg_1008.pdf" format="PDF"/>
</imageobject>
<imageobject role="web">
<imagedata fileref="figs/web/jtdg_1008.png" format="PNG"/>
</imageobject>
</mediaobject>
</figure>
<para>The URL (which will look something like
<emphasis>http://jenkins.myorg.com/job/game-of-life/197/</emphasis>) can
be used to obtain information or artifacts from that build run. For
example, you could obtain the JAR or WAR file archived in a previous
build and run further tests with this particular binary in a separate
build job. For example, to access the WAR file of a previous build in a
multimodule Maven project, the URL would look something like
this:</para>
<programlisting id="I_programlisting10_d1e14177" format="linespecific">http://buildserver/job/game-of-life/197/artifact/gameoflife-web/target/
gameoflife.war</programlisting>
<para>So, using the parameter configured in <xref linkend="fig-hudson-build-parameter-run-param"/>, you could access this
WAR file using the following expression:</para>
<programlisting id="I_programlisting10_d1e14184" format="linespecific">${RELEASE_BUILD}gameoflife-web/target/gameoflife.war</programlisting>
<para>File parameters <indexterm id="I_indexterm10_d1e14188" significance="normal"><primary>File parameters</primary></indexterm>let you upload a file into the build job workspace, so
that it can then be used by the build script (see <xref linkend="fig-hudson-build-parameter-file"/>). Jenkins will store the
file into the specified location in the project workspace, where you can
access it in your build scripts. You can use the
<literal moreinfo="none">WORKSPACE</literal> variable to refer to the current Jenkins
workspace directory, so you could manipulate the file uploaded in <xref linkend="fig-hudson-build-parameter-file"/> by using the <indexterm id="I_indexterm10_d1e14199" class="endofrange" startref="ch10-type1" significance="normal"><primary/></indexterm><indexterm id="I_indexterm10_d1e14201" class="endofrange" startref="ch10-type2" significance="normal"><primary/></indexterm>expression
<literal moreinfo="none">${WORKSPACE}/deploy/app.war</literal>.</para>
<figure float="none" id="fig-hudson-build-parameter-file">
<title>Configuring a File parameter</title>
<mediaobject id="I_mediaobject10_d1e14211">
<imageobject role="print">
<imagedata fileref="figs/print/jtdg_1009.pdf" format="PDF"/>
</imageobject>
<imageobject role="web">
<imagedata fileref="figs/web/jtdg_1009.png" format="PNG"/>
</imageobject>
</mediaobject>
</figure>
</sect2>
<sect2 id="sect-build-from-svn-tag">
<title>Building from a Subversion Tag</title>
<para>The <indexterm class="startofrange" id="ch10-sub1" significance="normal"><primary>parameterized build jobs</primary><secondary>run against a Subversion tag</secondary></indexterm><indexterm class="startofrange" id="ch10-sub2" significance="normal"><primary>build jobs</primary><secondary>parameterized</secondary><tertiary>run against a Subversion tag</tertiary></indexterm><indexterm class="startofrange" id="ch10-sub3" significance="normal"><primary>Subversion</primary><secondary>tags, building against</secondary></indexterm>parameterized trigger has special support for Subversion,
allowing you to build against a specific Subversion tag. This is useful
if you want to run a release build using a tag generated by a previous
build job. For example, an upstream build job may tag a particular
revision. Alternatively, you might use the standard Maven release
process (see <xref linkend="jenkins-maven-releases"/>) to generate a
new release. In this case, a tag with the Maven release number will
automatically be generated in Subversion.</para>
<para>This approach is useful for projects that need to be partially or
entirely rebuilt before they can be deployed to a given platform. For
example, you may need to run the Ant or Maven build using different
properties or profiles for different platforms, so that
platform-specific configuration files can be embedded in the deployed
WAR or EAR files.</para>
<para>You can configure a Jenkins build to run against a selected tag by
using the “List Subversion Tag” parameter type (see <xref linkend="fig-jenkins-parameterized-subversion-tag"/>). You just need to
provide the Subversion repository URL pointing to the tags directory of
your project.</para>
<figure float="none" id="fig-jenkins-parameterized-subversion-tag">
<title>Adding a parameter to build from a Subversion tag</title>
<mediaobject id="I_mediaobject10_d1e14250">
<imageobject role="print">
<imagedata fileref="figs/print/jtdg_1010.pdf" format="PDF"/>
</imageobject>
<imageobject role="web">
<imagedata fileref="figs/web/jtdg_1010.png" format="PNG"/>
</imageobject>
</mediaobject>
</figure>
<para>When you run this build, Jenkins will propose a list of tags to
choose<indexterm id="I_indexterm10_d1e14257" class="endofrange" startref="ch10-sub1" significance="normal"><primary/></indexterm><indexterm id="I_indexterm10_d1e14259" class="endofrange" startref="ch10-sub2" significance="normal"><primary/></indexterm><indexterm id="I_indexterm10_d1e14261" class="endofrange" startref="ch10-sub3" significance="normal"><primary/></indexterm> from (see <xref linkend="fig-jenkins-parameterized-subversion"/>).</para>
<figure float="none" id="fig-jenkins-parameterized-subversion">
<title>Building from a Subversion tag</title>
<mediaobject id="I_mediaobject10_d1e14269">
<imageobject role="print">
<imagedata fileref="figs/print/jtdg_1011.pdf" format="PDF"/>
</imageobject>
<imageobject role="web">
<imagedata fileref="figs/web/jtdg_1011.png" format="PNG"/>
</imageobject>
</mediaobject>
</figure>
</sect2>
<sect2 id="sect-building-git-tag">
<title>Building from a Git Tag</title>
<para>Building<indexterm class="startofrange" id="ch10-git1" significance="normal"><primary>parameterized build jobs</primary><secondary>run against a Git tag</secondary></indexterm><indexterm class="startofrange" id="ch10-git2" significance="normal"><primary>build jobs</primary><secondary>parameterized</secondary><tertiary>run against a Git tag</tertiary></indexterm><indexterm class="startofrange" id="ch10-git3" significance="normal"><primary>Git</primary><secondary>tags, building against</secondary></indexterm> from a Git tag is not as simple as doing so from a
Subversion tag, though you can still use a parameter to indicate which
tag to use. Indeed, because of the very nature of Git, when Jenkins
obtains a copy of the source code from Git, it clones the Git
repository, including all of the tags. Once you have the latest version
of the repository on your Jenkins server, you can then proceed to
checkout a tagged version using <literal moreinfo="none">git checkout
<tagname></literal>.</para>
<para>To set this up in Jenkins, you first need to add a String
parameter to your build job (called <literal moreinfo="none">RELEASE</literal> in this
example—see <xref linkend="fig-jenkins-git-release-param"/>). Unlike
the Subversion support, there is no way to list the available Git tags
in a drop-down list, so users will need to know the name of the tag they
want to release.</para>
<figure float="none" id="fig-jenkins-git-release-param">
<title>Configuring a parameter for a Git tag</title>
<mediaobject id="I_mediaobject10_d1e14310">
<imageobject role="print">
<imagedata fileref="figs/print/jtdg_1012.pdf" format="PDF"/>
</imageobject>
<imageobject role="web">
<imagedata fileref="figs/web/jtdg_1012.png" format="PNG"/>
</imageobject>
</mediaobject>
</figure>
<para>Once you have added this parameter, you need to checkout the
corresponding tag once the repository has been cloned locally. So if you
have a freestyle build, the first build step would be a command-line
call to Git to check out the tag referenced by the
<literal moreinfo="none">RELEASE</literal> parameter (see <xref linkend="fig-jenkins-git-tag"/>). Of course a more portable way to do
this would be to write a simple Ant or Groovy script to do the same
thing in a more<indexterm id="I_indexterm10_d1e14322" class="endofrange" startref="ch10-git1" significance="normal"><primary/></indexterm><indexterm id="I_indexterm10_d1e14324" class="endofrange" startref="ch10-git2" significance="normal"><primary/></indexterm><indexterm id="I_indexterm10_d1e14326" class="endofrange" startref="ch10-git3" significance="normal"><primary/></indexterm> OS-neutral way.</para>
<figure float="0" id="fig-jenkins-git-tag">
<title>Building from a Git tag</title>
<mediaobject id="I_mediaobject10_d1e14332">
<imageobject role="print">
<imagedata fileref="figs/print/jtdg_1013.pdf" format="PDF"/>
</imageobject>
<imageobject role="web">
<imagedata fileref="figs/web/jtdg_1013.png" format="PNG"/>
</imageobject>
</mediaobject>
</figure>
</sect2>
<sect2>
<title>Starting a Parameterized Build Job Remotely</title>
<para>You <indexterm class="startofrange" id="ch10-remote1" significance="normal"><primary>parameterized build jobs</primary><secondary>starting remotely</secondary></indexterm><indexterm class="startofrange" id="ch10-remote2" significance="normal"><primary>build jobs</primary><secondary>parameterized</secondary><tertiary>starting remotely</tertiary></indexterm>can also start a parameterized build job remotely, by
invoking the URL of the build job. The typical form of a parameterized
build job URL is illustrated here:</para>
<programlisting id="I_programlisting10_d1e14355" format="linespecific">http://jenkins.acme.org/job/myjob/buildWithParameters?PARAMETER=Value</programlisting>
<para>So, in the example shown above, you could trigger a build like
this:</para>
<programlisting id="I_programlisting10_d1e14359" format="linespecific">http://jenkins.acme.org/job/parameterized-build/buildWithParameters?VERSION=1.2.3</programlisting>
<para>When you use a URL to start a build job in this way, remember that
the parameter names are case-sensitive, and that the values need to be
escaped (just like any other HTTP parameter). And if you are using a Run
parameter, you need to provide the name of the build job
<emphasis>and</emphasis> the run number (e.g.,
<literal moreinfo="none">game-of-life#197</literal>) and not just the run<indexterm id="I_indexterm10_d1e14369" class="endofrange" startref="ch10-remote1" significance="normal"><primary/></indexterm><indexterm id="I_indexterm10_d1e14371" class="endofrange" startref="ch10-remote2" significance="normal"><primary/></indexterm> <phrase role="keep-together">number</phrase>.</para>
</sect2>
<sect2>
<title>Parameterized Build Job History</title>
<para>Finally, <indexterm id="I_indexterm10_d1e14383" significance="normal"><primary>parameterized build jobs</primary><secondary>history of</secondary></indexterm><indexterm id="I_indexterm10_d1e14388" significance="normal"><primary>build jobs</primary><secondary>parameterized</secondary><tertiary>history of</tertiary></indexterm><indexterm id="I_indexterm10_d1e14395" significance="normal"><primary>build history</primary><secondary>parameterized</secondary></indexterm>it is indispensable to know what parameters were used to
run a particular parameterized build. For example, in an automated
deployment build job, it is useful to know exactly what version was
actually deployed. Fortunately, Jenkins stores these values in the build
<indexterm id="I_indexterm10_d1e14401" class="endofrange" startref="ch10-param1" significance="normal"><primary/></indexterm><indexterm id="I_indexterm10_d1e14403" class="endofrange" startref="ch10-param2" significance="normal"><primary/></indexterm>history (see <xref linkend="fig-hudson-build-parameter-history"/>), so you can always go
back and take a look.</para>
<figure float="none" id="fig-hudson-build-parameter-history">
<title>Jenkins stores what parameter values where used for each
build</title>
<mediaobject id="I_mediaobject10_d1e14411">
<imageobject role="print">
<imagedata fileref="figs/print/jtdg_1014.pdf" format="PDF"/>
</imageobject>
<imageobject role="web">
<imagedata fileref="figs/web/jtdg_1014.png" format="PNG"/>
</imageobject>
</mediaobject>
</figure>
</sect2>
</sect1>
<sect1 id="sect-advanced-builds-triggers">
<title>Parameterized Triggers</title>
<para>When <indexterm class="startofrange" id="ch10-trig1" significance="normal"><primary>parameterized triggers</primary></indexterm><indexterm class="startofrange" id="ch10-trig2" significance="normal"><primary>build triggers</primary><secondary>parameterized</secondary></indexterm>you trigger another build job from within a parameterized
build job, it is often useful to be able to pass the parameters of the
current build job to the new one. Suppose, for example, that you have an
application that needs to be tested against several different databases.
As we have seen, you could do this by setting up a parameterized build job
that accepts the target database as a parameter. You may want to kick of a
series of builds, all of which will need this parameter.</para>
<para>If you try to do this using the conventional “Build other projects”
option in the Post-Build Actions section, it won’t work. In fact, you
can’t trigger a parameterized build in this way.</para>
<para>However, <indexterm id="I_indexterm10_d1e14434" significance="normal"><primary>plugins</primary><secondary>Parameterized Trigger</secondary></indexterm><indexterm id="I_indexterm10_d1e14439" significance="normal"><primary>Parameterized Trigger plugin</primary></indexterm>you can do this using the Jenkins Parameterized Trigger
plugin. This plugin lets you configure your build jobs to both trigger
parameterized builds, and to pass arbitrary parameters to these
builds.</para>
<para>Once you install this plugin, you will find the option of
“Triggering parameterized builds on other projects” in your build job
configuration page (see <xref linkend="fig-hudson-build-parameters-trigger"/>). This lets you start
another build job in a number of ways. In particular, it lets you kick off
a subsequent build job, passing the current parameters to this new build
job, which is impossible to do with a normal triggered build. The best way
to see how this works is through an example.</para>
<para>In <xref linkend="fig-hudson-build-parameters-unit-test"/> we have
an initial build job. This build job takes a single parameter,
<literal moreinfo="none">DATABASE</literal>, which specifies the database to be used for
the tests. As we have seen, the user will be prompted to enter this value
whenever the build is started.</para>
<figure float="0" id="fig-hudson-build-parameters-unit-test">
<title>Jenkins stores what parameter values where used for each
build</title>
<mediaobject id="I_mediaobject10_d1e14457">
<imageobject role="print">
<imagedata fileref="figs/print/jtdg_1015.pdf" format="PDF"/>
</imageobject>
<imageobject role="web">
<imagedata fileref="figs/web/jtdg_1015.png" format="PNG"/>
</imageobject>
</mediaobject>
</figure>
<para>Now suppose we want to trigger a second build job to run more
comprehensive integration tests once this first build job has finished.
However we need it to run the tests against the same database. We can do
this by setting up a parameterized trigger to start this second build job
(see <xref linkend="fig-hudson-build-parameters-trigger"/>).</para>
<figure float="0" id="fig-hudson-build-parameters-trigger">
<title>Adding a parameterized trigger to a build job</title>
<mediaobject id="I_mediaobject10_d1e14469">
<imageobject role="print">
<imagedata fileref="figs/print/jtdg_1016.pdf" format="PDF"/>
</imageobject>
<imageobject role="web">
<imagedata fileref="figs/web/jtdg_1016.png" format="PNG"/>
</imageobject>
</mediaobject>
</figure>
<para>In this case, we are simple passing through the current build
parameters. This second build job will automatically be started after the
first one, with the <literal moreinfo="none">DATABASE</literal> parameter value provided
by the user. You can also fine-tune the triggering policy, by telling
Jenkins when the build should be triggered. Typically, you would only
trigger a downstream build after your build has completed successfully,
but with the Parameterized Trigger plugin you can also configure builds to
be triggered even if the build is unstable, only when the build fails or
ask for it to be triggered no matter what the outcome of the first build.
You can even set up multiple triggers for the same build job.</para>
<para>Naturally, the build job that you trigger must be a parameterized
build job (as illustrated in <xref linkend="fig-hudson-build-parameters-integration-test"/>), and you must
pass through all of the parameters it requires.</para>
<figure float="0" id="fig-hudson-build-parameters-integration-test">
<title>The build job you trigger must also be a parameterized build
job</title>
<mediaobject id="I_mediaobject10_d1e14487">
<imageobject role="print">
<imagedata fileref="figs/print/jtdg_1017.pdf" format="PDF"/>
</imageobject>
<imageobject role="web">
<imagedata fileref="figs/web/jtdg_1017.png" format="PNG"/>
</imageobject>
</mediaobject>
</figure>
<para>This feature actually has much broader applications than simply
passing through the current build parameters. You can also trigger a
parameterized build job with an arbitrary set of parameters, or use a
combination of parameters that were passed to the current build, and your
own additional ones. Or, if you have a lot of parameters, you can load
them from a properties file. In <xref linkend="fig-hudson-build-parameters-deploy-trigger"/>, we are passing
both the current build parameters (the <literal moreinfo="none">DATABASE</literal>
variable in this case), and an additional parameter <indexterm id="I_indexterm10_d1e14499" class="endofrange" startref="ch10-trig1" significance="normal"><primary/></indexterm><indexterm id="I_indexterm10_d1e14501" class="endofrange" startref="ch10-trig2" significance="normal"><primary/></indexterm>called <literal moreinfo="none">TARGET_PLATFORM</literal>.</para>
<figure float="0" id="fig-hudson-build-parameters-deploy-trigger">
<title>Passing a predefined parameter to a parameterized build
job</title>
<mediaobject id="I_mediaobject10_d1e14510">
<imageobject role="print">
<imagedata fileref="figs/print/jtdg_1018.pdf" format="PDF"/>
</imageobject>
<imageobject role="web">
<imagedata fileref="figs/web/jtdg_1018.png" format="PNG"/>
</imageobject>
</mediaobject>
</figure>
</sect1>
<sect1 id="sect-multi-configuration-build-jobs">
<title>Multiconfiguration Build Jobs</title>
<para>Multiconfiguration <indexterm class="startofrange" id="ch10-multi1" significance="normal"><primary>build jobs</primary><secondary>multiconfiguration</secondary></indexterm><indexterm class="startofrange" id="ch10-multi2" significance="normal"><primary>multiconfiguration build jobs</primary></indexterm><indexterm id="I_indexterm10_d1e14528" significance="normal"><primary>parameterized build jobs</primary><seealso>multiconfiguration build jobs</seealso></indexterm>build jobs are an extremely powerful feature of Jenkins. A
multiconfiguration build job can be thought of as a parameterized build
job that can be automatically run with all the possible combinations of
parameters that it can accept. They are particularly useful for tests,
where you can test your application using a single build job, but under a
wide variety of conditions (browsers, databases, and so forth).</para>
<sect2>
<title>Setting Up a Multiconfiguration Build</title>
<para>To <indexterm class="startofrange" id="ch10-mcreate1" significance="normal"><primary>multiconfiguration build jobs</primary><secondary>creating</secondary></indexterm><indexterm class="startofrange" id="ch10-mcreate2" significance="normal"><primary>build jobs</primary><secondary>multiconfiguration</secondary><tertiary>creating</tertiary></indexterm>create a new multiconfiguration build job, simply choose
this option on the New Job page (see <xref linkend="fig-hudson-build-multi-configuration"/>).</para>
<figure float="0" id="fig-hudson-build-multi-configuration">
<title>Creating a multiconfiguration build job</title>
<mediaobject id="I_mediaobject10_d1e14557">
<imageobject role="print">
<imagedata fileref="figs/print/jtdg_1019.pdf" format="PDF"/>
</imageobject>
<imageobject role="web">
<imagedata fileref="figs/web/jtdg_1019.png" format="PNG"/>
</imageobject>
</mediaobject>
</figure>
<para>A multiconfiguration build job is just like any other build job,
but with one very important additional element: the
<firstterm>Configuration Matrix</firstterm> (see <xref linkend="fig-hudson-build-multi-config"/>). This is where you define
the different configurations that will be used to run your
builds.</para>
<figure float="none" id="fig-hudson-build-multi-config">
<title>Adding an axis to a multiconfiguration build</title>
<mediaobject id="I_mediaobject10_d1e14572">
<imageobject role="print">
<imagedata fileref="figs/print/jtdg_1020.pdf" format="PDF"/>
</imageobject>
<imageobject role="web">
<imagedata fileref="figs/web/jtdg_1020.png" format="PNG"/>
</imageobject>
</mediaobject>
</figure>
<para>You can define different axes of configuration options, including
running the build job on different slaves or on different JDKs, or
providing your own custom properties to the build. For example, in the
build jobs discussed earlier, we might want to test our application for
different databases and different operating systems. We could define one
axis defining slave machines with different operating systems we wanted
our build to run on, and another axis defining all the possible database
values. Jenkins will then run the build job for each possible database
and each possible operating system.</para>
<para>Let’s look at the types of axis you can<indexterm id="I_indexterm10_d1e14581" class="endofrange" startref="ch10-mcreate1" significance="normal"><primary/></indexterm><indexterm id="I_indexterm10_d1e14583" class="endofrange" startref="ch10-mcreate2" significance="normal"><primary/></indexterm> define.</para>
</sect2>
<sect2>
<title>Configuring a Slave Axis</title>
<para>The<indexterm class="startofrange" id="ch10-slave1" significance="normal"><primary>multiconfiguration build jobs</primary><secondary>slave axis for</secondary></indexterm><indexterm class="startofrange" id="ch10-slave2" significance="normal"><primary>build jobs</primary><secondary>multiconfiguration</secondary><tertiary>slave axis for</tertiary></indexterm><indexterm class="startofrange" id="ch10-slave3" significance="normal"><primary>slave machines</primary><secondary sortas="multi-config">for multiconfiguration build
jobs</secondary></indexterm> first option is to configure your build to run
simultaneously on different slave machines (see <xref linkend="chapter-distributed-builds"/>). Now of course, the idea of
having a set of slave machines is usually that you can run your build
job on any of them. But there are cases where it makes sense to be a
little more choosy. For example, you might want your tests to run on
Windows, Mac OS X, and Linux. In this case, you create a new axis for
your slave nodes, as shown in <xref linkend="fig-build-multi-config-slaves"/>. You can choose the nodes you
want to use in two ways: by label or by individual node. Using labels
lets you identify categories of build nodes (for example, Windows
machines), without tying the build to any one machine. This is a more
flexible option, and makes it easier to expand your build capacity as
required. Sometimes, however, you may really want to run a build on a
specific machine. In this case, you can use the “Individual nodes”
option, and choose the machine in this list.</para>
<figure float="none" id="fig-build-multi-config-slaves">
<title>Defining an axis of slave nodes</title>
<mediaobject id="I_mediaobject10_d1e14616">
<imageobject role="print">
<imagedata fileref="figs/print/jtdg_1021.pdf" format="PDF"/>
</imageobject>
<imageobject role="web">
<imagedata fileref="figs/web/jtdg_1021.png" format="PNG"/>
</imageobject>
</mediaobject>
</figure>
<para>If you need more flexibility, you can also use a Label Expression,
which lets you define which slave nodes should be used for builds on a
particular axis using boolean expressions and logical operators to
combine labels. For example, suppose you have defined labels for slave
machines based on operating system (“windows”, “linux”) and installed
databases (“oracle”, “mysql”, “db2”). To define an axis running tests
only on Windows machines installed with MySQL, you could use an
expression like <literal moreinfo="none">windows && mysql</literal>.</para>
<para>We discuss working with slave nodes and distributed builds in more
<indexterm id="I_indexterm10_d1e14628" class="endofrange" startref="ch10-slave1" significance="normal"><primary/></indexterm><indexterm id="I_indexterm10_d1e14630" class="endofrange" startref="ch10-slave2" significance="normal"><primary/></indexterm><indexterm id="I_indexterm10_d1e14632" class="endofrange" startref="ch10-slave3" significance="normal"><primary/></indexterm>detail in <phrase role="keep-together"><xref linkend="chapter-distributed-builds"/></phrase>.</para>
</sect2>
<sect2>
<title>Configuring a JDK Axis</title>
<para>If you<indexterm id="I_indexterm10_d1e14643" significance="normal"><primary>multiconfiguration build jobs</primary><secondary>JDK axis for</secondary></indexterm><indexterm id="I_indexterm10_d1e14648" significance="normal"><primary>build jobs</primary><secondary>multiconfiguration</secondary><tertiary>JDK axis for</tertiary></indexterm><indexterm id="I_indexterm10_d1e14655" significance="normal"><primary>JDK (Java Development Kit)</primary><secondary>versions of, for multiconfiguration build
jobs</secondary></indexterm> are deploying your application to a broad client base
where you have limited control over the target environment, you may need
to test your application using different versions of Java. In cases like
this it is useful to be able to set up a JDK axis in a
multiconfiguration build. When you add a JDK axis, Jenkins will
automatically propose the list of JDK versions that it knows about (see
<xref linkend="fig-hudson-build-multi-config-jdk"/>). If you need to
use additional JDKs, just add them to your Jenkins configuration
page.</para>
<figure float="0" id="fig-hudson-build-multi-config-jdk">
<title>Defining an axis of JDK versions</title>
<mediaobject id="I_mediaobject10_d1e14666">
<imageobject role="print">
<imagedata fileref="figs/print/jtdg_1022.pdf" format="PDF"/>
</imageobject>
<imageobject role="web">
<imagedata fileref="figs/web/jtdg_1022.png" format="PNG"/>
</imageobject>
</mediaobject>
</figure>
</sect2>
<sect2>
<title>Custom Axis</title>
<para>The<indexterm id="I_indexterm10_d1e14676" significance="normal"><primary>multiconfiguration build jobs</primary><secondary>custom axis for</secondary></indexterm><indexterm id="I_indexterm10_d1e14681" significance="normal"><primary>build jobs</primary><secondary>multiconfiguration</secondary><tertiary>custom axis for</tertiary></indexterm> third type of axis lets you define different ways to run
your build job, based on arbitrary variables that you define. For
example, you might provide a list of databases you need to test against,
or a list of browsers to use in your web tests. These are like
parameters for a parameterized build job, except that you provide the
complete list of possible values, and rather than prompting for you to
enter a value, Jenkins will run the build with <emphasis>all</emphasis>
of the values you provide (<xref linkend="fig-hudson-build-mulit-config-custom"/>).</para>
<figure float="none" id="fig-hudson-build-mulit-config-custom">
<title>Defining a user-defined axis</title>
<mediaobject id="I_mediaobject10_d1e14697">
<imageobject role="print">
<imagedata fileref="figs/print/jtdg_1023.pdf" format="PDF"/>
</imageobject>
<imageobject role="web">
<imagedata fileref="figs/web/jtdg_1023.png" format="PNG"/>
</imageobject>
</mediaobject>
</figure>
</sect2>
<sect2>
<title>Running a Multiconfiguration Build</title>
<para>Once<indexterm class="startofrange" id="ch10-mrun1" significance="normal"><primary>multiconfiguration build jobs</primary><secondary>running</secondary></indexterm><indexterm class="startofrange" id="ch10-mrun2" significance="normal"><primary>build jobs</primary><secondary>multiconfiguration</secondary><tertiary>running</tertiary></indexterm> you have set up the axes, you can run your
multiconfiguration build just like any other. However, Jenkins will
treat each combination of variables as a separate build job. Jenkins
displays the aggregate results in a table, where all of the combinations
are shown (see <xref linkend="fig-hudson-build-multi-config-results"/>). If you click on any
of the balls, Jenkins will take you to the detailed results for that
particular build.</para>
<figure float="0" id="fig-hudson-build-multi-config-results">
<title>Multiconfiguration build results</title>
<mediaobject id="I_mediaobject10_d1e14725">
<imageobject role="print">
<imagedata fileref="figs/print/jtdg_1024.pdf" format="PDF"/>
</imageobject>
<imageobject role="web">
<imagedata fileref="figs/web/jtdg_1024.png" format="PNG"/>
</imageobject>
</mediaobject>
</figure>
<para>By default, Jenkins will run the build jobs in parallel. However
there are some cases where this is not a good idea. For example, many
Java web applications use Selenium or WebDriver tests running against a
local instance of Jetty that is automatically started by the build job.
Build scripts like this need to be specially configured to be able to
run in parallel on the same machine, to avoid port conflicts. Concurrent
database access during tests can be another source of problems if
concurrency is not designed into the tests. If your builds are not
designed to run in parallel, you can force Jenkins to run the tests
sequentially by ticking the Run each configuration sequentially checkbox
at the bottom<indexterm id="I_indexterm10_d1e14732" significance="normal"><primary>multiconfiguration build jobs</primary><secondary>configuration matrix for</secondary></indexterm><indexterm id="I_indexterm10_d1e14737" significance="normal"><primary>build jobs</primary><secondary>multiconfiguration</secondary><tertiary>configuration matrix for</tertiary></indexterm> of the Configuration Matrix section.</para>
<para>By default, Jenkins will run all possible combinations of the
different axes. So, in the above example, we have three environments,
two JDKs, and four databases. This results in a total of 24 builds.
However, in some cases, it may not make sense (or be possible) to run
certain combinations. For example, suppose you have a build job that
runs automated web tests. If one axis contains the web browsers to be
tested (Firefox, Internet Explorer, Chrome, etc.) and another the
Operating Systems (Linux, Windows, Mac OS), it would make little sense
to run Internet Explorer with Linux or Mac OS.</para>
<para>The<indexterm id="I_indexterm10_d1e14749" significance="normal"><primary>build jobs</primary><secondary>multiconfiguration</secondary><tertiary>combination filter for</tertiary></indexterm><indexterm id="I_indexterm10_d1e14756" significance="normal"><primary>multiconfiguration build jobs</primary><secondary>combination filter for</secondary></indexterm> Combination Filter option lets you set up rules about
which combinations of variables are valid. This field is a Groovy
boolean expression that uses the names of the variables you defined for
each axis. The expression must evaluate to true for the build to
execute. For example, suppose you have a build job running web tests in
different browsers on different operating systems (see <xref linkend="fig-hudson-build-multi-config-filters"/>). The tests need to
run Firefox, Internet Explorer and Chrome, on Windows, Mac OS X, and
Linux. However Internet Explorer only runs on Windows, and Chrome does
not run on Linux.</para>
<figure float="none" id="fig-hudson-build-multi-config-filters">
<title>Setting up a combination filter</title>
<mediaobject id="I_mediaobject10_d1e14767">
<imageobject role="print">
<imagedata fileref="figs/print/jtdg_1025.pdf" format="PDF"/>
</imageobject>
<imageobject role="web">
<imagedata fileref="figs/web/jtdg_1025.png" format="PNG"/>
</imageobject>
</mediaobject>
</figure>
<para>To set this up with a Combination Filter, we could use an
expression like the following:</para>
<programlisting id="I_programlisting10_d1e14774" format="linespecific">(browser=="firefox")
|| (browser=="iexplorer" && os=="windows")
|| (browser=="chrome" && os != "linux")</programlisting>
<para>This would result in only the correct browser/operating system
combinations being executed (see <xref linkend="fig-hudson-multi-config-filter-result"/>). Executed builds are
displayed in the usual colors, whereas skipped builds are shown in
gray.</para>
<figure float="0" id="fig-hudson-multi-config-filter-result">
<title>Build results using a combination filter</title>
<mediaobject id="I_mediaobject10_d1e14783">
<imageobject role="print">
<imagedata fileref="figs/print/jtdg_1026.pdf" format="PDF"/>
</imageobject>
<imageobject role="web">
<imagedata fileref="figs/web/jtdg_1026.png" format="PNG"/>
</imageobject>
</mediaobject>
</figure>
<para>Another reason to use a build filter is that there are simply too
many valid combinations to run in a reasonable time. In this case, the
best solution may be to upscale your build server. The second-best
solution, on the other hand, might be to only run a subset of the
combinations, possibly running the full set of combinations on a nightly
basis. You can do this by using the special <code>index</code> variable.
If you include the expression <code>(index%2 == 0)</code>, for example,
will ensure that only one build job in two is actually executed.</para>
<para>You may also want certain builds to be executed before the others,
as a sanity check. For example, you might want to run the default (and,
theoretically, the most reliable) configuration for your application
first, before continuing on to more exotic combinations. To do this, you
can use the “Execute touchstone builds first” option. Here, you enter a
filter value (like the one seen above) to define the first build or
builds to be executed. You can also specify if the build should proceed
only if these builds are successful, or even if they are unsuccessful.
Once these builds have completed as expected, Jenkins will proceed with
the other<indexterm id="I_indexterm10_d1e14799" class="endofrange" startref="ch10-mrun1" significance="normal"><primary/></indexterm><indexterm id="I_indexterm10_d1e14801" class="endofrange" startref="ch10-mrun2" significance="normal"><primary/></indexterm><indexterm id="I_indexterm10_d1e14803" class="endofrange" startref="ch10-multi1" significance="normal"><primary/></indexterm><indexterm id="I_indexterm10_d1e14805" class="endofrange" startref="ch10-multi2" significance="normal"><primary/></indexterm> combinations.</para>
</sect2>
</sect1>
<sect1 id="I_sect110_d1e14808">
<title>Generating Your Maven Build Jobs Automatically</title>
<para>
<emphasis>Contributed by Evgeny Goldin</emphasis>
</para>
<para>As <indexterm class="startofrange" id="ch10-mavengen" significance="normal"><primary>Maven build jobs</primary><secondary>generating automatically</secondary></indexterm>mentioned in the previous section, the number of build jobs
that your Jenkins server will host can vary. As the number of build jobs
grows, it becomes harder not only to view them in Jenkins dashboard, but
to configure them as well. Imagine what would it take to configure 20 to
50 Jenkins jobs one-by-one! In addition, many of those jobs may have
common configuration elements, such as Maven goals or build memory
settings, which results in duplicated configuration and higher maintenance
overhead.</para>
<para>For example, if you decide to run <literal moreinfo="none">mvn clean
install</literal> instead of <literal moreinfo="none">mvn clean deploy</literal> for your
release jobs and switch to alternative deployment methods, such as those
provided by <ulink url="http://wiki.jenkins-ci.org/display/JENKINS/Artifactory+Plugin">Artifactory
plugin</ulink>, you’ll have no choice but to visit all relevant jobs and
update them manually.</para>
<para>Alternatively, you could take an advantage of the fact that Jenkins
is a simple and straightforward tool that keeps all of its definitions in
plain files on the disk. Indeed you can update the <filename moreinfo="none">config.xml</filename> files of your jobs directly in the
<filename moreinfo="none">.jenkins/jobs</filename> directory where they
are kept. While this approach will work, it is still far from ideal as it
involves quite a lot of manual picking and fragile replacements in Jenkins
XML files.</para>
<para>There is a third way to achieve the nirvana of massive job updates:
generate your configuration files automatically using some sort of
definition file. The<indexterm id="I_indexterm10_d1e14843" significance="normal"><primary>Maven Jenkins plugin</primary></indexterm><indexterm id="I_indexterm10_d1e14846" significance="normal"><primary>plugins</primary><secondary>Maven Jenkins</secondary></indexterm> <ulink url="http://evgeny-goldin.com/wiki/Maven-jenkins-plugin">Maven Jenkins
Plugin</ulink> does exactly that, generating <filename moreinfo="none">config.xml</filename> files for all jobs using standard
Maven definitions kept in a single <filename moreinfo="none">pom.xml</filename> file.</para>
<sect2>
<title>Configuring a Job</title>
<para>When <indexterm class="startofrange" id="ch10-mavenconfig" significance="normal"><primary>Maven build jobs</primary><secondary>generating automatically</secondary><tertiary>configuring</tertiary></indexterm>configuring a single job with the Maven Jenkins Plugin,
you can define all the usual Jenkins configuration elements, such as
Maven goals, POM location, repository URLs, e-mail addresses, number of
days to keep the logs, and so on. The plugin tries to bring you as close
to possible to Jenkins’ usual way of configuring a job manually.</para>
<para>Let’s take a look on a <ulink url="http://code.google.com/p/google-guice/">Google Guice</ulink> build
job:</para>
<screen format="linespecific"><job>
<id>google-guice-trunk</id>
<description>Building Google Guice trunk.</description>
<descriptionTable>
<row>
<key>Project Page</key>
<value>
<a href="http://code.google.com/p/google-guice/">
<b><code>code.google.com/p/google-guice</code></b>
</a>
</value>
<escapeHTML>false</escapeHTML>
<bottom>false</bottom>
</row>
</descriptionTable>
<jdkName>jdk1.6.0</jdkName>
<mavenName>apache-maven-3</mavenName>
<mavenOpts>-Xmx256m -XX:MaxPermSize=128m</mavenOpts>
<daysToKeep>5</daysToKeep>
<useUpdate>false</useUpdate>
<mavenGoals>-e clean install</mavenGoals>
<trigger>
<type>timer</type>
<expression>0 0 * * *</expression>
</trigger>
<repository>
<remote>http://google-guice.googlecode.com/svn/trunk/</remote>
</repository>
<mail>
<recipients>jenkins@evgeny-goldin.org</recipients>
</mail>
</job></screen>
<para>This job uses a number of standard configurations such as
<literal moreinfo="none"><jdkName></literal>,
<literal moreinfo="none"><mavenName></literal>, and
<literal moreinfo="none"><mavenOpts></literal>. The code is checked out from a
Subversion repository (defined in the
<literal moreinfo="none"><repository></literal> element), and a cron
<literal moreinfo="none"><trigger></literal> runs the job nightly at 00:00. Email
notifications are sent to people specified with the
<literal moreinfo="none"><mail></literal> element. This configuration also adds a
link back to the project’s page in the description table that is
generated automatically for each job.</para>
<para>The generated job is displayed in your Jenkins server as
illustrated in <xref linkend="jenkins-plugin-google-guice-trunk-job"/>.</para>
<figure float="none" id="jenkins-plugin-google-guice-trunk-job">
<title>A job generated by the Maven Jenkins plugin</title>
<mediaobject id="I_mediaobject10_d1e14909">
<imageobject role="print">
<imagedata fileref="figs/print/jtdg_1027.pdf" format="PDF"/>
</imageobject>
<imageobject role="web">
<imagedata fileref="figs/web/jtdg_1027.png" format="PNG"/>
</imageobject>
</mediaobject>
</figure>
<para>Here’s another job building the Jenkins master branch at
GitHub:</para>
<screen format="linespecific"><job>
<id>jenkins-master</id>
<jdkName>jdk1.6.0</jdkName>
<numToKeep>5</numToKeep>
<mavenName>apache-maven-3</mavenName>
<trigger>
<type>timer</type>
<expression>0 1 * * *</expression>
</trigger>
<scmType>git</scmType>
<repository>
<remote>git://github.com/jenkinsci/jenkins.git</remote>
</repository>
<mail>
<recipients>jenkins@evgeny-goldin.org</recipients>
<sendForUnstable>false</sendForUnstable>
</mail>
</job></screen>
<para>This would generate the job shown in <xref linkend="jenkins-plugin-jenkins-master-job"/>.</para>
<figure float="0" id="jenkins-plugin-jenkins-master-job">
<title>jenkins-master job generated</title>
<mediaobject id="I_mediaobject10_d1e14925">
<imageobject role="print">
<imagedata fileref="figs/print/jtdg_1028.pdf" format="PDF"/>
</imageobject>
<imageobject role="web">
<imagedata fileref="figs/web/jtdg_1028.png" format="PNG"/>
</imageobject>
</mediaobject>
</figure>
<para>The plugin’s <ulink url="http://evgeny-goldin.com/wiki/Maven-jenkins-plugin#.3Cjob.3E">documentation</ulink>
provides a detailed reference of all settings that can be <indexterm id="I_indexterm10_d1e14936" class="endofrange" startref="ch10-mavenconfig" significance="normal"><primary/></indexterm>configured.</para>
</sect2>
<sect2>
<title>Reusing Job Configuration with Inheritance</title>
<para>Being<indexterm class="startofrange" id="ch10-inherit" significance="normal"><primary>Maven build jobs</primary><secondary>generating automatically</secondary><tertiary>inheritance of configuration</tertiary></indexterm> able to generate Jenkins jobs using centralized
configuration, such as Maven POM, solves the problem of creating and
updating many jobs at once. All you has to do now is to modify the job
definitions, re-run the plugin and load definitions updated with Manage
Jenkins<phrase role="unicode">→</phrase>“Reload Configuration from
Disk”. This approach also has the advantage of making it easy to store
your job configurations in your version control system, which in turn
makes it easier to keep track of changes made to the build <phrase role="keep-together">configurations</phrase>.</para>
<para>But we still didn’t solve the problem of maintaining jobs that
share a number of identical properties, such as Maven goals, email
recipients or code repository URL. For that, the Maven Jenkins Plugin
provides jobs inheritance, demonstrated in the following <phrase role="keep-together">example</phrase>:</para>
<screen format="linespecific"><jobs>
<job>
<id>google-guice-inheritance-base</id>
<abstract>true</abstract>
<jdkName>jdk1.6.0</jdkName>
<mavenName>apache-maven-3</mavenName>
<daysToKeep>5</daysToKeep>
<useUpdate>true</useUpdate>
<mavenGoals>-B -e -U clean install</mavenGoals>
<mail><recipients>jenkins@evgeny-goldin.org</recipients></mail>
</job>
<job>
<id>google-guice-inheritance-trunk</id>
<parent>google-guice-inheritance-base</parent>
<repository>
<remote>http://google-guice.googlecode.com/svn/trunk/</remote>
</repository>
</job>
<job>
<id>google-guice-inheritance-3.0-rc3</id>
<parent>google-guice-inheritance-base</parent>
<repository>
<remote>http://google-guice.googlecode.com/svn/tags/3.0-rc3/</remote>
</repository>
</job>
<job>
<id>google-guice-inheritance-2.0-maven</id>
<parent>google-guice-inheritance-base</parent>
<mavenName>apache-maven-2</mavenName>
<repository>
<remote>http://google-guice.googlecode.com/svn/branches/2.0-maven/
</remote>
</repository>
</job>
</jobs></screen>
<para>In this configuration,
<emphasis>google-guice-inheritance-base</emphasis> is an abstract parent
job holding all common properties: JDK name, Maven name, days to keep
the logs, SVN update policy, Maven goals, and mail recipients. The three
following jobs are very short, merely specifying that they extend a
<literal moreinfo="none"><parent></literal> job and add any missing configurations
<phrase role="keep-together">(repository</phrase> URLs in this case).
When generated, they inherit all of the properties from the parent job
automatically.</para>
<para>Any inherited property can be overridden, as demonstrated in
<emphasis>google-guice-<phrase role="keep-together">inheritance-</phrase>2.0-maven</emphasis> job where
Maven 2 is used instead of Maven 3. If you want to “cancel” an inherited
property, you will need to override it with an empty value.</para>
<para>Jobs inheritance is a very powerful concept that allows jobs to
form hierarchical groups of any kind and for any purpose. You can group
your CI, nightly or release jobs this way, centralizing shared execution
triggers, Maven goals or mail recipients in parent jobs. This approach
borrowed from an OOP world solves the problem of maintaining jobs
sharing a number of identical <indexterm id="I_indexterm10_d1e14986" class="endofrange" startref="ch10-inherit" significance="normal"><primary/></indexterm>properties.</para>
</sect2>
<sect2>
<title>Plugin Support</title>
<para>In addition to configuring a job and reusing its definitions, you
can apply special support for a number of Jenkins plugins. Right now, a
simplified usage of Parameterized Trigger and Artifactory plugins is
provided, with support for other popular plugins planned for future
versions.</para>
<para>Below<indexterm id="I_indexterm10_d1e14996" significance="normal"><primary>Parameterized Trigger plugin</primary></indexterm><indexterm id="I_indexterm10_d1e14999" significance="normal"><primary>plugins</primary><secondary>Parameterized Trigger</secondary></indexterm><indexterm id="I_indexterm10_d1e15004" significance="normal"><primary>Maven build jobs</primary><secondary>generating automatically</secondary><tertiary>Parameterized Trigger plugin with</tertiary></indexterm> is an example of invoking jobs with the Parameterized
Trigger plugin. Using this option assumes you have this plugin installed
already:</para>
<screen format="linespecific"><job>
<id>google-guice-inheritance-trunk</id>
...
<invoke>
<jobs>
google-guice-inheritance-3.0-rc3,
google-guice-inheritance-2.0-maven
</jobs>
</invoke>
</job>
<job>
<id>google-guice-inheritance-3.0-rc3</id>
...
</job>
<job>
<id>google-guice-inheritance-2.0-maven</id>
...
</job></screen>
<para>The <literal moreinfo="none"><invoke></literal> element lets you invoke
other jobs each time the current job finishes successfully. You can
create a pipeline of jobs this way, making sure each job in a pipeline
invokes the following one. Note that if there are more than one Jenkins
executors available at the moment of invocation, the specified jobs will
start running in parallel. For serial execution you’ll need to connect
each upstream job to a downstream one with
<literal moreinfo="none"><invoke></literal>.</para>
<para>By default invocation happens only when the current job is stable.
This can be modified, as shown in the following examples:</para>
<screen format="linespecific"><invoke>
<jobs>jobA, jobB, jobC</jobs>
<always>true</always>
</invoke>
<invoke>
<jobs>jobA, jobB, jobC</jobs>
<unstable>true</unstable>
</invoke>
<invoke>
<jobs>jobA, jobB, jobC</jobs>
<stable>false</stable>
<unstable>false</unstable>
<failed>true</failed>
</invoke></screen>
<para>The first invocation in the example above always invokes the
downstream jobs. It can be used for a pipeline of jobs that should
always be executed even if some of them or their tests fail.</para>
<para>The second invocation in the example above invokes downstream jobs
even if an upstream job is unstable: the invocation happens regardless
of test results. It can be used for a pipeline of jobs that are less
sensitive to tests and their failures.</para>
<para>The third invocation in the example above invokes downstream jobs
only when an upstream job fails but not when it is stable or unstable.
You can find this configuration useful when a failing job needs to
perform additional actions beyond traditional email
notifications.</para>
<para><indexterm id="I_indexterm10_d1e15033" significance="normal"><primary>Artifactory plugin</primary></indexterm><indexterm id="I_indexterm10_d1e15036" significance="normal"><primary>plugins</primary><secondary>Artifactory</secondary></indexterm><indexterm id="I_indexterm10_d1e15041" significance="normal"><primary>Maven build jobs</primary><secondary>generating automatically</secondary><tertiary>Artifactory plugin with</tertiary></indexterm><ulink url="http://jfrog.org">Artifactory</ulink> is a