Friday, September 14, 2007

How to create a release using the maven2 release plugin

If you haven't figured out how to simplify creating a release for your maven2 projects then you need to look into the maven-release-plugin. This powerful plugin helps shorten the time it takes when creating a release and we have used it extensively on our open source projects: RSS BC, SIP BC, UDDI BC, and the XMPP BC.

Kicking It Old School
Back when we were using maven1 we actually used a sed script to update the versions in the project.xml and project.properties files. Boy those where the days; how I don't miss them. However, I was still impressed with it so here you go. Create a script named swap:
#!/bin/sh
cp $1 $1.backup
sed -e s/"$2"/"#3"/g $1 > temp
cat temp $1

Browse to your project and run:
find -name 'project.properties' -exec ~/swap {} 1.1.0-SNAPSHOT 1.1.0 \;
find -name 'project.xml' -exec ~/swap {} 1.1.0-SNAPSHOT 1.1.0 \;

It was effective and did the job (in fact it's easier to use a perl script), but you still had to create the tag/branch and commit. Also with maven2 POMs you have other values that have to be updated like the <scm> information.

How to use the maven-release-plugin
First, you need to clean up your POMs. Here are three basic guidelines that will make your life easier when managing them:

  1. Avoid declaring groupIds and versions where it is not required. For example in child POMs, if the groupId and version are the same as the parent, you don't have to define your own groupId or version. By default it inherits from the parent.
  2. If you do have to declare versions, use the section of your parent POM. This helps define your downstream dependencies and prevents the child POMs from having to declare the versions that are shared among the project.
  3. Use properties to define other common versions.
For a real example, view the RSS BCs parent pom, and subsequent child poms: extensions, jar, and zip. Notice the use of properties and dependencyManagement in the super pom. Also note how the child POMs don't have to declare versions for inner project dependencies that are defined in the parent POM under dependencyManagement.

Now that you have your POMs cleaned up it's time to use the maven-release-plugin. It doesn't actually require these changes, but I am anal so sorry.

Step1
Make sure your parent POM has the <scm> section describing the projects source control location.

Step2
Get a clean copy of your project. The maven-release-plugin will not run if you have locally modified files; including IDE files or the target folder.

Step3
Run mvn release:prepare -DdryRun=true
This will walk you through a dry run and you can view the temporary POMs it creates to verify you did everything correctly.

Step4
Run mvn release:clean release:prepare -Dusername=johndoe -Dpassword=passwd
This will actually commit a tag with non-snapshot versions of your project and also increment all your versions to the next release. So for example, if your current version is 0.9.1-SNAPSHOT, it will commit a tag with 0.9.1 version, and update the trunk POMs with 0.9.2-SNAPSHOT. Of course when using the prepare goal you are prompted for the release numbers and next release numbers.

Step5
Run mvn release:perform
The perform goal basically runs deploy and site-deploy. This step is optional and I typically don't run it.

Gotcha
One gotcha is if your project has a SNAPSHOT dependency on an artifact outside your project, the release plugin doesn't handle that (or at least I haven't figured it out). The prompts seem to ask questions about what version they need to be, but never actually does anything with the information. Hopefully this will be fixed in future versions. In the mean time, use properties, and when running mvn release:prepare use the -D option to specify the version and then manually update the tag and trunk pom to reflect the real version. So something like mvn release:prepare -DdryRun=true -Dcommon.jbi.runtime.version=0.9.2.

Windows Users
The other issue you might have is if you are using Windows. Since I am using Linux the svn commands are already installed and I use them frequently. And since the release plugin uses the svn commands to do its work, you will need to install the svn client commands in order to it in DOS. To do that go here, go down to the Windows section, and click Win32 packages built against Apache 2.2. In there download and install the svn-1.4.6-setup.exe. After installing it, open up a new DOS window and run svn help.

For further tips and tricks read the Gestalt Developers Guidelines for creating a release using the maven-release-plugin.

Related Articles

10 comments:

Unknown said...

Once again, another excellent post. Very good stuff!!

murali said...

just wanted to mention that one can skip tests by specifying the attribute -DpreparationGoals=clean in the commandline along with mvn release:prepare. It helps when you have a big suite of tests.

boomtown15 said...

I use the Maven release plugin to branch, tag and create a release. The problem is that you need to do these in a certain order unless you want to use Perl or sed to manipulate the POM. Anyways, here is what I've found to work:

1. Checkout clean copy of project
svn co [project]

2. Create Branch:
mvn -DupdateBranchVersions=true -DupdateWorkingCopyVersions=false --batch-mode release:branch

3. Create Tag:
mvn --batch-mode release:prepare

4. Checkout the tag to create a release from it
svn co [tagged_project]

5. Create release
mvn clean deploy site-deploy

The only extra step I needed to perform was to find the tag name to checkout the project and create the release. This can be obtained from the release.properties file after performing step 3.

I have a script that basically automates all of this process for a given project. It works quite well.

jlorenzen said...

If you are a windows user using cygwin and are having issues using the release plugin, try the cmd or dos program to create the release. A coworker recently had issues creating a release using cygwin on windows because his TMP directory came across incorrectly in cygwin.

vineetmanohar said...

Maven release plugin is great. Don't forget the single line which does the full release automatically. You can even release automatically in a nightly build.

See my blog post for more details.
How to automate project versioning and release with maven

jlorenzen said...

Another way to skip tests is to specify mvn release:prepare -Dmaven.test.skip=true

Ayush Java Solution said...

Thanks a lot. Very nice tutorial on Maven. It helped me lot during setup my project.

Thanks,

Ayush Suman
http://ayushsuman.blogspot.com

Anonymous said...

Find on Java Tutorial a cookbook
on Maven Release desrcibing how to release a project using a subversion repository and Nexus

Karthik said...

Hi,

Excellent post! I am using the maven release plugin from a jenkins ci server. When it commits the new pom file to the GIT Repo, it commits as the jenkins user(our org has a user configured in jenkins). but i want it to show it committed by me. How can i achieve it? Any inputs would be greatly apreciated

Rose Weber said...

Thank youu for writing this