Version Labeling and Continuous Frustration

I approach continuous integration (CI) servers in the same way I do my IDE -- as a tool of convenience for performing tasks I could choose to perform manually. I would no more have a build system reliant upon a specific CI server than I would write code that was only recognized by a specific IDE. Thankfully the CI servers with which I've worked conform to my philosophy. They do not seek to replace your build system as much as provide much needed automation. There is one area, though, where I feel CI servers violate this ideal, and that's creating a unique build/version label.

Out-of-the-box, most CI servers provide a simple numbering scheme in order to produce a unique label for each build. Generating a build/version label is a task I prefer to happen within the build itself, so that the build is truly self-contained. Take our builds, for example. I've made use of the ant task buildnumber, so, upon a build, ant reads and increments a build-number property file and appends it to the project's "base version," the result being a label like "", where "6" would be the build number. I imagine this is a common scenerio -- indeed its why theant task exists. Once I launch an official build via command-line, label generation happens automatically, and the repository is tagged "Build".

Introduce the CI server, though, and suddenly I'm having to jump through hoops to accommodate this setup. At the crux of the problem is this: from the CI server's perspective, a build starts upon checkout or update of a project, and therefore wants to know the build label prior to actually running the build. That's putting the cart before the horse, in my opinion, although I do understand the reasoning. Should access to the repository fail, for example, the CI server is able to report " Build failed due to VCS unavailability".

What I've done is create a small script whose sole duty is to fetch the next build label for the CI server -- fortunately the CI servers with which I've worked allow for pre-build script execution in some manner or another. With CruiseControl, I use an "antbootstrapper" to invoke a small ant build named "get-next-version.xml". CruiseControl passes the value generated from that to the official build, so ant is invoked like so: "ant package -Dbuild.label=".

However, my work isn't done. I still must ensure that my build-number property file is accurate, even if the build.label is being provided instead of being generated. So, in addition to configuring CruiseControl in the manner described, I also must have my build.xml extract the build number from the passed label (in this case, "6"), and update the build-number file appropriately.

Granted, I imagine most folks don't rely on ant to generate build numbers, and therefore the CI server provided functionality is a convenient mechanism. The minority of us who do, though, ought to be able to supply build labels to the server in an easier fashion.