Friday, May 14, 2010

How to create a release without the maven2 release plugin

One of the most referenced articles I have written is "How to create a release using the maven release plugin". But what if you can't get the maven release plugin to work with your project? Perhaps like our team, you've got a legacy maven2 multi-module project that's been nigh impossible to use with the release plugin. Our project has a mix of WAR modules combined with some Flex modules. I believe our last issue was some googlecode flex mojo wasn't working with the release plugin. Consequently, for the past year or so, we've been manually creating our releases. This actually hasn't been that much of a pain since we really only do it once a sprint at the end. Combined with my favorite perl script it doesn't really take that long. However, it does have the disadvantage of requiring some knowledge of what and now to do it. Ideally, it would be a job in Hudson, anyone on the team could run as many times as they like.

In an effort to try and automate as much as possible, I decided to try and automate releasing our legacy multi-module project using bash. This has several benefits: create a release faster, done consistently each time, turn-key solution anyone on the team can run that doesn't require stale documentation on how to do it.

It took my several hours to essentially duplicate the maven release plugin process. Thanks to our new intern Scott Rogers and linux master Ron Alleva, I was eventually able to get it finished. It's my first "official" bash script so pardon the mess. If you've never attempted to automate your release project, first consider reading my article on How to effectively use SNAPSHOT.

Here is the script available as a gist on github: project-release.sh. Here is what it does:

  1. Copies the current working branch (i.e. trunk) into another branch. It uses the pom.xml value to get the current working branch.
  2. Updates all the pom.xml version sections of the current working branch
  3. Commits the pom.xml changes
  4. Checks out the release branch
  5. Updates all the pom.xml version sections of the release branch (basically stripping off -SNAPSHOT)
  6. Commits the pom.xml changes
To run this script all you have to do is run: project-release.sh 2 false. The first parameter (2) is the increment position that the current working branch needs to be next. For example, if trunk was on 1.2.0-SNAPSHOT and the position passed in was 2, then trunk gets updated to 1.3.0-SNAPSHOT. If the position was 3 then trunk would be updated to 1.2.1-SNAPSHOT. The second parameter is used when testing. It's like the dryRun option in the maven release plugin. When set to true, nothing gets copied or committed.

A few notes about the script:
  • The base branch URL is hardcoded but could easily be passed in as another parameter or placed and read from some external file.
  • It uses the cmd xpath to extract out the pom version, project name, and scm url. I'm on ubuntu 9.10 and according to synaptic I have libxml-xpath-perl version 1.13-6 installed.
  • It doesn't run any maven commands like mvn deploy. Other jobs in CI can accomplish that or you can easily add them into the script.
  • To run from Hudson:
    • Create a New Job
    • In the Build section Add a Execute Shell Step
    • Update the Command text with: $WORKSPACE/trunk/project-release.sh 2 false
Overall, I'm pretty happy with the outcome. And as we start to perform more releases among multiple projects I think it's going to really come in handy. I think ideally you should try and release your project using the maven release plugin, but if that isn't possible then don't give up. Just clone.