Creating robust build pipelines on Continuous Integration servers such as Jenkins is still quite a challenge. Especially when it comes to versioning and performance (duration of the builds).

I’m going to show here how to use the nonsnapshot-maven-plugin together with Maven 3.2.x to build fully automated build pipelines with automatic version updates and incremental (fast) builds.

The pipeline will have the following features:

  • Update upstream dependencies versions (from a previous build step)
  • Update the version of all modules with code changes or updated (upstream) dependencies
  • Build (compile, test and deploy) of all modules with a new version
  • Commit changed POM files

Here a diagram how the steps of our pipeline shall work:
build_pipeline10

Example

Let’s say we have two projects depending on each other (Project 2 depends on Project 1, therefore the build pipeline consists of two consecutive steps):

build_pipeline5

The build of Project 1 starts and the nonsnapshot-maven-plugin detects code changes in Module 1. So, it updates the version and also the version of Module 2, because it has a dependency to Module 1. The two changed Modules will be compiled, tested and deployed.
At the end the build of Project 2 will be triggered, because it is a downstream project. The nonsnapshot-maven-plugin detects a newer version of Project 1 Module 2 in the Maven repository und updates the version of Module 2 accordingly. Maven will compile, test and deploy only this module. Like this:

build_pipeline6

Maven Configuration

For the incremental build you need at least Maven 3.2.1. Additionally you have configure the nonsnapshot-maven-plugin for each root (aggregator) project of your build pipeline. Below an example configuration for GIT, which considers all Maven dependencies with the groupId at.nonblocking and org.springframework as upstream dependencies (built by previous build steps):

<build>
    <plugins>
        <plugin>
            <groupId>at.nonblocking</groupId>
            <artifactId>nonsnapshot-maven-plugin</artifactId>
            <version>2.0.9</version>
            <configuration>
                <baseVersion>${myproject.base.version}</baseVersion>
                <scmType>GIT</scmType> <!-- GIT or SVN -->
                <!-- <scmUser></scmUser> -->
                <scmPassword>${git.passphrase}</scmPassword>
                <deferPomCommit>true</deferPomCommit>
                <generateIncrementalBuildScripts>true</generateIncrementalBuildScripts>        
                <!-- <generateChangedProjectsPropertyFile>true</generateChangedProjectsPropertyFile> -->
                <upstreamDependencies>
                    <upstreamDependency>at.nonblocking:*:LATEST</upstreamDependency>
                    <upstreamDependency>org.springframework:*:4.0</upstreamDependency>
                </upstreamDependencies>
            </configuration>
        </plugin>
    </plugins>
</build>

<pluginRepositories>
	<pluginRepository>
		<id>jcenter</id>
		<url>http://jcenter.bintray.com</url>
	</pluginRepository>
</pluginRepositories>

The baseVersion defines the version applied to changed modules. The option generateIncrementalBuildScripts enables the generation of a script for an incremental build.
The upstream dependency configuration org.springframework:*:4.0 means: Try to find newer versions of artifacts with the groupId org.springframework, but consider only 4.0.x versions.

On the command line execute a build step as follows:

cd <myproject-root>
mvn nonsnapshot:updateVersions -Dmyproject.base.version=1.2.3
./nonsnapshotBuildIncremental.sh clean install
mvn nonsnapshot:commitVersions

Note, you don’t have to touch any code to update the base version. Just change the property on the command line.

Jenkins Configuration

To create a build step on Jenkins, enable the option generateChangedProjectsPropertyFile in the nonsnapshot-maven-plugin configuration. It will create a property file with the changed modules, which can be passed to the Maven build for an incremental build. Furthermore you’ll need the EnvInject Jenkins plugin.

Configure the Jobs as follows:

build_pipeline1

(The Check-out strategy could also be Always check out a fresh copy)

build_pipeline2

build_pipeline3

build_pipeline4

build_pipeline5

Something similar should be possible on other CI servers.

3 thoughts on “Build Pipeline on Jenkins with incremental Maven builds and automatic versioning

Leave a Reply

Your email address will not be published. Required fields are marked *


*