DevOps Zone is brought to you in partnership with:

By day I'm a build and release engineer in London, but by night I'm a normal person! If anyone ever asks me what I do, I usually generarlise and say "I'm in I.T." and then check to see if they've already stopped listening. When I'm not working or blogging I can be found playing rugby or cycling around the countryside on my bike, in an attempt to keep fit and fool myself into thinking I'm still young. James is a DZone MVB and is not an employee of DZone and has posted 54 posts at DZone. You can read more from them at their website. View Full User Profile

Maven the Version Number Nazi

05.07.2012
| 8451 views |
  • submit to reddit

Maven doesn’t like it when you use different verison numbers to the Maven standard format. Of course it doesn’t. It wouldn’t would it? It’s Maven, and Maven only likes it when you do what it tells you to do. I’m still a bit annoyed with Maven, as you can probably tell.

Don’t get me wrong, I’m not “Maven bashing”, it’s just that this particular problem doesn’t have quite the elegant solution I was looking for. I do appreciate Maven, honestly.

This was the problem:

I wanted to change our versioning system from something like 1.0.0-1234 to something like 1.0.0-1234-01

Why the hell would I want to do that?? I’ll explain…

Our verisoning is like this:

{major}.{minor}.{patch}-{build}


The only problem was, the build number was taken from the Perforce check-in number, and this number didn’t always change whenever a build was made, especially if the build was kicked off by an upstream dependency, or a forced build was triggered. Basically, if the build was kicked off by anything other than a commit to Perforce, the build would create an artifact of identical version to the previous build. This, in theory, shouldn’t be a problem, because it is actually building exactly the same thing, but I just don’t like it. Anything could happen, any environmental change could produce a slightly different build to the previous one.

The problem was that I wasn’t using an incremental counter anywhere in my version numbe. It’s essential to have an incrementing version number in order to ensure that every single build creates a unique identifier, so that no two different builds can appear to be the same build.

My first thought was to append a build counter on the end, like this:

{major}.{minor}.{patch}-{build}-{counter}


And that would have worked fine, if it wasn’t for the fact that we use version ranges in our dependencies, and we already have plenty of builds which use the previous versioning system. Maven kept picking up the builds with the previous version system, even though, in every possible sense, the new ones had higher version numbers. It made no sense. That’s when I looked into how maven works out versions. Basically it says “if you’re using version ranges, and not using the maven standard versioning format, you might as well forget it”. If it sees dependencies using the standard format, and ones using the non-standard maven format, it’ll pick up the standard format ones and basically ignore the new ones. To get around this you can delete all the old builds using the standard maven format, and then it’ll work, because it’ll treat each build version like a string and just get you the latest in whatever your range is.

Sadly, this isn’t an option for me, as I want to kep the old builds using the old format. So I tried a few things. I tried putting a string in as a separator, so it would look like this:

{major}.{minor}.{patch}-{build}rc{counter}


This effectively produces something looking like:

1.0.0-1234rc01

I’m fine with that. Maven, on the other hand, isn’t. I made a build with this version 1.0.0-9999rc01 and used it as a dependency in another build, but the other build still went and got 1.0.0-1234, the OLD build using the standard maven versioning. I mean, you’d think 1.0.0-9999rc01 > 1.0.0-1234 but apparently not.

I was a bit pushed for time so I couldn’t spend forever looking into this, so I’ve basically just appended the build counter directly onto the end of the perforce number. This works ok, but just looks a little ugly.

There’s more information on the Maven versioning rules here. It seems that you can break the rules no problems, but you’re in trouble if you use version ranges in your dependencies, and your dependencies need to live alongside binaries which use the standard maven versioning system :-(

If anyone has any better solutions I’d like to hear them. And please don’t say “stop using Maven”.

Published at DZone with permission of James Betteley, author and DZone MVB. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Comments

Mladen Girazovski replied on Mon, 2012/05/07 - 7:00am

 If anyone has any better solutions I’d like to hear them. And please don’t say “stop using Maven”.

 Let me put it this way: Stop abusing Maven version numbers ;)

Our verisoning is like this...

Sounds to me like your build/deploy/release process is not really aligned to Maven yet.

Maven has its own versioning scheme, instead of trying to change Mavens way, change your own way :)

Have you had a look at this plugin?

http://mojo.codehaus.org/buildnumber-maven-plugin/

It should do what you want, except for naming the file the way you want, since it would break maven versioning scheme, instead you'll have the build number in your MetaData like MANIFEST etc. pp.

 

Jörg Buchberger replied on Mon, 2012/05/07 - 8:41am

Hi

if you need to change your version format ...

you might just as well also slightly change your group-ID.

Such a workaround would avoid the conflicts you outlined above. 

 

Cheers

Jörg 

Bruce Baron replied on Mon, 2012/05/07 - 12:15pm

Version number Nazi? That's a bit harsh, considering there has to be some sane way to order version strings to determine if a particular version string is inside or outside a range.

Pieter Van Der Meer replied on Mon, 2012/05/07 - 2:13pm

James,

 what wonders me is the following from your post: 

Anything could happen, any environmental change could produce a slightly different build to the previous one.

 How can this happen. What you are saying is that you have a non-reproduciable build. If so, why even bother with build numbers. The number has become meaning less. A defect found in build 4321 can not be reproduced, some environment change (which i dont know) introduced this defect...

 Just use the standard maven snapshot numbering and you are at the same point.

(btw I endorse the solution with the build number plugin. In general I create a custom manifest including my SCM revision number, timestamp and info about who or what created the artifact).

Pieter 

Loren Kratzke replied on Wed, 2012/05/09 - 11:52am

Basically, stop putting metadata (patch numbers and buildIds) in your version numbers. Use the manifest to hold that information and use some other system to report on it.

Furthermore, you pretty much need to do a Maven release with every build based upon your previous posts mentioning that you want every build to be a potential release. Just bite the bullet and release with every build. It is what you want to do anyway. Just do it.

The notion of every build being a potential release is unconventional at best. The Maven montra is convention over configuration.

Curtis Yanko replied on Tue, 2012/05/08 - 7:22am

Clasic case of solving a problem that doesn't exist. I ran into this when we were doing modular builds, the EAR projects tend not to increment so we started passing in the build number from the CI instead. However, if the intent is to reflect the repository version, you should check out from a level that is reflective of the whole project and not just the one module.

Pietro Martinelli replied on Thu, 2012/05/10 - 7:28am

What about using a numbering schema like

{major}.{minor}.{patch}-{timestamp} ?

 This schema complies with Maven standard schema but can differentiate different build of the same VCS snapshot, if you can pay the price of losing the reference to Perforce check-in number...

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.