Continuous Integration and Delivery with Hudson or Jenkins

Hudson CI, or the new fork Jenkins CI, is a Java web server application to automate and control the building of projects.

Note

Hudson is very similar to Jenkins, and they differ only in the sense of licensing policies, hosting, and some minimal functionalities; some authors work with both systems, but in this book, we will refer only to Hudson.

Installing Hudson

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

Note

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.

Configuring Hudson

To configure Hudson (and Jenkins) CI, we need to accomplish the following steps:

  1. Configuring the proxy: Navigate to Manage Hudson | Manage Plugins | Advanced, and then configure the proxy server (see the following screenshot):
    Configuring Hudson

    Hudson proxy configuration settings

  2. Installing plugins: Navigate to Manage Hudson | Manage Plugins, then check the Hudson Maven 3, Hudson Subversion Plugin, Maven2 Legacy Integration plugin, and Email-ext plugin options if they are not yet installed, and click on Install.
  3. Configuring JDK, Maven, and Ant (see the following screenshot): Navigate to Manage Hudson | Configure System, and then perform the following steps:
    • Click on Add Jdk, uncheck Install automatically, and provide the name and Java home
    • Click on Add Maven3, uncheck Install automatically, and provide the name and Maven home (refer to Chapter 1, Maven and Its Philosophy)
    • Click on Add Ant, uncheck Install automatically, and provide the name and Ant home
    Configuring Hudson

    Hudson installation configuration settings

  4. Configuring security (optional): The security configuration is not strictly required for the purpose of this book, but it is strongly encouraged to enable security. Navigate to Manage Hudson | Configure Security, click on Enable security, and enable Hudson's own user database or configure LDAP.
  5. Finally, restart Hudson.

Working with Hudson

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:

  1. Click on the New Job option from the left-hand side menu, ensure that the free-style job is checked, and provide the job name (see the following screenshot):
    Working with Hudson

    Hudson's new job

  2. On the Configuration Job panel, do the following:
    • Navigate to Advanced Options | Custom Workspace and provide the path of the workspace
    • From the Build section (see the following screenshot), navigate to Add build step | Invoke Maven 3
    Working with Hudson

    Hudson's invoke new step option

  3. Click on Save at the end of the page.

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

Working with Hudson interactively

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:

  1. Click on Configure Job.
  2. Enable This build is parameterized.
  3. Navigate to Add Parameter | String parameter.
  4. In the Name field, write developmentVersion (see the following screenshot):
    Working with Hudson interactively

    Configuring the development version in Hudson

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):

Working with Hudson interactively

Configuring the Maven release step in Hudson

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.

Tip

All the Maven actions are performed with the batch mode option, –B. You do not need to specify it.

Maven-Hudson integration to deliver a new artifact

The following list shows the basic steps to release a new artifact (see the following screenshot):

  1. Test the software (unit and integration test) and quality assurance.
  2. Fix bugs on the issue-tracking system.
  3. Assign a new version to the pom.xml file.
  4. Make a new svn tag and create the package.
  5. Assign a new SNAPSHOT version to the pom.xml file and commit changes to the development stage.

This work can be easily done by Maven Release Plugin.

Tip

This plugin can be easily integrated with Hudson/M2 Release Plugin. To install Hudson M2 Release Plugin, navigate to Manage Hudson | Plugin Manager from the available plugin list, look for the plugin and enable it, click on Install, and restart Hudson. We do not use this plugin.

Testing software automation

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.

Tip

From Version 2.7, Surefire Plugin will inspect the unit library (Junit version or TestNG), and it will activate the right provider automatically.

Sometimes, you might need to skip the execution of unit tests. There are two ways to skip tests:

  • Launch Maven with the 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
    
  • Configure Surefire Plugin to skip all the tests:
    […]
    <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:

  1. Click on Configure Job.
  2. Enable This build is parameterized.
  3. Click on Add Parameter | Boolean parameter.
  4. In the Name field, write skipTests (see the following screenshot):
    Testing software automation

    Hudson's configure skip test parameter

  5. The next step is to use the following property:
    […]
        <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.

Scheduling a test reporting

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):

Scheduling a test reporting

Configuring a new unit test job in Hudson

Configure the workspace and Maven build process like the previous job, but set Fail Mode to AT_END:

  1. From the Build section, click on Advanced.
  2. Select AT_END for the Fail Mode parameter (see the following screenshot):
    Scheduling a test reporting

    Hudson's configure build step

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:

  1. From the Post-Build section, enable Publish JUnit test result report.
  2. In the Test report XMLs field, write **/target/surefire-reports/*.xml (see the following screenshot):
    Scheduling a test reporting

    Hudson's configure Surefire report

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):

Scheduling a test reporting

Hudson's test report

Finally, we can schedule the job to run every day at midnight:

  1. From the Build-Triggers section, enable Build periodically.
  2. In the Schedule field, write @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.

Aligning the shared development environment

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:

Plugin

Description

weblogic-maven-plugin

This is the Weblogic deploy plugin. It is not available in the central repository.

jboss-as-maven-plugin

This is the JBoss deploy plugin.

tomcat7-maven-plugin

This is the Tomcat 7 deploy WAR plugin.

wagon-ssh-external

This plugin is used to deploy on an SSH external host.

maven-glassfish-plugin

This plugin is used to deploy on a GlassFish server.

When the plugin has been configured, we can add a Maven 3 build step after the clean install task from the previous job:

  1. Click on Configure Job.
  2. From the Build step section, add a new Maven 3 step.
  3. In the goal field, write jboss-as:deploy.

Alternatively, you can use the dedicated Hudson plugins.

Integration tests

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:

  1. Click on Configure Job.
  2. From the Build step section, add a new Maven 3 step.
  3. In the 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.

Static code analysis tools (FindBugs)

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:

Maven Plugin

Hudson Plugin

Description

findbugs-maven-plugin

FindBugs-Plug-in

FindBugs analyzes Java code from 1.0 to 1.7.

maven-checkstyle-plugin

Checkstyle Plug-in

Checkstyle checks Java code to adhere to a coding standard.

maven-pmd-plugin

PMD Plug-in

PMD finds common programming flaws such as unused variables, empty catch blocks, and unnecessary object creation. It supports Java, JavaScript, XML, and XSL.

cobertura-maven-plugin

Cobertura Plug-In

Cobertura checks the unit test coverage.

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:

  1. Navigate to Manage Hudson | Manage Plugins, check the FindBugs Plug-in option if not yet installed, and click on Install.
  2. In the 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:

  1. Click on Configure Job.
  2. From the Build step section, add a new Maven 3 step.
  3. In the Goals field, write site (see the following screenshot).
  4. From the Post-build Actions section, enable Publish findbugs analysis tools.
  5. In the FindBugs results field, write **/findbugsXml.xml (see the following screenshot):
    Static code analysis tools (FindBugs)

    Hudson's configure FindBugs report

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.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset