I’ve Got Your Number

A little while ago, I posted on the Panacea/Test Level 7 blog about our frequent releases and how we identify the builds on our application main page. I’ve been meaning, for a while, to follow that up with a more technical entry to talk about the logistics of producing that build information.

While Maven has provided help tracking high-level release numbers, I’m still somewhat disappointed that there’s no standardized way of recording version and build information about a Java application. It’s not an uncommon requirement. Invariably, we want to be able to say “this instance of the application was built on such-and-such date”, but it’s usually the case that each development team comes up with its own way of handling that. Here’s the approach that I’ve used on the last few projects I’ve been on.

I’m rather fond of putting version information in the META-INF/MANIFEST.MF file. It’s always seemed to me like that’s the most obvious place to put version information about your .jar or .war. Certainly, every .jar or .war is required to have a MANIFEST.MF, so there’s seldom any confusion about where to look for it. Reading in the MANIFEST.MF can be a bit tricky, but I’ve posted in the past about how one can do that. If I read in the manifest, I can scrape out whatever information I’ve decided to put there. Lately, I’ve been putting in these pieces of information:

Manifest-Version: 1.0
...
Application-Name: panaceaWeb
Implementation-Build: 15268
Implementation-Build-Date: 1233009303679
Implementation-Version: 1.8-SNAPSHOT

I can format those items nicely, and present them on the bottom of my application’s web page.

So how do I actually get that information in there? That’s pretty simple. There are two Maven plugins that are interesting. One is the standard war plugin. I configure it like this:

<plugin>
  <artifactId>maven-war-plugin</artifactId>
  <version>2.0.2</version>
  <configuration>
    <manifest>
      <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
    </manifest>
    <archive>
      <manifestEntries>
        <Application-Name>${project.name}</Application-Name>
        <Implementation-Build>${buildNumber}</Implementation-Build>
        <Implementation-Version>${project.version}</Implementation-Version>
        <Implementation-Build-Date>${timestamp}</Implementation-Build-Date>
      </manifestEntries>
    </archive>
  </configuration>
</plugin>

This configuration handles almost everything. The one piece it doesn’t understand by itself it the variable reference to “buildNumber”. In order to set the “buildNumber”, we use a second plugin — the build-number plugin. When I use Maven to assemble my .war, the build number plugin pulls the build number off of the source code repository, making the build number identical to the Subversion revision number for the root of my project. I configure it like this:

<plugin>
  <groupId>org.codehaus.mojo</groupId>
  <artifactId>buildnumber-maven-plugin</artifactId>
  <version>1.0-beta-1</version>
  <configuration>
    <doCheck>false</doCheck>
    <doUpdate>false</doUpdate>
  </configuration>
  <executions>
    <execution>
      <phase>validate</phase>
      <goals>
        <goal>create</goal>
      </goals>
    </execution>
  </executions>
</plugin>

This ensures that I can always correlate the build number in the MANIFEST.MF with a Subversion identifier so that, if necessary, I can call up the exact version of the code for any debugging purposes.

Now, it turns out that Hudson will also add its own magic tags to the MANIFEST.MF. During a Hudson build, it adds the following information:

Hudson-Build-Number: 1567
Hudson-Project: panacea
Hudson-Version: 1.262

If necessary, I can now correlate the Hudson build number with the other information.

For the last several months, we’ve been using a simple tool that the P/ET Cemetery built for us — we call it the autoDeployer. The autoDeployer is scheduled to run on our test server, to check out Maven repository to see if a new version of the application has been put there. If so, it downloads it, shuts down out application server, pushes out the new version, and starts the server up again. We’ve been very happy with the autoDeployer. In particular, decoupling the “build process” from the “update the test server” process has had a lot of benefits for us. Our test server always has a successfully built version of the app on it, and we’ve been pushing out new features to our beta-test clients pretty much every day.

Recently, we added an extra feature to the autoDeployer so that we could scrape out the information in the MANIFEST.MF file and send that information to DevCreek. And this morning, I was delighted to discover a new report in DevCreek that displays that information. Here’s a graphical representation of the last several deployments of Panacea/Test Level 7. As you can see we’re pretty much getting a new deployment every night, and we can see when the cut-over from 1.7-SNAPSHOT to 1.8-SNAPSHOT took place. We can also see a couple of deployments taking place in the middle of the day, as our users have clamoured for extra features or improvements.

It's only fair to share...
Share on FacebookGoogle+Tweet about this on TwitterShare on LinkedIn

Leave a Reply