Creating a build pipeline using Maven, Jenkins, Subversion and Nexus.

For a while now, we had been operating in the wild west when it comes to building our applications and deploying to production.  Builds were typically done straight from the developer’s IDE and manually deployed to one of our app servers.  We had a manual process in place, where the developer would do the following steps.

  • Check all project code into Subversion and tag
  • Build the application.
  • Archive the application binary to a network drive
  • Deploy to production
  • Update our deployment wiki with the date and version number of the app that was just deployed.

The problem is that there were occasionally times where one of these steps were missed, and it always seemed to be at a time when we needed to either rollback to the previous version, or branch from the tag to do a bugfix.  Sometimes the previous version had not been archived to the network, or the developer forgot to tag SVN.  We were already using Jenkins to perform automated builds, so we wanted to look at extending it further to perform release builds.

The Maven Release plug-in provides a good starting point for creating an automated release process.  We have also just started using the Nexus Maven repository and wanted to incorporate that as well to archive our binaries to, rather than archiving them to a network drive.

The first step is to set up the project’s pom file with the Deploy plugin as well as include configuration information about our Nexus and Subversion repositories.

<plugin>
   <groupId>org.apache.maven.plugins</groupId>
   <artifactId>maven-release-plugin</artifactId>
   <version>2.2.2</version>
   <configuration>
      <tagBase>http://mks:8080/svn/jrepo/tags/Frameworks/SiestaFramework</tagBase>
    </configuration
</plugin>

The Release plugin configuration is pretty straightforward. The configuration takes the subversion URL of the location where the tags will reside for this project.

The next step is to configure the SVN location where the code will be checked out from.

<scm>
   <connection>scm:svn:http://mks:8080/svn/jrepo/trunk/Frameworks/SiestaFramework</connection>
   <url>http://mks:8080/svn</url>
</scm>

The last step in configuring the project is to set up the location where the binaries will be archived to.  In our case, the Nexus repository.

<distributionManagement>
   <repository>
       <id>Lynden-Java-Release</id>
       <name>Lynden release repository</name>
       <url>http://cisunwk:8081/nexus/content/repositories/Lynden-Java-Release</url>
    </repository>
</distributionManagement>

The project is now ready to use the Maven release plug-in.  The Release plugin provides a number of useful goals.

  • release:clean – Cleans the workspace in the event the last release process was not successful.
  • release: prepare – Performs a number of operations
    • Checks to make sure that there are no uncommitted changes.
    • Ensures that there are no SNAPSHOT dependencies in the POM file,
    • Changes the version of the application and removes SNAPSHOT from the version.  ie 1.0.3-SNAPSHOT becomes 1.0.3
    • Run project tests against modified POMs
    • Commit the modified POM
    • Tag the code in Subversion
    • Increment the version number and append SNAPSHOT.  ie 1.0.3 becomes 1.0.4-SNAPSHOT
    • Commit modified POM
  • release: perform – Performs the release process
    • Checks out the code using the previously defined tag
    • Runs the deploy Maven goal to move the resulting binary to the repository.

Putting it all together

The last step in this process is to configure Jenkins to allow release builds on-demand, meaning we want the user to have to explicitly kick off a release build for this process to take place.  We have download and installed the Release Jenkins plug-in in order to allow developers to kick off release builds from Jenkins.  The Release plug-in will execute tasks after the normal build has finished.  Below is a screenshot of the configuration of one of our projects.  The release build option for the project is enabled by selecting the “Configure release build” option in the “Build Environment” section.

The Maven release plug-in is activated by adding the goals to the “After successful release build” section.  (The –B option enables batch mode so that the Release plug-in will not ask the user for input, but use defaults instead.)

image

Once the release option has been configured for a project there will be a “Release” icon on the left navigation menu for the project. Selecting this will kick off a build and then the Maven release process, assuming the build succeeds.

image

Finally a look at SVN and Nexus verifies that the build for version 1.0.4 of the Siesta-Framework project has been tagged in SVN and uploaded to Nexus.

image

image

The next steps for this project will be to generate release notes for release builds, and also to automate a deployment pipeline, so that developers can deploy to our test, staging and production servers via Jenkins rather than manually from their development workstations.

twitter: @RobTerp
blog: http://rterp.wordpress.com

12 thoughts on “Creating a build pipeline using Maven, Jenkins, Subversion and Nexus.

    • Thanks Vijay! I’m looking forward to the deploy pipeline myself as it will greatly streamline our deployment process. I’m hoping to begin work on it after our next major release at the end of the month.

  1. Pingback: Creating a Deployment Pipeline with Jenkins, Nexus, Ant and Glassfish | Rob's Blog

  2. Do you have any ideas on how to tackle a failed release execution? Like configuring the rollback in Jenkins instead of manually rolling back changes?

    • This may be a bit tricky depending on how simple/complex your deployment is. Are you simply deploying a .war file to an application server, or are there other steps in your deployment process?

  3. is there any way to perform a maven release without pushing the release button manually?
    I want to do a mvn release using a trigger. Example
    Build jar –> build config files –> deploy –> test –> if ok–> perform mvn release

    • Hi Marco,
      you could set up a separate job for the release, and then set the release job as a “Down stream” job that will run when you regular build process successfully finishes.

  4. Nice Article. Wanted to check whether you can help me in the following:
    1. Jenkins to use maven and release to artifactory repository and deploy in JBoss server
    2. How we can move the code from branch to trunk and tag the version once UAT is over and ready for production release in Jenkins
    3. Best practices in implementing CI Server

    • Hi Vijay,

      Our Jenkins process is calling an Ant script behind the scenes to download the artifact from Nexus and then install it to Glassfish. I image the Ant task to download from Artifactory would be the same. To deploy to JBoss you may want to search Google to see if there are any Ant tasks that would allow you to deploy automatically.

      As far as #2 goes. I’m not sure you can automate a merge from the branch to trunk, as there could be conflicts that would have to be resolved. You could however tag the branch or trunk via Ant.

      3. What we have found as far as implementing Jenkins was that converting our projects to use Maven rather than Ant to build them saved quite a bit of time, as all of our projects now have a similar directory structure and build process. We are also running sonar as part of our Jenkins builds which will check for unit test code coverage as well as do a static analysis on the code to check for potential issues.

      hth,
      -Rob

  5. Pingback: Maven and continous integration | Machine Learning, Maths and Physics

Leave a Reply to rterpCancel reply