Friday, December 4, 2009

Releasing a multi-module project using the maven-release-plugin

To create a release the maven-release-plugin will execute 2 steps: prepare and perform. Let's first describe those steps.

Prepare the release

Preparing a release executes the following steps:
  1. Check that there are no uncommitted changes in the sources
  2. Check that there are no SNAPSHOT dependencies
  3. Change the version in the poms from x-SNAPSHOT to a new version (you will be prompted for the versions to use)
  4. Transform the SCM information in the POM to include the final destination of the tag
  5. Run the project tests against the modified POMs to confirm everything is in working order
  6. Commit the modified POMs
  7. Tag the code in the SCM with a version name (this will be prompted for)
  8. Bump the version in the POMs to a new value y-SNAPSHOT (these values will also be prompted for)
  9. Commit the modified POMs
To execute this step, run
mvn release:prepare

Perform the release

Performing a release does the following:
  1. Checkout from an SCM URL with optional tag
  2. Run the predefined Maven goals to release the project (by default, deploy site-deploy)
To execute this step, run
mvn release:perform

Which strategy to use to release a multi-module project

Let's consider a multi-module project with the following architecture :

_ project-parent
|_ _ project-child-1
|_ _ project-child-2
...
|_ _ project-child-n
|_ _ pom.xml

The parent project is a POM project and the parent of the other modules.

When you have a lot of child modules, the easiest way to release your projects is to release them all at the same time by executing the prepare and perform command at parent level. You certainly don't want to release your modules one at a time because you don't have time for that.

There is 2 issues with this strategy :

  1. The prepare step will fail if it finds any SNAPSHOT dependencies in one of your child module
  2. If you resolve the first problem, you will be prompted for each child module version. This one is not really a major problem but it can be a pain in the ass if you don't want to use the default versionning.

The first issue can be resolved by not setting the version of your child module. Remember, every child module inherits the groupId and the version of its parent module.


The second issue can be resolved by setting the autoversionsubmodules to true in the maven-release-plugin configuration.


Here's how to define the plugin in the POM file of the parent project :

<plugin>
<groupid>org.apache.maven.plugins</groupid>
<artifactid>maven-release-plugin</artifactid>
<version>2.0-beta-9</version>
<configuration>
<goals>deploy</goals>
<autoversionsubmodules>true</autoversionsubmodules>
</configuration>
</plugin>

By setting the autoversionsubmodules to true the maven-release-plugin will not prompt you for the version of your child modules.


Tips : The prepare step does a lot of things and you can hesitate to execute the command the first time you're releasing a project. In that case use the DryRun option to simulate what will happen :
mvn release:prepare -DdryRun
The DryRun option will create the following files :

- pom.xml.next : what the projects pom looks like after the release
- pom.xml.releaseBackup : what the pom looked like before
- pom.xml.tag : the pom for the tagged version of project
- release.properties : the information about the release of the project

If you're happy with that, execute the mvn release:clean command to clean the generated files.

Resources :
http://maven.apache.org/plugins/maven-release-plugin/
http://maven.apache.org/guides/mini/guide-releasing.html