Maven Release Plugin and Continuous Delivery

I was setting up a Continuous Delivery system using Maven as the build tool, Perforce as the SCM and Go (ThoughtWorks’ CI system). All was going perfectly well until I got to the point when I no longer wanted to make snapshot builds…

The idea behind my Continuous Delivery system was this:

  • Every check-in runs a load of unit tests
  • If they pass it runs a load of acceptance tests
  • If they pass we run more tests – Integration, scenario and performance tests
  • If they all pass we run a bunch of static analysis and produce pretty reports and eventually deploy the candidate to a “Release Candidate” repository where QA and other like-minded people can look at it, prod it, and eventually give it a seal of approval.

As you can see, there’s no room for the notion of “snapshot” and “release” builds being separate here. Every build is a potential release build. So, a few days ago I went right ahead and used the maven release plugin, and that was the last time I remember smiling, having fun, getting a full night’s sleep, and my brain not hurting.

The problem is this: the maven release plugin doesn’t really work for continuous delivery. And what’s more, it REALLY doesn’t work with Go and Perforce. I’ll start with the Go/Perforce issues: I got loads of errors thanks to the way Go runs as the system user, and creates its own clientspecs. The results of this debacle are detailed here and here.

I managed to finally get around the clientspec/P4/Go problems with some help from my colleague Toby Catlin who bears the scars of similar skirmishes with Go and Perforce from days gone by. The “fix” was to create a perforce config file and an “uber” client spec. The perforce config file specified the uber clientspec and it lived in the root of the project directory. It was hardly a satisfactory workaround, as it meant that every project would need to have this file, and the uber clientspec would need to be updated every time a new build job was created. But never mind that, it was just a relief to see the builds going green for a change.

And that’s when it happened… the release build completed. The maven release plugin increased the version number in the pom and checked it in. And then Go detected the change in the pom and checked it out again and started building again. This then updated the version number and checked it in, which in turn got detected and kicked off another build CAN YOU SEE THE GLARINGLY OBVIOUS PROBLEM HERE????

It’s obvious really. I’ve always made my maven release builds a manual process in the past and that was exactly why, I’d just forgotten all about it. So, I’ve decided not to use the maven release plugin at all. Every build now just creates a “release” build because I’ve removed all instances of the word SNAPSHOT from the poms. If they pass all their tests and look good enough, they’re automatically promoted to the release candidate repository. And everyone’s happy. Also, I’ve added a property to the builds which pulls in a variable from the Go system, and if that’s not present the “deploy to release candidate repository” step fails – this is to stop developers from manually creating releases – all release builds must come from the CI system.



  1. Curt · June 17, 2011

    Nice! One of these days I’m going to re-write that plugin to NOT check back in, never made any sense to me.

  2. Stephen Smith · July 4, 2011

    Hi James

    This particular issue with Maven has also been discussed at and There are a number of barriers to Maven being a useful Continuous Delivery tool by default, and this one is certainly a biggie.

    In my experience, Maven needs to be kept within a bounded context. It starts to become painful after the “verify” stage, so I don’t use it any further in a Continuous Delivery pipeline.


    • unsan · December 23, 2014

      This opinion piece is about the release plugin not Maven as an overall product. Maven is a valuable product that is very flexible. The release plugin not so much.

  3. Martin Eigenbrodt · July 5, 2011

    Thanks for this article. Your setup does not produce a distinct version of artifacts for each build. So how do you distinguish them? I would like to have Jenkins/Hudson produce Artifacts with a unique Version each time a build runs. After all this is what version are for. An of course I don’t want to have mvn/Jenkins/Hudson pollute my VCS with automated commits.
    I run into this is a problem everytime I’m forced to use maven. Solutions are welcome :-).

  4. jamesbetteley · July 11, 2011

    Hi Martin,
    I’m now using the SCM commit number as the “build number” section of the artifact version number. e.g. artifactName-1.0.0-1234 where 1234 is the commit number I pull in from the SCM system which causes the build. This ensures that each build produces a unique version. I’ve detailed it here:

  5. Pingback: Continuous Delivery Using Maven « James Betteley's Devops Ramblings
  6. Pingback: Always Agile · The Strangler Pipeline – Challenges

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s