Blog News about what we are doing

Fernando Dobladez

Build Version Maven Plugin for Git

Written by Fernando Dobladez

For all artifacts we build on our projects (.war files, packaged installers, single .jar archives, etc.) we always want to include precise and descriptive information about the build: time stamps, version number, commit hash and whether it’s a final/pre/internal release.

We include all build information inside the artifacts themselves for programmatic consumption (e.g. for showing the current build version at the bottom of a some web pages or “about” screens) and also for humans: to know exactly what build each artifact is in, for reporting and reproducing defects, for troubleshooting dependency issues and so forth. Even the naming of some artifacts (like, RPM packages) depend on build information.

Initial approach

We are using Maven for many of our projects. We started using the existing buildnumber-maven-plugin to extract build information from git; unfortunately, it does not provide all we need. So, we later started cooking simple groovy scripts (via gmaven-plugin) which called git describe and other git commands to obtain the information we wanted and set it as project properties.

This approach worked for awhile. However, the script started to get complicated and was not easy to reuse across projects.

Our current solution

With that in mind, I wrote buildversion-plugin: a simple Maven plugin that provides the functionality we need. It extracts build info from the current git branch, including timestamp, commit hash, tag name and number of commits since the last tag.

The problem with git-describe

We initially relied on calling git describe to obtain a descriptive version number, which includes the most recent tag and the number of commits since such tag.

Unfortunately, the logic behind git describe searches for the closest tag back in history following all parent commits on merges. This means it may select tags you originally put on another branch. So, if you are working on a development branch and merge back a fix made on a release branch, calling git describe on the development branch may shield a description that includes a tag you placed on the release branch.

Other people run into the same problem. There’s been a discussion on GIT’s mailing list about git describe’s logic and the need for adding a --first-parent option. And there’s even a working patch to add --first-parent.

Until git describe accepts a --first-parent argument, this plugin implements its own logic, which basically leverages git log --first-parent and traverses the history on the current “line of development”, parsing the tag names and counting the number of commits as it goes.

Don’t repeat yourself

One of the reasons why we started writing this plugin was to obtain the version number from git in order to “inject” it into the Maven project. That is, we wanted to stop having to maintain the version number inside the pom.xml’s given that the information was already managed by git. We couldn’t (yet?) achieve this: apparently, Maven reads the version from the pom before invoking the plugins; so, even after we set the version number most of Maven’s operations continue using the version originally set in the pom.xml.

Notes about the implementation

It’s a really simple plugin. However, I coded it in Clojure as an exercise and to prove its Java “interoperability”. Luckily, Hugo Duncan did all of the hard work already, so it was quite simple.

I hope the plugin is useful for others. If you try it, let us now if you find issues or have ideas to improve it.

Acknowledgment: thanks to José Rozanec who implemented the first prototype trying to inject the project version. He’s also the first one to seriously test the current buildversion-plugin.