Wednesday, December 17, 2008

Control versioning in new maven-release-plugin

I have been waiting with much anticipation for the new version of the maven-release-plugin to be, well released. Our team uses this time saving plugin heavily but since moving to a MAJOR.MINOR.PATCH version strategy we quickly found out that it needed some new features. What we really needed was the ability to specify versions for the tag and for the new trunk. For example, when HEAD is at 2.1.0-SNAPSHOT, while in batch-mode the new default version would be 2.1.1-SNAPSHOT, but I want it to be 2.2.0-SNAPSHOT.

Fortunately, someone else was thinking the same thing and the new capabilities where already in the works. Our current version we are using is 2.0-beta-7. But I noticed today the maven team finally released 2.0-beta-8 (see repo1). Here are the release notes for the new version.

What I was specifically interested in was the new batch-mode features. Now instead of having to manually update the POMs after creating a release I can do the following automatically in CI:

mvn release:prepare -DdevelopmentVersion=2.2.0-SNAPSHOT

I haven't tested it yet, but will know in the near future if it works.

Friday, December 5, 2008

Maven Profiles: Something you need to know

An issue came up today in our CI environment and I learned something new about maven profiles. Something that everyone who uses maven should know. Perhaps, like your environment, our project uses maven2 to build and we take advantage of multiple profiles (see our example here). A common use for profiles is to define new modules and properties. For example:

<profiles>
<profile>
<id>integration-tests</id>
<modules>
<module>integration</module>
</modules>
<properties>
<app.port>8080</app.port>
</properties>
</profile>
<profiles>

This profile is activated when you run mvn -P integration-tests install. But sometimes you want a profile on all the time. Maven profiles have the ability to be actived by default. To do this just do the following:
<profiles>
<profile>
<id>integration-tests</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<modules>
<module>integration</module>
</modules>
<properties>
<app.port>8080</app.port>
</properties>
</profile>
<profiles>

Then you can just run mvn install and that module and property will already be active.

activeByDefault.....Sometimes
Turns out that perhaps maven should have renamed it to activeByDefaultSometimes. Reading their documentation I learned something important about maven profiles:
"This profile will automatically be active for all builds unless another profile in the same pom is activated using one of the previously described methods. All profiles that are active by default are automatically deactivated when a profile in the pom is activated on the command line or through its activation config."
So in my example, if I have more than one profile defined in my pom and I run that new profile, then my integration-tests profile is deactivated. For example, when I run mvn -P SecondProfile, the module and property defined in the integration-tests profiles are not available to my build. One trick to see which profiles are activated when running maven is to run mvn help:active-profiles.

In general I have never been a huge fan of profiles. They feel clumsy, clutter up the cmd line, and are not well known among your team. As their documentation states, "adding profiles to your build has the potential to break portability for your project". Instead of using Profiles, attach to known phases. For example, see my second example from this previous post. In this example, I use the maven-antrun-plugin to attach to the install phase. Now this will run anytime I run mvn install. No clumsy profile I have to memorize and run. Given that, I am not saying you should avoid Profiles all together. Just use them as a last resort.