Hudson CI, or the new fork Jenkins CI, is a Java web server application to automate and control the building of projects.
You can download Hudson (formally known as Hudson Open Source Continuous Integration Server from the Eclipse Foundation) from http://eclipse.org/hudson/download.php.
The next step is to launch the embedded Jetty servlet container:
$ java -jar Hudson.<version>.war
Jenkins can be downloaded from http://mirrors.jenkins-ci.org/war/latest/jenkins.war.
To launch Jenkins or deploy a WAR file on a servlet container, execute the following command:
$ java -jar jenkins.war
Then, we can connect to http://localhost:8080
and click on Finish.
To configure Hudson (and Jenkins) CI, we need to accomplish the following steps:
Hudson (and Jenkins) is based on jobs; jobs can be scheduled or launched by users. Jobs can execute a shell script, a Maven goal, an Ant target, or a specific action defined by a plugin. In our examples, we will work with Maven and Maven-Ant jobs.
To create a new job, perform the following steps:
In the workspace directory, enter the following pom.xml
code:
<project> <modelVersion>4.0.0</modelVersion> <name>My Hudson Test</name> <groupId>com.mycompany.projects</groupId> <artifactId>my-first-maven-project</artifactId> <version>1.0-SNAPSHOT</version> <packaging>jar</packaging> </project>
Finally, execute the job. Click on build job from the Hudson home screen or from the menu on the left-hand side. See the output console to monitor the build. Hudson launches Maven on the given workspace directory.
The following output will be shown:
Started by user anonymous [INFO] Using Maven 3 installation: Maven3 … [INFO] ------------------------------------------------------ [INFO] Building My Hudson Test 1.0-SNAPSHOT [INFO] ------------------------------------------------------ … [DEBUG] Waiting for process to finish [DEBUG] Result: 0 Finished: SUCCESS
The previous example is completely didactic since it does not introduce anything interesting. Hudson provides an easy way to customize a job by asking the user for some parameters. In this example, we will change the pom.xml
version through Hudson and Maven Release Plugin.
From the Hudson home screen, select the job configured in the previous example (or duplicate it). From the left-hand side menu, perform the following steps:
developmentVersion
(see the following screenshot):The next step is to change the Maven goal to release:update-versions
. In the build section, change clean install
to release:update-versions
(see the following screenshot):
Finally, we need to add the maven-release-plugin
to the pom.xml
file. Open the pom.xml
file located in your workspace and add the following lines:
[…] <build> <plugins> <plugin> <artifactId>maven-release-plugin</artifactId> <version>2.5</version> <configuration> <releaseProfiles>release</releaseProfiles> <goals>deploy assembly:single</goals> </configuration> </plugin> </plugins> </build> […]
Now, we are ready to launch the job. Select the configured job from the Maven home screen. Click on the Build Now button.
Hudson will require the version number; provide the version number in the x.x.x-SNAPSHOT
format.
The result appears like this:
[INFO] Transforming 'My Hudson Test 2'... [INFO] Cleaning up after release... [INFO] ------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------
Finally, reopen the pom.xml
file located in your workspace; it will appear changed to the given version number.
The following list shows the basic steps to release a new artifact (see the following screenshot):
pom.xml
file.svn
tag and create the package.SNAPSHOT
version to the pom.xml
file and commit changes to the development stage.This work can be easily done by Maven Release Plugin.
The building step is formally complete when all the unit tests are passed. Unit tests are typically written and run by developers to ensure that the code meets its design and functionalities, but it is good practice to rerun all the tests during the software release. To enable Maven to run the unit tests, we need to define Surefire Plugin (see Chapter 3, Writing Plugins) in pom.xml
:
[…] <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>2.17</version> </plugin> […]
Surefire Plugin will launch all the unit tests (Junit or TestNG) defined by the developer.
Sometimes, you might need to skip the execution of unit tests. There are two ways to skip tests:
skipTest
parameter. Use one of the following three commands:$ mvn clean install –DskipTests $ mvn clean install –Dmaven.skip.test=true $ mvn test –Dmaven.skip.test=true
[…] <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>2.17</version> <configuration> <skipTests>true</skipTests> </configuration> </plugin> […]
Finally, we can configure Hudson to ask the user about the test policy to apply. Perform the following steps from the left-hand side menu:
skipTests
(see the following screenshot):[…]
<configuration>
<skipTests>${skipTests}</skipTests>
</configuration>
[…]
Through these few steps, the user will control the execution of the unit test in order to enable or disable it. From a theoretical point of view, automatic unit test execution should be enabled and executed every time before any release; also, it is bad practice to allow the final user to control this step. Unfortunately, the devil is in the details, and this practice is the common practice in case of emergency.
A good compromise is to exclude some specific tests providing (through Hudson's parameter) a regular expression. A regular expression must be defined with the %regex[expression]
syntax and defined into the configuration
section:
[…] <configuration> <excludes> <exclude>%regex[.*[My|You].*Test.*]</exclude> </excludes> </configuration> […]
From our point of view, this solution is equivalent to the usage of the proposed skipTests
parameter since the user can specify all the tests. A second common approach is to use a scheduled Hudson job reporting the status of the report periodically.
One common way to grant a good level of software quality is to execute some common tasks periodically and publish these results on a site area. Hudson provides a large number of plugins to execute the unit (NUnit, JSUnit, JUnit, and TestNG) performance and functional tests and publish results on external (or internal) sites. Luckily, Surefire Plugin for JUnit tests is natively integrated, and it can be easily configured without any further installation.
A common practice is to define a new Hudson job scheduled every day (or trigger SCM changes).
From the Hudson home screen, click on the New Job option from the left-hand side menu and copy settings from an existing job or create a new one (see the following screenshot):
Configure the workspace and Maven build process like the previous job, but set Fail Mode to AT_END
:
AT_END
for the Fail Mode parameter (see the following screenshot):This parameter allows Maven to build all the modules, postponing any intermediate error up to the end of the entire build process.
The next step is to configure Hudson to publish the Surefire Plugin result:
Test report XMLs
field, write **/target/surefire-reports/*.xml
(see the following screenshot):These settings allow Hudson to parse the Surefire Plugin test result and publish it in the test result section (or in a Hudson dashboard). To see the test result trend, you can execute the job we just configured and see the latest test result (see the following screenshot):
Finally, we can schedule the job to run every day at midnight:
@midnight
.Hudson will execute the job every day at midnight and publish the test results. Alternatively, from the From Build-Triggers section, you can poll SCM for changes.
If the test task just described does not fail, it is a good idea to deploy the nightly build software on a shared environment. Unfortunately, there is a wide range of available plugins for all the platforms, and it depends on the strategy adopted (Weblogic, JBOSS, GlassFish, Tomcat, Job scheduling, Linux, and so on); therefore, it is not possible to suggest a unique strategy. In Chapter 2, Core Maven Concepts, we introduced the deployment plugin for JBOSS. The following table provides some basic Maven plugins that can be adopted to perform this step:
When the plugin has been configured, we can add a Maven 3 build step after the clean install
task from the previous job:
jboss-as:deploy
.Alternatively, you can use the dedicated Hudson plugins.
Now, the environment is ready to perform the integration tests. Integration tests can be configured like the unit tests of a dedicated project (which is already deployed) using Maven Failsafe Plugin.
To install Failsafe Plugin, configure pom.xml
as follows:
<project> […] <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-failsafe-plugin</artifactId> <version>2.17</version> </plugin> </plugins> […] </project>
When the plugin has been configured, we can add a Maven 3 build step after the jboss:deploy
task from the previous job:
goal
field, write failsafe:integration-test failsafe:verify
.Since we are using Surefire Plugin and Failsafe Plugin together, we have to make sure to use the correct naming convention to make it easier to identify which tests are being executed by which plugin. Failsafe Plugin will look for tests with the **/IT*.java
, **/*IT.java
, and **/*ITCase.java
patterns by default, but, since it is a branch of Surefire Plugin, it supports the include
and exclude
syntaxes.
Alternatively, you can develop some dedicated unit tests on each artifact and activate them through Maven profiles.
The previous job can be refined and improved by integrating a static code analysis tool. Static code analysis tools inspect the code for potential bugs, missing code styles, high complexities, missing tests, or wrong patterns. Static code analysis tools require the definition of a specific Maven plugin integrated with a Hudson Plugin. The following table reports a short list of the most common static analysis tools:
Other commercial-related products integrated with Hudson are JIRA, Clover, and Sonar.
FindBugs is one of the most interesting and complete tools. Since a complete discussion on all the plugins is outside the scope of this book, we can discover the power of the code analysis tools by only experiencing FindBugs.
Firstly, we need to install a Hudson Plugin by performing the following steps:
pom.xml
file, define the FindBugs Plugin as follows:<project> […] <reporting> <plugins> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>findbugs-maven-plugin</artifactId> <version>2.5.4</version> <configuration> <xmlOutput>true</xmlOutput> <threshold>Default</threshold> </configuration> </plugin> </plugins> </reporting> […] </project>
The next step is to configure the previous job:
site
(see the following screenshot).**/findbugsXml.xml
(see the following screenshot):The following lines should be displayed:
[FINDBUGS] Collecting findbugs analysis files... [FINDBUGS] Collecting findbugs analysis files... [FINDBUGS] Finding all files that match the pattern **/findbugsXml.xml [FINDBUGS] Parsing 1 files in … [FINDBUGS] Successfully parsed file …findbugsXml.xml of module with … warnings.
To see the FindBugs report, you can execute the job just configured. To see the latest result, click on FindBugs Warnings from the left-hand side menu.