What is the Maven way for automatic project versions when doing continuous delivery?

Solution 1:

I recommend the following presentation that discusses the practical realities of doing continuous delivery with Maven:

  • You tube presentation on CD with Maven
  • Slides

The key takeaway is each build is a potential release, so don't use snapshots.

Solution 2:

This is my summary based on the video linked by Mark O'Connor's answer.

  • The solution requires a DVCS like git and a CI server like Jenkins.
  • Don't use snapshot builds in the Continuous Delivery pipeline and don't use the maven release plugin.
  • Snapshot versions such as 1.0-SNAPSHOT are turned into real versions such as 1.0.buildNumber where the buildNumber is the Jenkins job number.

Algorithm steps:

  1. Jenkins clones the git repo with the source code, and say the source code has version 1.0-SNAPSHOT
  2. Jenkins creates a git branch called 1.0.JENKINS-JOB-NUMBER so the snapshot version is turned into a real version 1.0.124
  3. Jenkins invokes the maven versions plugin to change the version number in the pom.xml files from 1.0-SNAPSHOT to 1.0.JENKINS-JOB-NUMBER
  4. Jenkins invokes mvn install
  5. If the mvn install is a success then Jenkins will commit the branch 1.0.JENKINS-JOB-NUMBER and a real non-snapshot version is created with a proper tag in git to reproduce later. If the mvn install fails then Jenkins will just delete the newly created branch and fail the build.

I highly recommend the video linked from Mark's answer.

Solution 3:

Starting from Maven 3.2.1 continuous delivery friendly versions are supported out of the box : https://issues.apache.org/jira/browse/MNG-5576 You can use 3 predefined variables in version:

${changelist}
${revision}
${sha1}

So what you basically do is :

  1. Set your version to e.g. 1.0.0-${revision}. (You can use mvn versions:set to do it quickly and correctly in multi-module project.)
  2. Put a property <revision>SNAPSHOT</revision> for local development.
  3. In your CI environment run mvn clean install -Drevision=${BUILD_NUMBER} or something like this or even mvn clean verify -Drevision=${BUILD_NUMBER}.

You can use for example https://wiki.jenkins-ci.org/display/JENKINS/Version+Number+Plugin to generate interesting build numbers.

Once you find out that the build is stable (e.g. pass acceptance tests) you can push the version to Nexus or other repository. Any unstable builds just go to trash.