Skip to main content

Using the Maven Release Plugin

Posted by johnsmart on August 31, 2008 at 9:23 PM PDT

It is an excellent and widely used best practice to tag each of your stable releases in your version control system for future reference. However, this sort of bookkeeping is tedious and error-prone at the best of times. Like many tedious, error-prone tasks, it is one of those things that could do with a bit of automation.

Fortunately, Maven can help. The Maven Release Plugin helps you automate the whole process of upgrading your POM version number and tagging a release version in your version control system. Let's see how it works. Here is an extract from a POM file, showing the version number that uniquely identifies this version:


<project...>
    ...
    <groupId>com.wakaleo.myapp</groupId>
    <artifactId>myapp-core</artifactId>
    <packaging>jar</packaging>
    <version>1.0.1-SNAPSHOT</version>
    ...

The SNAPSHOT suffix means that each time I deploy this version, a new snapshot will be deployed into my Maven repository. Anyone who wants to use the latest, bleeding-edge SNAPSHOT version can add a SNAPSHOT dependency in their project. This would usually be myself, or other members of the development team. Snapshots, by definition, tend to be fairly unstable beasts.


        <dependency>
            <groupId>com.wakaleo.myapp</groupId>
            <artifactId>myapp-core</artifactId>
            <version>1.0.1-SNAPSHOT</version>
        </dependency>  

As a side-note, the fearless and the reckless can take this a step further by always using the LATEST version, regardless of its actual version number, and regardless of whether it happens to be an official release or just a snapshot:


        <dependency>
            <groupId>com.wakaleo.myapp</groupId>
            <artifactId>myapp-core</artifactId>
            <version>LATEST</version>
        </dependency>  

When the version 1.0.1 is ready, we need to update the POM file, commit the new POM file to version control, tag this version as a release, and then move on to work on version 1.0.2. The Maven Release plugin can automate much of this process. However, before the Maven Release plugin can do its magic, you need to make sure you have everything it needs set up in your POM file.

First of all, you need to be working with a SNAPSHOT release. However, when you are ready to release your new version, you should remove any references to snapshots in your dependencies. This is because a release needs to be stable, and a build using snapshots is, by definition, not always reproducible.

The next thing you need is an block, so that it can find where to create a new release tag and commit the changes. Here is a real-world example:


    <scm>
        <connection>scm:svn:https://wakaleo.devguard.com/svn/maven-plugins/maven-schemaspy-plugin/trunk</connection>
        <developerConnection>scm:svn:https://wakaleo.devguard.com/svn/maven-plugins/maven-schemaspy-plugin/trunk</developerConnection>
        <url>https://wakaleo.devguard.com/svn/maven-plugins/maven-schemaspy-plugin/trunk</url>
    </scm> 

Next, you need to configure the Release plugin itself. This mainly involves telling Maven where your release tags go, via the "tagBase" configuration element. If you are using the Subversion trunk/tags/branches convention, Maven will automatically put release tags in the "tags" directory. In the following example, we use a slight variation on the normal convention, and place releases in the "tags/releases" directory:


<project>
  ...
  <build>
    ...
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-release-plugin</artifactId>
        <configuration>
          <tagBase>https://wakaleo.devguard.com/svn/maven-plugins/maven-schemaspy-plugin/tags/releases</tagBase>
        </configuration>
      </plugin>
    </plugins>
    ...
  </build>
  ...
</project>

Now you can get down to business, and try out a (semi-)automated release. The first thing you need to do is to make sure all your latest changes have been committed to (in our case) Subversion. If there are any outstanding changes, Maven won't let you do a release. First of all, you need to prepare the release, using the "prepare" goal:


$ mvn release:prepare

This goal will ask you a series of questions to confirm what version number you want to release, what new snapshot version number you want to use, and where you want to place the release tag. If you have set up your POM file correctly, these will have sensible defaults, and you won't have to do much thinking. In fact, you can even disable these questions entierly using the "--batch-mode" command line option.

If you want to know exactly what Maven will do to your POM file and your SCM ahead of time (generally a good idea), you can run the operation in the "dry-run" mode, as shown here:


$ mvn release:prepare -DdryRun=true

This useful trick simulates the SCM operations (by writing them out to the console), and creates two sample pom files that you can consult: pom.xml.tag, which is the pom file that will be committed to Subversion and tagged, and pom.xml.next, which contains the next snapshot version number. Once you are happy with what Maven will do, you can do the real thing:

$ mvn release:clean release:prepare

The "prepare" goal actually does quite a lot. Indeed, it will:

  • Make sure that there are no uncommitted changes or SNAPSHOT dependencies (see above)
  • Update the SNAPSHOT version number to a release version (e.g. going from "1.0.1-SNAPSHOT" to "1.0.1")
  • Update the SCM section of the POM file to point to the release tag rather than the trunk in the Subversion repository
  • Run all the application tests to make sure everything still works
  • Commit the changes made to the POM file
  • Create a new tag in Subversion for this release
  • Update the SNAPSHOT version number to a new SNAPSHOT version (e.g. going from "1.0.1" to "1.0.2-SNAPSHOT")
  • Commit the changes made to the POM file

