Skip to content
Fetching contributors…
Cannot retrieve contributors at this time
1974 lines (1966 sloc) 136 KB
<?xml version="1.0"?>
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "">
<chapter id="chapter-advanced-builds">
<title>Advanced Builds</title>
<sect1 id="sect-advanced-builds-introduction">
<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 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>
<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 role="web">
<imagedata fileref="figs/web/jtdg_1001.png" format="PNG" scale="90"/>
<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
<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 role="web">
<imagedata fileref="figs/web/jtdg_1002.png" format="PNG"/>
<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 role="web">
<imagedata fileref="figs/web/jtdg_1003.png" format="PNG"/>
<title>Adapting Your Builds to Work with Parameterized Build
<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 role="web">
<imagedata fileref="figs/web/jtdg_1004.png" format="PNG"/>
<para>When we run this, we get a console output along the following
<screen format="linespecific">Started by user anonymous
Building on master
[workspace] $ /bin/sh -xe /var/folders/y+/y+a+wZ-jG6WKHEm9KwnSvE+++TI/-Tmp-/
<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">&lt;target name="printversion"&gt;
&lt;property environment="env" /&gt;
&lt;echo message="${env.VERSION}"/&gt;
<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"> ...
&lt;version&gt;<userinput moreinfo="none">${target.version}</userinput>&lt;/version&gt;
<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 role="web">
<imagedata fileref="figs/web/jtdg_1005.png" format="PNG"/>
<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 role="web">
<imagedata fileref="figs/web/jtdg_1006.png" format="PNG"/>
<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
<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 role="web">
<imagedata fileref="figs/web/jtdg_1007.png" format="PNG"/>
<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 role="web">
<imagedata fileref="figs/web/jtdg_1008.png" format="PNG"/>
<para>The URL (which will look something like
<emphasis></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
<programlisting id="I_programlisting10_d1e14177" format="linespecific">http://buildserver/job/game-of-life/197/artifact/gameoflife-web/target/
<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 role="web">
<imagedata fileref="figs/web/jtdg_1009.png" format="PNG"/>
<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 role="web">
<imagedata fileref="figs/web/jtdg_1010.png" format="PNG"/>
<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 role="web">
<imagedata fileref="figs/web/jtdg_1011.png" format="PNG"/>
<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
<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 role="web">
<imagedata fileref="figs/web/jtdg_1012.png" format="PNG"/>
<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 role="web">
<imagedata fileref="figs/web/jtdg_1013.png" format="PNG"/>
<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"></programlisting>
<para>So, in the example shown above, you could trigger a build like
<programlisting id="I_programlisting10_d1e14359" format="linespecific"></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>
<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
<mediaobject id="I_mediaobject10_d1e14411">
<imageobject role="print">
<imagedata fileref="figs/print/jtdg_1014.pdf" format="PDF"/>
<imageobject role="web">
<imagedata fileref="figs/web/jtdg_1014.png" format="PNG"/>
<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
<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>A parameterized build job with DATABASE parameter</title>
<mediaobject id="I_mediaobject10_d1e14457">
<imageobject role="print">
<imagedata fileref="figs/print/jtdg_1015.pdf" format="PDF"/>
<imageobject role="web">
<imagedata fileref="figs/web/jtdg_1015.png" format="PNG"/>
<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 role="web">
<imagedata fileref="figs/web/jtdg_1016.png" format="PNG"/>
<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
<mediaobject id="I_mediaobject10_d1e14487">
<imageobject role="print">
<imagedata fileref="figs/print/jtdg_1017.pdf" format="PDF"/>
<imageobject role="web">
<imagedata fileref="figs/web/jtdg_1017.png" format="PNG"/>
<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
<mediaobject id="I_mediaobject10_d1e14510">
<imageobject role="print">
<imagedata fileref="figs/print/jtdg_1018.pdf" format="PDF"/>
<imageobject role="web">
<imagedata fileref="figs/web/jtdg_1018.png" format="PNG"/>
<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>
<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 role="web">
<imagedata fileref="figs/web/jtdg_1019.png" format="PNG"/>
<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
<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 role="web">
<imagedata fileref="figs/web/jtdg_1020.png" format="PNG"/>
<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>
<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 role="web">
<imagedata fileref="figs/web/jtdg_1021.png" format="PNG"/>
<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 &amp;&amp; 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>
<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
<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 role="web">
<imagedata fileref="figs/web/jtdg_1022.png" format="PNG"/>
<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 role="web">
<imagedata fileref="figs/web/jtdg_1023.png" format="PNG"/>
<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 role="web">
<imagedata fileref="figs/web/jtdg_1024.png" format="PNG"/>
<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 role="web">
<imagedata fileref="figs/web/jtdg_1025.png" format="PNG"/>
<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" &amp;&amp; os=="windows")
|| (browser=="chrome" &amp;&amp; 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
<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 role="web">
<imagedata fileref="figs/web/jtdg_1026.png" format="PNG"/>
<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>
<sect1 id="I_sect110_d1e14808">
<title>Generating Your Maven Build Jobs Automatically</title>
<emphasis>Contributed by Evgeny Goldin</emphasis>
<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
<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="">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="">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>
<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="">Google Guice</ulink> build
<screen format="linespecific">&lt;job&gt;
&lt;description&gt;Building Google Guice trunk.&lt;/description&gt;
&lt;key&gt;Project Page&lt;/key&gt;
&lt;a href=""&gt;
&lt;mavenOpts&gt;-Xmx256m -XX:MaxPermSize=128m&lt;/mavenOpts&gt;
&lt;mavenGoals&gt;-e clean install&lt;/mavenGoals&gt;
&lt;expression&gt;0 0 * * *&lt;/expression&gt;
<para>This job uses a number of standard configurations such as
<literal moreinfo="none">&lt;jdkName&gt;</literal>,
<literal moreinfo="none">&lt;mavenName&gt;</literal>, and
<literal moreinfo="none">&lt;mavenOpts&gt;</literal>. The code is checked out from a
Subversion repository (defined in the
<literal moreinfo="none">&lt;repository&gt;</literal> element), and a cron
<literal moreinfo="none">&lt;trigger&gt;</literal> runs the job nightly at 00:00. Email
notifications are sent to people specified with the
<literal moreinfo="none">&lt;mail&gt;</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 role="web">
<imagedata fileref="figs/web/jtdg_1027.png" format="PNG"/>
<para>Here’s another job building the Jenkins master branch at
<screen format="linespecific">&lt;job&gt;
&lt;expression&gt;0 1 * * *&lt;/expression&gt;
<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 role="web">
<imagedata fileref="figs/web/jtdg_1028.png" format="PNG"/>
<para>The plugin’s <ulink url="">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>
<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">&lt;jobs&gt;
&lt;mavenGoals&gt;-B -e -U clean install&lt;/mavenGoals&gt;
<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">&lt;parent&gt;</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
<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>
<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
<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
<screen format="linespecific">&lt;job&gt;
<para>The <literal moreinfo="none">&lt;invoke&gt;</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">&lt;invoke&gt;</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">&lt;invoke&gt;
&lt;jobs&gt;jobA, jobB, jobC&lt;/jobs&gt;
&lt;jobs&gt;jobA, jobB, jobC&lt;/jobs&gt;
&lt;jobs&gt;jobA, jobB, jobC&lt;/jobs&gt;
<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
<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="">Artifactory</ulink> is a
general purpose binaries repository that can be used as a Maven
repository manager. The <ulink url="">Jenkins
Artifactory plugin</ulink>, shown in <xref linkend="jenkins-plugin-artifactory"/>, provides a number of benefits
for Jenkins build jobs. We have already reviewed some of them in <xref linkend="sect-builds-deploy-enterprise-repository"/>, including an
ability to deploy artifacts upon job completion or to send builds
environment info together with artifacts for their better
<figure float="0" id="jenkins-plugin-artifactory">
<title>Artifactory Jenkins plugin configuration</title>
<mediaobject id="I_mediaobject10_d1e15062">
<imageobject role="print">
<imagedata fileref="figs/print/jtdg_1029.pdf" format="PDF"/>
<imageobject role="web">
<imagedata fileref="figs/web/jtdg_1029.png" format="PNG"/>
<para>You can also use the Artifactory Jenkins plugin in conjunction
with the Maven Jenkins Plugin to deploy artifacts to Artifactory, as
shown in the following example:</para>
<screen format="linespecific">&lt;job&gt;
<para>Default deployment credentials are specified when Jenkins is
configured in the Manage Jenkins<phrase role="unicode">→</phrase>Configure System screen. They can be also
specified for each Jenkins job. The default Maven repositories are
<filename moreinfo="none">libs-releases-local</filename> and
<filename moreinfo="none">libs-snapshots-local</filename>. You can find more details in
the plugin’s documentation at <ulink url=""/>.</para>
<title>Freestyle Jobs</title>
<para>In <indexterm id="I_indexterm10_d1e15089" significance="normal"><primary>freestyle build jobs</primary><secondary>generating automatically</secondary></indexterm><indexterm id="I_indexterm10_d1e15094" significance="normal"><primary>Maven Jenkins plugin</primary></indexterm><indexterm id="I_indexterm10_d1e15097" significance="normal"><primary>plugins</primary><secondary>Maven Jenkins</secondary></indexterm>addition to Maven jobs, the Maven Jenkins Plugin allows
you to configure Jenkins freestyle jobs. An example is shown
<screen format="linespecific">&lt;job&gt;
&lt;jvmOptions&gt;-Xmx128m -XX:MaxPermSize=128m -ea&lt;/jvmOptions&gt;
&lt;properties&gt;plugins-version = 0.2.2&lt;/properties&gt;
&lt;shell&gt;&lt;command&gt;pwd; ls -al; du -hs .&lt;/command&gt;&lt;/shell&gt;
<para>Freestyle jobs let you execute a shell or batch command, run Maven
or Ant, and invoke other jobs. They provide a convenient run-time
environment for system scripts or any other kind of activity not readily
available with Jenkins or one of its plugins. Using this approach, you
can generate Freestyle build job configuration files in a similar way to
the approach we have seen for Maven build jobs, which can help make your
build environment more consistent <indexterm id="I_indexterm10_d1e15107" class="endofrange" startref="ch10-mavengen" significance="normal"><primary/></indexterm>and maintainable.</para>
<sect1 id="I_sect110_d1e15110">
<title id="sect-advanced-builds-coordinating">Coordinating Your
<para>Triggering downstream build jobs is easy enough. However, when
setting up larger and more complicated build job setups, you sometimes
would like builds to be able to run concurrently, or possibly wait for
certain build jobs to finish before proceeding. In this section, we will
look at techniques and plugins that can help you do this.</para>
<title>Parallel Builds in Jenkins</title>
<para>Jenkins<indexterm class="startofrange" id="ch10-parallel" significance="normal"><primary>build jobs</primary><secondary>running in parallel</secondary></indexterm> has built-in support for parallel builds—when a build job
starts, Jenkins will assign it to the first available build node, so you
can potentially have as many parallel builds running as you have build
nodes available.</para>
<para>If you need to run slight variations of the same build job in
parallel, multiconfiguration build jobs (see <xref linkend="sect-multi-configuration-build-jobs"/>) are an excellent
option. This can come in handy as a way of accelerating your build
process. A typical application of multiconfiguration build jobs in this
context is to run integration tests in parallel. One strategy is to set
up an integration test build job that can be run in different ways to
execute different subsets of the integration tests. You could define
separate Maven profiles, for example, or configure your build to use a
command-line parameter to decide which tests to run. Once you have set
up your build script in this way, it is easy to configure a
multiconfiguration build job to run the subsets of your integration
tests in parallel.</para>
<para>You can also get Jenkins to trigger several downstream builds in
parallel, simply by listing them all in the “Build other projects” field
(see <xref linkend="fig-hudson-build-other-projects"/>). The subsequent
build jobs will be executed in parallel as much as possible. However, as
we will see further on, this may not always be exactly what you
<figure float="none" id="fig-hudson-build-other-projects">
<title>Triggering several other builds after a build job</title>
<mediaobject id="I_mediaobject10_d1e15137">
<imageobject role="print">
<imagedata fileref="figs/print/jtdg_1030.pdf" format="PDF"/>
<imageobject role="web">
<imagedata fileref="figs/web/jtdg_1030.png" format="PNG"/>
<title>Dependency Graphs</title>
<para>Before<indexterm id="I_indexterm10_d1e15147" significance="normal"><primary>build jobs</primary><secondary>dependencies between</secondary></indexterm><indexterm id="I_indexterm10_d1e15152" significance="normal"><primary>Dependency Graph View plugin</primary></indexterm><indexterm id="I_indexterm10_d1e15155" significance="normal"><primary>plugins</primary><secondary>Dependency Graph View</secondary></indexterm> we investigate the finer points of parallel builds, it is
useful to be able to visualize the relationships between your build
jobs. The Dependency Graph View plugin analyzes your build jobs and
displays a graph describing the upstream and downstream connections
between your jobs. This plugin uses <ulink url="">graphviz</ulink>, which you will need to
install on your server if you don’t already have it.</para>
<para>This plugin adds a Dependency Graph icon in the main menu, which
displays a graph showing the relationships between all the build jobs in
your project (at the dashboard level), or all of the build jobs related
to the current build job (when you are inside a particular project [see
<xref linkend="fig-hudson-dependency-graph"/>]). What’s more, if you
click on a build job in the graph, Jenkins will take you directly to the
project page of that build job.</para>
<figure float="0" id="fig-hudson-dependency-graph">
<title>A build job dependency graph</title>
<mediaobject id="I_mediaobject10_d1e15171">
<imageobject role="print">
<imagedata fileref="figs/print/jtdg_1031.pdf" format="PDF"/>
<imageobject role="web">
<imagedata fileref="figs/web/jtdg_1031.png" format="PNG"/>
<para>When <indexterm class="startofrange" id="ch10-join1" significance="normal"><primary>build jobs</primary><secondary>joins in</secondary></indexterm><indexterm class="startofrange" id="ch10-join2" significance="normal"><primary>joins, in build jobs</primary></indexterm>setting up more complicated build pipelines, you
frequently come across situations where a build job cannot proceed until
a number of other build jobs have been completed, but that these
upstream build jobs do not need to be executed sequentially. For
example, in <xref linkend="fig-hudson-dependency-graph"/>, imagine that
the <command moreinfo="none">phoenix-deploy-to-uat</command> build job
actually requires three jobs to succeed before it can be executed:
<command moreinfo="none">phoenix-compatibility-tests</command>, <command moreinfo="none">phoenix-load-tests</command>, and <command moreinfo="none">phoenix-performance-tests</command>.</para>
<para>We can set this up by using the Joins plugin, which you will need
to install in the usual way via the Update center. Once installed, you
configure a join in the build job that initiates the join process (in
our example, this would be <command moreinfo="none">phoenix-web-tests</command>). In our example, we need to
modify the <command moreinfo="none">phoenix-web-tests</command> build
job so that it triggers the <command moreinfo="none">phoenix-compatibility-tests</command>, <command moreinfo="none">phoenix-load-tests</command>, and <command moreinfo="none">phoenix-performance-tests</command> first, and then, if
these three succeed, the <command moreinfo="none">phoenix-deploy-to-uat</command> build job.</para>
<para>We do this by simply configuring the Join Trigger field with the
name of the <command moreinfo="none">phoenix-deploy-to-uat</command>
build job (see <xref linkend="fig-hudson-build-join"/>). The “Build
other projects” field is not modified, and still lists the build jobs to
be triggered immediately after the current one. The Join Trigger field
contains the build jobs to be built once all of the immediate downstream
build jobs have finished.</para>
<figure float="0" id="fig-hudson-build-join">
<title>Configuring a join in the phoenix-web-tests build job</title>
<mediaobject id="I_mediaobject10_d1e15236">
<imageobject role="print">
<imagedata fileref="figs/print/jtdg_1032.pdf" format="PDF"/>
<imageobject role="web">
<imagedata fileref="figs/web/jtdg_1032.png" format="PNG"/>
<para>As a result, you no longer need the original build trigger for the
final build job, as it is now redundant.</para>
<para>This new flow shows up nicely in the dependency graphs
as<indexterm id="I_indexterm10_d1e15245" class="endofrange" startref="ch10-join1" significance="normal"><primary/></indexterm><indexterm id="I_indexterm10_d1e15247" class="endofrange" startref="ch10-join2" significance="normal"><primary/></indexterm> illustrated in <xref linkend="fig-build-dependency-graph-join"/>.</para>
<figure float="0" id="fig-build-dependency-graph-join">
<title>A more complicated build job dependency graph</title>
<mediaobject id="I_mediaobject10_d1e15255">
<imageobject role="print">
<imagedata fileref="figs/print/jtdg_1033.pdf" format="PDF"/>
<imageobject role="web">
<imagedata fileref="figs/web/jtdg_1033.png" format="PNG"/>
<?dbfo-need height=”1in”?>
<title>Locks and Latches</title>
<para>In other <indexterm class="startofrange" id="ch10-locks1" significance="normal"><primary>build jobs</primary><secondary>locking resources for</secondary></indexterm><indexterm class="startofrange" id="ch10-locks2" significance="normal"><primary>locking resources for build jobs</primary></indexterm>situations, you might be able to run a series of builds in
parallel to some degree, but certain build jobs cannot be run in
parallel because they access concurrent resources. Of course,
well-designed build jobs should strive to be as independent as possible,
but sometimes this can be difficult. For example, different build jobs
may need to access the same test database or files on the hard disk, and
doing so simultaneously could potentially compromise the results of the
tests. Or a performance build job may need exclusive access to the test
server, in order to have consistent results each time.</para>
<para>The<indexterm id="I_indexterm10_d1e15277" significance="normal"><primary>plugins</primary><secondary>Locks and Latches</secondary></indexterm><indexterm id="I_indexterm10_d1e15282" significance="normal"><primary>Locks and Latches plugin</primary></indexterm> Locks and Latches plugin lets you get around this problem
to some extent. This plugin lets you set up “locks” for certain
resources, in a similar way to locks in multithreaded programming.
Suppose, for example, in the build jobs depicted in <xref linkend="fig-build-dependency-graph-join"/>, that the load tests and
the performance tests run against a dedicated server, but only one build
job can run against this server at any one time. Imagine furthermore
that the performance tests for other projects also run against this
<para>To avoid contention over the performance server, you could use the
Locks and Latches plugin to set up a “lock” reserving access to this
server to a single build job at a time. First, in the System
Configuration page, you need to add a new lock in the Locks section (see
<xref linkend="fig-jenkins-build-lock"/>). This lock will then be
available to all build jobs on the server.</para>
<figure float="0" id="fig-jenkins-build-lock">
<title>Adding a new lock</title>
<mediaobject id="I_mediaobject10_d1e15295">
<imageobject role="print">
<imagedata fileref="figs/print/jtdg_1034.pdf" format="PDF"/>
<imageobject role="web">
<imagedata fileref="figs/web/jtdg_1034.png" format="PNG"/>
<para>Next, you need to set up each build job that will be using the
contended resource. In the Build Environment section, you will find a
Locks field. Tick the checkbox and select the lock you just created (see
<xref linkend="fig-jenkins-build-locks"/>). Once you do this for each
of the build jobs that need to access the resource in question, only one
of these build jobs will ever be able to run at a given<indexterm id="I_indexterm10_d1e15304" class="endofrange" startref="ch10-locks1" significance="normal"><primary/></indexterm><indexterm id="I_indexterm10_d1e15306" class="endofrange" startref="ch10-locks2" significance="normal"><primary/></indexterm><indexterm id="I_indexterm10_d1e15308" class="endofrange" startref="ch10-parallel" significance="normal"><primary/></indexterm> time.</para>
<figure float="0" id="fig-jenkins-build-locks">
<title>Configuring a build job to use a lock</title>
<mediaobject id="I_mediaobject10_d1e15314">
<imageobject role="print">
<imagedata fileref="figs/print/jtdg_1035.pdf" format="PDF"/>
<imageobject role="web">
<imagedata fileref="figs/web/jtdg_1035.png" format="PNG"/>
<sect1 id="sect-build-pipelines">
<title>Build Pipelines and Promotions</title>
<para>Continuous<indexterm class="startofrange" id="ch10-pipe" significance="normal"><primary>build pipelines</primary></indexterm><indexterm id="I_indexterm10_d1e15327" significance="normal"><primary>pipelines</primary><see>build pipelines</see></indexterm> Integration is not just about automatically building and
testing software, but can also help in the broader context of the software
product development and release life cycle. In many organizations, the
life of a particular version of an application or product starts out in
development. When it is deemed ready, it is passed on to a QA team for
testing. If they consider the version acceptable, they pass it on to
selected users for more testing in a User Acceptance Testing (UAT)
environment. And if the users are happy, it is shipped out into
production. Of course, there are almost as many variations on this as
there are software development teams, but one common principle is that
specific versions of your software are selected, according to certain
quality-related criteria, to <indexterm id="I_indexterm10_d1e15333" significance="normal"><primary>build pipelines</primary><secondary>promotions in</secondary></indexterm><indexterm id="I_indexterm10_d1e15338" significance="normal"><primary>promotions</primary></indexterm>be “promoted” to the next stage of the life cycle. This is
known as build promotion, and the broader process is known as a build
pipeline. In this section, we will look at how you can implement build
pipelines using Jenkins.</para>
<sect2 id="jenkins-maven-releases">
<title>Managing Maven Releases with the M2Release Plugin</title>
<para>An important part of any build pipeline is a well-defined release
strategy. This involves, among other things, deciding how and when to
cut a new release, and how to identify it with a unique label or version
number. If <indexterm class="startofrange" id="ch10-numbers1" significance="normal"><primary>build pipelines</primary><secondary>Maven version numbers for</secondary></indexterm><indexterm class="startofrange" id="ch10-numbers2" significance="normal"><primary>Maven</primary><secondary>version numbers for</secondary></indexterm><indexterm class="startofrange" id="ch10-numbers3" significance="normal"><primary>version numbers, Maven</primary></indexterm>you are working with Maven projects, using the <indexterm id="I_indexterm10_d1e15361" significance="normal"><primary>plugins</primary><secondary>Maven Release</secondary></indexterm><indexterm id="I_indexterm10_d1e15366" significance="normal"><primary>Maven Release plugin</primary></indexterm>Maven Release plugin to handle version numbers comes as a
highly recommended practice.</para>
<para>Maven projects use well-defined and well-structured version
numbers. A typical version number is made up of three digits (e.g.,
“1.0.1”). Developers work on SNAPSHOT versions (e.g.,“1.0.1-SNAPSHOT”),
which, as the name would indicate, are not designed to be definitive.
The definitive releases (e.g., “1.0.1”) are built once and deployed to
the local enterprise repository (or the central Maven repository for
open source libraries), where they can be used in turn by other
projects. The version numbers used in Maven artifacts are a critical
part of Maven’s dependency management system, and it is strongly advised
to stick to the Maven conventions.</para>
<para>The Maven Release plugin helps automates the process of updating
Maven version numbers in your projects. In a nutshell, it verifies,
builds and tests your application, bumps up the version numbers, updates
your version control system with the appropriate tags, and deploys the
released versions of your artifacts to your Maven repository. This is a
tedious task to do by hand, so the Maven Release plugin is an excellent
way to automate things.</para>
<para>However the Maven Release plugin can be fickle, too. Uncommitted
or modified local files can cause the process to fail, for example. The
process is also time-consuming and CPU intensive, especially for large
projects: it builds the application and runs the entire set of unit and
integration tests several times, checks out a fresh copy of the source
code from the repository, and uploads many artifacts to the Enterprise
repository. Indeed, this is not the sort of thing you want running on a
developer machine.</para>
<para>So it makes good sense to run this process on your build
<para>One way to do this is to set up a special manual build job to
invoke the Maven Release plugin. However, the M2Release plugin proposes
a simpler approach. Using this <phrase role="keep-together">plugin</phrase>, you can add the ability to build a
Maven release version in an existing build job. This way you can avoid
duplicating build jobs unnecessarily, making build job maintenance
<para>Once you have installed this plugin, you can define any build job
to also propose a manual Maven Release step. You do this by ticking the
“Maven release build” checkbox in the Build Environment section (see
<xref linkend="fig-build-m2release-plugin"/>). Here, you define the
goals you want to execute to trigger the build (typically
<literal moreinfo="none">release:prepare release:perform</literal>).</para>
<figure float="none" id="fig-build-m2release-plugin">
<title>Configuring a Maven release using the M2Release plugin</title>
<mediaobject id="I_mediaobject10_d1e15393">
<imageobject role="print">
<imagedata fileref="figs/print/jtdg_1036.pdf" format="PDF"/>
<imageobject role="web">
<imagedata fileref="figs/web/jtdg_1036.png" format="PNG"/>
<para>Once you have set this up, you can trigger a Maven release
manually using a new menu option called “Perform Maven Release” (see
<xref linkend="fig-jenkins-m2-release-menu"/>).</para>
<figure float="none" id="fig-jenkins-m2-release-menu">
<title>The Perform Maven Release menu option</title>
<mediaobject id="I_mediaobject10_d1e15405">
<imageobject role="print">
<imagedata fileref="figs/print/jtdg_1037.pdf" format="PDF"/>
<imageobject role="web">
<imagedata fileref="figs/web/jtdg_1037.png" format="PNG"/>
<para>This will kick off a special build job using the goals you
provided in the plugin configuration (see <xref linkend="fig-jenkins-perform-release"/>). Jenkins gives you the option
to either use the default version numbers provided by Maven (for
example, version 1.0.1-SNAPSHOT will be released as version 1.0.1, and
the development version number bumped up to 1.0.2-<phrase role="keep-together">SNAPSHOT</phrase>), or to provide your own custom
numbers. If you want to release a major version, for example, you might
choose to manually specify 1.1.0 as the release version number and
1.1.1-SNAPSHOT as the next development version number.</para>
<para>If you have a multimodule Maven project, you can choose to provide
a single version number configuration for all modules, or provide a
different version number update for each module. Note that it is
generally not recommended practice to provide different version numbers
for different modules in a multimodule project.</para>
<figure float="none" id="fig-jenkins-perform-release">
<title>Performing a Maven release in Jenkins</title>
<mediaobject id="I_mediaobject10_d1e15423">
<imageobject role="print">
<imagedata fileref="figs/print/jtdg_1038.pdf" format="PDF"/>
<imageobject role="web">
<imagedata fileref="figs/web/jtdg_1038.png" format="PNG"/>
<para>Depending on your SCM configuration, you may also need to provide
a valid SCM username and password to allow Maven to create tags in your
source code repository.</para>
<para>The <indexterm id="I_indexterm10_d1e15432" significance="normal"><primary>Nexus</primary><secondary>Enterprise Repository Manager</secondary></indexterm>professional edition of the Nexus Enterprise Repository
provides a feature called Staging Repositories, which is a way of
deploying artifacts to a special staging area for further tests before
releasing them officially. If you are using this feature, you need to
fine-tune your build server configuration for best results.</para>
<para>Nexus Professional works by creating a new staging area for each
unique IP Address, deploy users and HTTP User agent. A given Jenkins
build machine will always have the same IP address and user. However,
you will typically want to have a separate staging area for each build.
The trick, then, is to configure Maven to use a unique HTTP User-Agent
for the deployment process. You can do this by configuring the <filename moreinfo="none">settings.xml</filename> file on your build server to
contain something along the following lines (the ID must match the ID
for the release repository in the deployment section<indexterm id="I_indexterm10_d1e15443" class="endofrange" startref="ch10-numbers1" significance="normal"><primary/></indexterm><indexterm id="I_indexterm10_d1e15445" class="endofrange" startref="ch10-numbers2" significance="normal"><primary/></indexterm><indexterm id="I_indexterm10_d1e15447" class="endofrange" startref="ch10-numbers3" significance="normal"><primary/></indexterm> of your project):</para>
<?dbfo-need height=”1in”?>
<programlisting id="I_programlisting10_d1e15451" format="linespecific"> &lt;server&gt;
&lt;value&gt;Maven m2Release (java:${java.vm.version} ${env.BUILD_TAG }&lt;/value&gt;
<sect2 id="sect-copying-artifacts">
<title>Copying Artifacts</title>
<para>During<indexterm class="startofrange" id="ch10-art1" significance="normal"><primary>build pipelines</primary><secondary>reusing artifacts in</secondary></indexterm><indexterm class="startofrange" id="ch10-art2" significance="normal"><primary>binary artifacts</primary><secondary>reusing in build pipeline</secondary></indexterm><indexterm id="I_indexterm10_d1e15468" significance="normal"><primary>artifacts</primary><see>binary artifacts</see></indexterm> a build process involving several build jobs, such as the
one illustrated in <xref linkend="fig-build-dependency-graph-join"/>,
it can sometimes be useful to reuse artifacts produced by one build job
in a subsequent build job. For example, you may want to run a series of
web tests in parallel on separate machines, using local application
servers for improved performance. In this case, it makes sense to
retrieve the exact binary artifact that was produced in the previous
build, rather than rebuilding it each time or, if you are using Maven,
relying on a SNAPSHOT build deployed to your enterprise repository.
Indeed, both these approaches may run the risk of inconsistent build
results: if you use a SNAPSHOT from the enterprise repository, for
example, you will be using the latest SNAPSHOT build, which may not
necessarily be the one built in the upstream build job.</para>
<para>The<indexterm id="I_indexterm10_d1e15478" significance="normal"><primary>plugins</primary><secondary>Copy Artifact</secondary></indexterm><indexterm id="I_indexterm10_d1e15483" significance="normal"><primary>Copy Artifact plugin</primary></indexterm> Copy Artifact plugin lets you copy artifacts from an
upstream build and reuse them in your current build. Once you have
installed this plugin and restarted Jenkins, you will be able to add a
new type of build step called “Copy artifacts from another project” to
your freestyle build jobs (see <xref linkend="fig-build-copy-artifacts"/>).</para>
<figure float="none" id="fig-build-copy-artifacts">
<title>Adding a “Copy artifacts from another project” build
<mediaobject id="I_mediaobject10_d1e15492">
<imageobject role="print">
<imagedata fileref="figs/print/jtdg_1039.pdf" format="PDF"/>
<imageobject role="web">
<imagedata fileref="figs/web/jtdg_1039.png" format="PNG"/>
<para>This new build step lets you copy artifacts from another project
into the workspace of the current project. You can specify any other
project, though most typically it will be one of the upstream build
jobs. And of course you can specify, with a great deal of flexibility
and precision, the exact artifacts that you want to copy.</para>
<para>You need to specify where to find the files you want in the other
build job’s workspace, and where Jenkins should put them in your current
project’s workspace. This can be a flexible regular expression (such as
<literal moreinfo="none">**/*.war</literal>, for any WAR file produced by the build
job), or it can be much more precise (such as
<literal moreinfo="none">gameoflife-web/target/gameoflife.war</literal>). Note that by
default, Jenkins will copy the directory structure along with the file
you retrieve, so if the WAR file you are after is nested inside the
<filename moreinfo="none">target</filename> directory of the
<literal moreinfo="none">gameoflife-web</literal> module, Jenkins will place it inside
the <filename moreinfo="none">gameoflife-web/target</filename> directory
in your current workspace. If this is not to your tastes, you can tick
the “Flatten directories” option to tell Jenkins to put all of the
artifacts at the root of the directory you specify (or, by default, in
your project workspace).</para>
<para>In many cases, you will simply want to retrieve artifacts from the
most recent successful build. However, sometimes you may want more
precision. The “Which builds” field lets you specify where to look for
artifacts in a number of other ways, including the latest saved build
(builds which have been marked to “keep forever”), the latest successful
build, or even a specific build number.</para>
<para>If you have installed the Build Promotion plugin (see <xref linkend="sect-build-promotion"/>), you can also select the latest
promoted artifact in a particular promotion process. To do this, choose
“Specify by permalink”, then choose the appropriate build promotion
process. This is an excellent way of ensuring a consistent and reliable
build pipeline. For example, you can configure a build promotion process
to trigger a build that copies a generated WAR file from the latest
promoted build and deploys it to a particular server. This ensures that
you deploy precisely the right binary file, even if other builds have
occurred since.</para>
<para>If you are copying artifacts from a multimodule Maven build job,
Jenkins will, by default, copy all of the artifacts from that build.
However often times you are only interested in one specific artifact
(such as the WAR artifact in a web application, for example.</para>
<para>This plugin is particularly useful when you need to run functional
or performance tests on your web application. It is often a useful
strategy to place these tests in a separate project, and not as part of
your main build process. This makes it easier to run these tests against
different servers or run the subsets of the tests in parallel, all the
while using the same binary artifact to deploy and test.</para>
<para>For example, imagine that you have a default build job called
<emphasis>gameoflife</emphasis> that generates a WAR file, and you would
like to deploy this WAR file to a local application server and run a
series of functional tests. Furthermore, you want to be able to do this
in parallel on several distributed machines.</para>
<para>One way to do this would be to create a dedicated Maven project
designed to run the functional tests against an arbitrary server. Then,
you would set up a build job to run these functional tests. This build
job would use the Copy Artifact plugin to retrieve the latest WAR file
(or even the latest promoted WAR file, for more precision), and deploy
it to a local Tomcat instance using Cargo. This build job could then be
set up as a configurable (“matrix”) build job, and run in parallel on
several machines, possibly with extra configuration parameters to filter
the tests run by each build. Each build run would then be using its own
copy of the original WAR file. An example of a configuration like this
is illustrated in <xref linkend="fig-jenkins-copy-artifact-web"/>.</para>
<figure float="none" id="fig-jenkins-copy-artifact-web">
<title>Running web tests against a copied WAR file</title>
<mediaobject id="I_mediaobject10_d1e15539">
<imageobject role="print">
<imagedata fileref="figs/print/jtdg_1040.pdf" format="PDF"/>
<imageobject role="web">
<imagedata fileref="figs/web/jtdg_1040.png" format="PNG"/>
<para>The Copy Artifact plugin is not limited to fetching files from
conventional build jobs. You can also copy artifacts from
multiconfiguration build jobs (see <xref linkend="sect-multi-configuration-build-jobs"/>). Artifacts from each
executed configuration will be copied into the current workspace, each
in its own directory. Jenkins will build a directory structure using the
axes that were used in the multiconfiguration build. For example,
imagine we need to produce a highly-optimized version of our product for
a number of different targeted databases and application servers. We
could do this with a multiconfiguration build job like the one
illustrated in <xref linkend="fig-jenkins-multi-config-artifacts"/>.</para>
<figure float="0" id="fig-jenkins-multi-config-artifacts">
<title>Copying from a multiconfiguration build</title>
<mediaobject id="I_mediaobject10_d1e15553">
<imageobject role="print">
<imagedata fileref="figs/print/jtdg_1041.pdf" format="PDF"/>
<imageobject role="web">
<imagedata fileref="figs/web/jtdg_1041.png" format="PNG"/>
<para>The Copy Artifacts plugin can duplicate any and all of the
artifacts produced by this build job. If you specify a
multiconfiguration build as the source of your artifacts, the plugin
will copy artifacts from all of the configurations into the workspace of
the target build job, using a nested directory structure based on the
multiconfiguration build axes. For example, if you define the target
directory as <filename moreinfo="none">multi-config-artifacts</filename>, Jenkins will
copy artifacts into a number of subdirectories in the target directory,
each with a name corresponding to the particular set of configuration
parameters. So, using the build job illustrated in <xref linkend="fig-jenkins-multi-config-artifacts"/>, the JAR file customized
for Tomcat and MySql would be copied<indexterm id="I_indexterm10_d1e15565" class="endofrange" startref="ch10-art1" significance="normal"><primary/></indexterm><indexterm id="I_indexterm10_d1e15567" class="endofrange" startref="ch10-art2" significance="normal"><primary/></indexterm> to the <filename moreinfo="none">$WORKSPACE/multi-config-artifacts/APP_SERVER/tomcat/DATABASE/mysql</filename>
<sect2 id="sect-build-promotion">
<title>Build Promotions</title>
<para>In the <indexterm class="startofrange" id="ch10-promote1" significance="normal"><primary>build pipelines</primary><secondary>promotions in</secondary></indexterm><indexterm class="startofrange" id="ch10-promote2" significance="normal"><primary>promotions</primary></indexterm>world of Continuous Integration, not all builds are
created equal. For example, you may want to deploy the latest version of
your web application to a test server, but only after it has passed a
number of automated functional and load tests. Or you may want testers
to be able to flag certain builds as being ready for UAT deployment,
once they have completed their own testing.</para>
<para>The<indexterm id="I_indexterm10_d1e15589" significance="normal"><primary>plugins</primary><secondary>Promoted Builds</secondary></indexterm><indexterm id="I_indexterm10_d1e15594" significance="normal"><primary>Promoted Builds plugin</primary></indexterm> Promoted Builds plugin lets you identify specific builds
that have met additional quality criteria, and to trigger actions on
these builds. For example, you may build a web application in on build
job, run a series of automated web tests in a subsequent build, and then
deploy the WAR file generated to the UAT server for further manual
<para>Let’s see how this works in practice. In the project illustrated
above, a default build job (<command moreinfo="none">phoenix-default</command>) runs unit and some
integration tests, and produces a WAR file. This WAR file is then reused
for more extensive integration tests (in the <command moreinfo="none">phoenix-integration-tests</command> build job) and then
for a series of automated web tests (in the <command moreinfo="none">phoenix-web-test</command> build job). If the build
passes the automated web tests, we would like to deploy the application
to a functional testing environment where it can be tested by human
testers. The deployment to this environment is implemented in the
<command moreinfo="none">phoenix-test-deploy</command> build job. Once
the testers have validated a version, it can be promoted into UAT, and
then into production. The full promotion strategy is illustrated in
<xref linkend="fig-jenkins-build-promotion-jobs"/>.</para>
<figure float="none" id="fig-jenkins-build-promotion-jobs">
<title>Build jobs in the promotion process</title>
<mediaobject id="I_mediaobject10_d1e15617">
<imageobject role="print">
<imagedata fileref="figs/print/jtdg_1042.pdf" format="PDF"/>
<imageobject role="web">
<imagedata fileref="figs/web/jtdg_1042.png" format="PNG"/>
<para>This strategy is easy to implement using the Promoted Builds
plugin. Once you have installed this in the usual way, you will find a
new “Promote builds when” checkbox on the job configuration page. You
use this option to set up build promotion processes. You define one or
more build promotion processes in the initial build job of process
(<command moreinfo="none">phoenix-default</command> in this example), as
illustrated in <xref linkend="fig-jenkins-build-promotion"/>. A build
job may be the starting point of several build promotion processes, some
automated, and some manual. In <xref linkend="fig-jenkins-build-promotion"/>, for example, there is an
automated build promotion process called
<emphasis>promote-to-test</emphasis> and a manual one called
<emphasis>promote-to-uat</emphasis>. Automated build promotion processes
are triggered by the results of downstream build jobs. Manual <phrase role="keep-together">promotion</phrase> processes (indicated by ticking
the ‘Only when manually approved’ checkbox) can only be triggered by
user intervention.</para>
<figure float="none" id="fig-jenkins-build-promotion">
<title>Configuring a build promotion process</title>
<mediaobject id="I_mediaobject10_d1e15644">
<imageobject role="print">
<imagedata fileref="figs/print/jtdg_1043.pdf" format="PDF"/>
<imageobject role="web">
<imagedata fileref="figs/web/jtdg_1043.png" format="PNG"/>
<para>Let’s look at configuring the automated
<emphasis>promote-to-test</emphasis> build process.</para>
<para>The first thing you need to define is how this build promotion
process will be triggered. Build promotion can be either automatic,
based on the result of a downstream build job, or manually activated by
a user. In <xref linkend="fig-jenkins-build-promotion"/>, the build
promotion for this build job will be automatically triggered when the
automated web tests (executed by the <command moreinfo="none">phoenix-web-tests</command> build job) are
<para>You can also have certain build jobs that can only be promoted
manually, as illustrated in <xref linkend="fig-jenkins-manual-build-promotion"/>. Manual build promotion
is used for cases where human intervention is needed to approve a build
promotion. Deployment to UAT or production are common examples of this.
Another example is where you want to temporarily suspend automatic build
promotions for a short period, such as nearing a release.</para>
<para>Manual builds, as the name suggests, need to be manually approved
to be executed. If the promotion process is to trigger a parameterized
build job, you can also provide parameters that the approver will need
to enter when approving. In some cases, it can also be useful to
designate certain users who are allowed to activate the manual
promotion. You can do this by specifying a list of users or groups in
the Approvers list.</para>
<figure float="0" id="fig-jenkins-manual-build-promotion">
<title>Configuring a manual build promotion process</title>
<mediaobject id="I_mediaobject10_d1e15671">
<imageobject role="print">
<imagedata fileref="figs/print/jtdg_1044.pdf" format="PDF"/>
<imageobject role="web">
<imagedata fileref="figs/web/jtdg_1044.png" format="PNG"/>
<para>Sometimes, it is useful to give some context to the person
approving a promotion. When you set up a manual promotion process, you
can also specify other conditions which must be met, in particular
downstream (or upstream) build jobs which must have been built
successfully (see <xref linkend="fig-jenkins-promotion-details"/>).
These will appear in the “Met Qualifications” (for the successful build
jobs) and in “Unmet Qualifications” (for the build jobs that failed or
have not been executed yet).</para>
<figure float="0" id="fig-jenkins-promotion-details">
<title>Viewing the details of a build promotion</title>
<mediaobject id="I_mediaobject10_d1e15683">
<imageobject role="print">
<imagedata fileref="figs/print/jtdg_1045.pdf" format="PDF"/>
<imageobject role="web">
<imagedata fileref="figs/web/jtdg_1045.png" format="PNG"/>
<para>Next you need to tell Jenkins what to do when the build is
promoted. You do this by adding actions, just like in a freestyle build
job. This makes build promotions extremely flexible, as you can add
virtually any action available to a normal freestyle build job,
including any additional steps made available by the plugins installed
on your Jenkins instance. Common actions include invoking Maven or Ant
scripts, deploying artifacts to a Maven repository, or triggering
another build job.</para>
<para>One important thing to remember here is that you cannot rely on
files in the workspace when promoting your build. Indeed, by the time
you promote the build, either automatically or manually, other build
jobs may have deleted or rewritten the files you need to use. For this
reason, it is unwise, for example, to deploy a WAR file directly from
the workspace to an application server from within a build promotion
process. A more robust solution is to trigger a separate build job and
to use the Copy Artifacts plugin (see <xref linkend="sect-copying-artifacts"/>) to retrieve precisely the right
file. In this case, you will be copying artifacts that you have
configured Jenkins to conserve, rather than copying the files directly
from the workspace.</para>
<para><indexterm id="I_indexterm10_d1e15695" significance="normal"><primary>fingerprints</primary></indexterm>For build promotion to work correctly, Jenkins needs to be
able to precisely link downstream build jobs to upstream ones. The more
accurate way to do this is by using fingerprints. In Jenkins, a
fingerprint is the MD5 checksum a file produced by or used in a build
job. By matching fingerprints, Jenkins is able to identify all of the
builds which use a particular file.</para>
<para>In the context of build promotion, a common strategy is to build
your application once, and then to run tests against the generated
binary files in a series of downstream build jobs. This approach works
well with build promotion, but you need to ensure that Jenkins
fingerprints the files that are shared or copied between build jobs. In
the example shown in <xref linkend="fig-jenkins-build-promotion"/>, for
instance, we need to do two things (<xref linkend="fig-jenkins-build-promotion-fingerprints"/>). First, we need
to archive the generated WAR file so that it can be reused in the
downstream project. Secondly, we need to record a fingerprint of the
archived artifacts. You do this by ticking the “Record fingerprints of
files to track usage” option, and specifying the files you want to
fingerprint. A useful shortcut is simply to fingerprint all archived
files, since these are the files that will typically be retrieved and
reused by the downstream build jobs.</para>
<figure float="0" id="fig-jenkins-build-promotion-fingerprints">
<title>Using fingerprints in the build promotion process</title>
<mediaobject id="I_mediaobject10_d1e15708">
<imageobject role="print">
<imagedata fileref="figs/print/jtdg_1046.pdf" format="PDF"/>
<imageobject role="web">
<imagedata fileref="figs/web/jtdg_1046.png" format="PNG"/>
<para>This is all you need to do to configure the initial build process.
The next step is to configure the integration tests executed in the
<command moreinfo="none">phoenix-integration</command> build job. Here,
we use the Copy Artifact plugin to retrieve the WAR file generated by
the <phrase role="keep-together"><command moreinfo="none">phoenix-default</command></phrase> build job (see <xref linkend="fig-jenkins-build-promotion-integration"/>). Since this build
job is triggered immediately after the <command moreinfo="none">phoenix-default</command> build job, we can simply fetch
the WAR file from the latest successful build.</para>
<figure float="none" id="fig-jenkins-build-promotion-integration">
<title>Fetching the WAR file from the upstream build job</title>
<mediaobject id="I_mediaobject10_d1e15730">
<imageobject role="print">
<imagedata fileref="figs/print/jtdg_1047.pdf" format="PDF"/>
<imageobject role="web">
<imagedata fileref="figs/web/jtdg_1047.png" format="PNG"/>
<para>This is not quite all we need to do for the integration tests,
however. The <command moreinfo="none">phoenix-integration</command>
build job is followed by the <command moreinfo="none">phoenix-web</command> build job, which executes the
automated web tests. To ensure that the same WAR file is used at each
stage of the build process, we need to retrieve it from the upstream
<command moreinfo="none">phoenix-integration</command> build job, and
not from the original <command moreinfo="none">phoenix-default</command>
build job (which may have been executed again in the meantime). So we
also need to archive the WAR file in the <command moreinfo="none">phoenix-integration</command> build job (see <xref linkend="fig-jenkins-promotion-integration-archive"/>).</para>
<figure float="0" id="fig-jenkins-promotion-integration-archive">
<title>Archiving the WAR file for use in the downstream job</title>
<mediaobject id="I_mediaobject10_d1e15759">
<imageobject role="print">
<imagedata fileref="figs/print/jtdg_1048.pdf" format="PDF"/>
<imageobject role="web">
<imagedata fileref="figs/web/jtdg_1048.png" format="PNG"/>
<para>In the <command moreinfo="none">phoenix-web</command> build job,
we then fetch the WAR file from the <phrase role="keep-together"><command moreinfo="none">phoenix-integration</command></phrase> build job, using
a configuration very similar to the one shown above (see <xref linkend="fig-jenkins-promotion-copy-from-integration"/>).</para>
<figure float="none" id="fig-jenkins-promotion-copy-from-integration">
<title>Fetching the WAR file from the integration job</title>
<mediaobject id="I_mediaobject10_d1e15778">
<imageobject role="print">
<imagedata fileref="figs/print/jtdg_1049.pdf" format="PDF"/>
<imageobject role="web">
<imagedata fileref="figs/web/jtdg_1049.png" format="PNG"/>
<para>For the build promotion process to work properly, there is one
more important thing we need to configure in the <command moreinfo="none">phoenix-web</command> build job. As we discussed
earlier, Jenkins needs to be able to be sure that the WAR file used in
these tests is the same one generated by the original build. We do this
by activating fingerprinting on the WAR file we fetched from the
<command moreinfo="none">phoenix-integration</command> build job (which,
remember, was originally built by the <command moreinfo="none">phoenix-default</command> build job). Since we have
copied this WAR file into the workspace, a configuration like the one in
<xref linkend="fig-jenkins-promotion-fingerprint-web"/> will work just
<figure float="none" id="fig-jenkins-promotion-fingerprint-web">
<title>We need to determine the fingerprint of the WAR file we
<mediaobject id="I_mediaobject10_d1e15799">
<imageobject role="print">
<imagedata fileref="figs/print/jtdg_1050.pdf" format="PDF"/>
<imageobject role="web">
<imagedata fileref="figs/web/jtdg_1050.png" format="PNG"/>
<para>The final step is to configure the <command moreinfo="none">phoenix-deploy-to-test</command> build job to retrieve
the last promoted WAR file (rather than just the last successful one).
To do this, we use the Copy Artifact plugin again, but this time we
choose the “Specified by permalink” option. Here Jenkins will propose,
among other things, the build promotion processes configured for the
build job you are copying from. So, in <xref linkend="fig-jenkins-copy-promoted-war"/>, we are fetching the last
promoted WAR file build by the <command moreinfo="none">phoenix-default</command> job, which is precisely what
we want.</para>
<figure float="none" id="fig-jenkins-copy-promoted-war">
<title>Fetching the latest promoted WAR file</title>
<mediaobject id="I_mediaobject10_d1e15817">
<imageobject role="print">
<imagedata fileref="figs/print/jtdg_1051.pdf" format="PDF"/>
<imageobject role="web">
<imagedata fileref="figs/web/jtdg_1051.png" format="PNG"/>
<para>Our promotion process is now ready for action. When the automated
web tests succeed for a particular build, the original build job will be
promoted and the corresponding WAR file deployed to the test
environment. Promoted builds are indicated by a star in the build
history (see <xref linkend="fig-jenkins-promoted-build-history"/>). By
default, the stars are yellow, but you can configure the color of the
star in the build promotion setup.</para>
<figure float="0" id="fig-jenkins-promoted-build-history">
<title>Promoted builds are indicated by a star in the build
<mediaobject id="I_mediaobject10_d1e15829">
<imageobject role="print">
<imagedata fileref="figs/print/jtdg_1052.pdf" format="PDF"/>
<imageobject role="web">
<imagedata fileref="figs/web/jtdg_1052.png" format="PNG"/>
<para>You can also use the “Promotion Status” menu entry (or click on
the colored star in the build history) to view the details of a
particular build promotion, and even to rerun a promotion manually (see
<xref linkend="fig-jenkins-promotion-details"/>). Any build promotion
can be triggered manually, by clicking on “Force promotion” (if this
build job has never been promoted) <indexterm id="I_indexterm10_d1e15838" class="endofrange" startref="ch10-promote1" significance="normal"><primary/></indexterm><indexterm id="I_indexterm10_d1e15840" class="endofrange" startref="ch10-promote2" significance="normal"><primary/></indexterm>or “Re-execute promotion” (if it has).</para>
<title>Aggregating Test Results</title>
<para>When<indexterm class="startofrange" id="ch10-agg1" significance="normal"><primary>build pipelines</primary><secondary>aggregating test results for</secondary></indexterm><indexterm class="startofrange" id="ch10-agg2" significance="normal"><primary>tests</primary><secondary>reports from</secondary><tertiary>aggregating</tertiary></indexterm><indexterm class="startofrange" id="ch10-agg3" significance="normal"><primary>aggregate test results</primary></indexterm><indexterm class="startofrange" id="ch10-agg4" significance="normal"><primary>reporting</primary><secondary>test results</secondary><tertiary>aggregating</tertiary></indexterm> distributing different types of tests across different
build jobs, it is easy to loose a global vision about the overall test
results. Test results are scattered among the various build jobs,
without a central place to see the total number of executed and failing
<para>A good way to avoid this problem is to use the Aggregated Test
Results feature of Jenkins. This will retrieve any test results recorded
in the downstream jobs, and aggregate them in the upstream build job.
You can configure this in the initial (upstream) build job by ticking
the “Aggregate downstream test results” option (see <xref linkend="fig-jenkins-aggregate-downstream-tests"/>).</para>
<figure float="0" id="fig-jenkins-aggregate-downstream-tests">
<title>Reporting on aggregate test results</title>
<mediaobject id="I_mediaobject10_d1e15878">
<imageobject role="print">
<imagedata fileref="figs/print/jtdg_1053.pdf" format="PDF"/>
<imageobject role="web">
<imagedata fileref="figs/web/jtdg_1053.png" format="PNG"/>
<para>The aggregate test results can be seen in the build details page
(see <xref linkend="fig-jenkins-show-aggregate-tests"/>).
Unfortunately, these aggregate test results do not appear in the overall
test results, but you can display the full list of tests executed by
clicking on the Aggregate Test Result link on the individual build
<figure float="0" id="fig-jenkins-show-aggregate-tests">
<title>Viewing aggregate test results</title>
<mediaobject id="I_mediaobject10_d1e15890">
<imageobject role="print">
<imagedata fileref="figs/print/jtdg_1054.pdf" format="PDF"/>
<imageobject role="web">
<imagedata fileref="figs/web/jtdg_1054.png" format="PNG"/>
<para>For this to work correctly, you need to ensure that you have
configured<indexterm id="I_indexterm10_d1e15897" significance="normal"><primary>fingerprints</primary></indexterm> fingerprinting for the binary files you use at each
stage. Jenkins will only aggregate downstream test results from builds
containing an artifact with the <indexterm id="I_indexterm10_d1e15901" class="endofrange" startref="ch10-agg1" significance="normal"><primary/></indexterm><indexterm id="I_indexterm10_d1e15903" class="endofrange" startref="ch10-agg2" significance="normal"><primary/></indexterm><indexterm id="I_indexterm10_d1e15905" class="endofrange" startref="ch10-agg3" significance="normal"><primary/></indexterm><indexterm id="I_indexterm10_d1e15907" class="endofrange" startref="ch10-agg4" significance="normal"><primary/></indexterm>same fingerprint.</para>
<title>Build Pipelines</title>
<para>The<indexterm class="startofrange" id="ch10-deploy1" significance="normal"><primary>build pipelines</primary><secondary>deployment pipelines from</secondary></indexterm><indexterm class="startofrange" id="ch10-deploy2" significance="normal"><primary>deployment pipelines</primary></indexterm> final plugin we will be looking at in this section is the
Build Pipeline plugin. The Build Pipelines plugin takes the idea of
build promotion further, and helps you design and monitor deployment
pipelines. A deployment pipeline is a way of orchestrating your build
through a series of quality gates, with automated or manual approval
processes at each stage, culminating with deployment into
<para>The <indexterm id="I_indexterm10_d1e15926" significance="normal"><primary>Build Pipeline plugin</primary></indexterm><indexterm id="I_indexterm10_d1e15929" significance="normal"><primary>plugins</primary><secondary>Build Pipeline</secondary></indexterm>Build Pipeline plugin provides an alternative way to
define downstream build jobs. A build pipeline, unlike conventional
downstream dependencies, is considered to be a linear process, a series
of build jobs executed in sequence.</para>
<para>To use this plugin, start by configuring the downstream build jobs
for each build job in the pipeline, using the “Build other projects”
field just as you would normally do. The Build Pipelines plugin uses the
standard upstream and downstream build configurations, and for automatic
steps this is all you need to do. However the Build Pipeline plugin also
supports manual build steps, where a user has to manually approve the
next step. For manual steps, you also need to configure In the <command moreinfo="none">Post-build Actions</command> of your upstream build job:
just tick the “Build Pipeline Plugin -&gt; Specify Downstream Project”
box, select the next step in your project, and tick the “Require manual
build executor” option (see <xref linkend="fig-jenkins-build-pipeline-downstream"/>).</para>
<figure float="none" id="fig-jenkins-build-pipeline-downstream">
<title>Configuring a manual step in the build pipeline</title>
<mediaobject id="I_mediaobject10_d1e15945">
<imageobject role="print">
<imagedata fileref="figs/print/jtdg_1055.pdf" format="PDF"/>
<imageobject role="web">
<imagedata fileref="figs/web/jtdg_1055.png" format="PNG"/>
<para>Once you have set up your build process to your satisfaction, you
can configure the build pipeline view. You can create this view just
like any other view (see <xref linkend="fig-jenkins-build-pipeline-view"/>).</para>
<figure float="none" id="fig-jenkins-build-pipeline-view">
<title>Creating a Build Pipeline view</title>
<mediaobject id="I_mediaobject10_d1e15957">
<imageobject role="print">
<imagedata fileref="figs/print/jtdg_1056.pdf" format="PDF"/>
<imageobject role="web">
<imagedata fileref="figs/web/jtdg_1056.png" format="PNG"/>
<para>There is a trick when it comes to configuring the view, however.
At the time of writing, there is no menu option or button that lets you
configure the view directly. In fact, you need to enter the URL
manually. Fortunately, this is not difficult: just add <filename moreinfo="none">/configure</filename> to the end of the URL shown when
you are displaying this view. For example, if you have named your view
“phoenix-build-pipeline”, as shown here, the URL to configure this view
would be <filename moreinfo="none">http://my_jenkins_server/view/phoenix-build-pipeline</filename>.
(see <xref linkend="fig-jenkins-build-pipeline-configure"/>).</para>
<figure float="0" id="fig-jenkins-build-pipeline-configure">
<title>Configuring a Build Pipeline view</title>
<mediaobject id="I_mediaobject10_d1e15975">
<imageobject role="print">
<imagedata fileref="figs/print/jtdg_1057.pdf" format="PDF"/>
<imageobject role="web">
<imagedata fileref="figs/web/jtdg_1057.png" format="PNG"/>
<para>The most important thing to configure in this screen is the
initial job. This marks the starting point of your build pipeline. You
can define multiple build pipeline views, each with a different starting
job. You can also configure the maximum number of build sequences to
appear on the screen at once.</para>
<para>Once you have configured the starting point, you can return to the
view to see the current state of your build pipeline. Jenkins displays
the successive related build jobs horizontally, using a color to
indicate the outcome of each build (<xref linkend="fig-jenkins-build-pipeline"/>). There is a column for each
build job in the pipeline. Whenever the initial build job kicks off, a
new row appears on this page. As the build progresses through the
successive build jobs in the pipeline, Jenkins will add a colored box in
the successive columns, indicating the outcome of each stage. You can
click on the box to drill down into a particular build result for more
details. Finally, if a manual execution is required, a button will be
displayed where the user can trigger the job.</para>
<figure float="0" id="fig-jenkins-build-pipeline">
<title>A Build Pipeline in action</title>
<mediaobject id="I_mediaobject10_d1e15990">
<imageobject role="print">
<imagedata fileref="figs/print/jtdg_1058.pdf" format="PDF"/>
<imageobject role="web">
<imagedata fileref="figs/web/jtdg_1058.png" format="PNG"/>
<?dbfo-need height=”1in”?>
<para>This plugin is still relatively new, and does not integrate with
all of the other plugins we have seen here. In particular, it is really
designed for a linear build pipeline, and does not cope well with
branches or parallel build jobs. Nevertheless, it does give an excellent
global vision of a build<indexterm id="I_indexterm10_d1e15998" class="endofrange" startref="ch10-deploy1" significance="normal"><primary/></indexterm><indexterm id="I_indexterm10_d1e16000" class="endofrange" startref="ch10-deploy2" significance="normal"><primary/></indexterm><indexterm id="I_indexterm10_d1e16002" class="endofrange" startref="ch10-pipe" significance="normal"><primary/></indexterm> pipeline.</para>
<sect1 id="I_sect110_d1e16005">
<para>Continuous Integration build jobs are much more than simply the
scheduled execution of build scripts. In this chapter we have reviewed a
number of tools and techniques enabling you to go beyond your typical
build jobs, combining them so that they can work together as part of a
larger process. We have seen how parameterized and multiconfiguration
build jobs add an element of flexibility to ordinary build jobs by
allowing you to run the same build job with different sets of parameters.
Other tools help coordinate and orchestrate groups of related build jobs.
The Joins and Locks and Latches plugins helps you coordinate build jobs
running in parallel. And the Build Promotions and Build Pipelines plugins,
with the help of the Copy Artifacts plugin, make it relatively easy to
design and configure complex build promotion strategies for your
Jump to Line
Something went wrong with that request. Please try again.