Once you're finished, you have your release version tagged in Subversion and you are working on a new SNAPSHOT version.

But wait, a minute, you might say. Didn't we forget to deploy our release somewhere? Well, that is why the goal is called "prepare". We only set everything up in preparation for the release, we haven't actually released anything yet. But dont worry, performing the release is pretty straight-forward, too. Just use "mvn release:perform":


$ mvn release:perform

This will effectively do a "mvn deploy" with the release we have just created. More precisely, it will use the release.properties file generated by the "release:prepare" goal to do the following:

  • Check out the release we just tagged
  • Build the application (compiling, testing and packaging)
  • Deploy the release version to local and remote repositories

Of course, both of these steps are very easy to place on a Hudson server, so that they can be done centrally.

All in all, a very convenient way to automate your release process.

"Best development course I have been on in a very long time...Greatly enjoyed the course...A 'must' course for serious Java developers..." - Read what people are saying about the Java Power Tools Bootcamps.

Comments

I am trying to configure Maven Release plugin in Jenkins ...

I am trying to configure Maven Release plugin in Jenkins job. I am getting authentication exception. For invoking maven release plugin do we need to have svn client from where we are invoking the release? The requirement is as follows:
My requirement is to configure maven release plugin as follows:
1. My current version is at 1.0.0-SNAPSHOT and once testing is done and ready for movement to production the maven release plugin will be invoked from Jenkins job to move the code from branch to trunk.
2. The configuration has to check out the source from branch, update all the POMs to version 1.0.0, tag the source code and check in the code at trunk location. The tags folder will contain the tagged version at 1.0.0 (as best practice we need to change the version from 1.0.0-SNAPSHOT to 1.0.0 once the product is ready for production, right? or while moving to UAT itself it should be done?).
3. Also, the next snapshot version will be updated to 1.0.1-SNAPSHOT(which is configurable in release plugin) and checked in at branch level for the next development.
I am able to configure this, but somehow it is not working. I am getting authentication exception.
svn: Authentication required for ''.

We are using Jenkins, maven, artifactory, SCM as tools.

The questions that I have are:
1. Do we need to use any certificate for https protocol communication with SCM?
2. How to send credentials to release plugin?

Also, pls share screenshots if you have any for configuring this.I need your help as I am completely struck with this and this has been a blocker for me and stopping to move ahead. PFA my configuration and logs from Jenkins job.

Vijay

<p>Hi,</p> <p>Hudson is doin a great job when it comes to ...

Hi,

Hudson is doin a great job when it comes to automating product build and release.I really love this product.Currently hudson don't seem to have a plugin which supports deployment on jboss 6.May I know when it is expected to come out?

Regards,

S.Sharath

<h3>Maven Release</h3> <p>Hi John, another link on ...

Maven Release
Hi John, another link on Maven release

Hi John, do you know if there's a way to get the mvn-release-plugin also update archetype projects? We have a couple of archetypes that reference the version of the library projects that they are for (in their src/main/resources/META-INF/archetype-metadata.xml, though we could change this to be the pom.xml under src/main/resources/archetype-resources/pom.xml). At the moment we're having to manually update these versions from x.x-SNAPSHOT to x.x prior to running release, but this doesn't seem right to us. Any thoughts appreciated. Thanks Dan

Hi John, good write up. For readers that bump into 3rd party snapshots, I gave some tips on how to deal with those when the Release plugin blocks you: http://blogs.sonatype.com/people/2009/01/best-practices-for-releasing-wi...

Nice article. You cover all of the builds using CI and SNAPSHOT versions quite nicely. But you've skipped over the detail of doing releases by saying that you can just do in in Hudson. How? I've been looking for information on this subject (Maven Releases from a CI machine) and I have not found much. Like you, we use Hudson and I'd love to hear more. There is also one other reason why the release should be on the CI server, that of build consistency. The entire thing can come undone if all SNAPSHOT builds are done on CI but the release is performed manually on a developers machine.

Seems like the release plugin does quite a few things. But I can't help wondering why all these checkin steps are necessary in the first place. Isn't it fundamentally problematic to "hardcode" version numbers into files the way Maven POMs require it? Doesn't that immediately invalidate basic SCM operations like tagging, branching and merging? For example, the SVN copy command presumably creates a new tag/branch to be referenced with a different version identifier. Any "copied" file with a version identifier in its content now necessarily is inconsistent with either the source or the destination of the copy operation. If I update and commit the file to make it consistent with its corresponding SCM version identifier, I create myself a guaranteed merge conflict, should I want to bring the two branches together again. I think these problems are symptoms of a basic problem: redundant storage of (version) information. To my understanding the SCM should be the only source and arbiter of versioning information. Maven should just use that information as the SCM provides it together with the sources it provides to Maven. That way there is gauranteed consistency as opposed to manually maintained consistency and the above described release process would appear to get a lot simpler.

Nice write up! Another goal that is worth highlighting is the newer release:branch goal. This can be used for creating an SCM branch and adjusting the versions, either in advance of a release or for a new line of development.