Exposing SVN version and build time with Ant

Darren - 30 Mar 2009

As a developer, I find that an application's most useful version number is its SVN version; once I have that number, I can head over to the repository and figure out exactly what code is running. This is extremely useful both during development (Did I upload the correct .war to my staging server?) and for ongoing maintenance (What version is running on this server that needs to be updated?)

Fortunately, it's pretty easy to configure Ant to automatically inject the SVN version into your application every time you build it. Let's say that you have a particular file (/WEB-INF/jsp/admin.jsp) that should contain the SVN version number.

We take advantage of svntask, a nice simple library that lets Ant use SVN. Download/unzip the project files, place them somewhere convenient in your project, and add the following to your Ant build file: (modifying the fileset directory to where you put the svntask libraries)

<target name="version">
  <typedef resource="com/googlecode/svntask/svntask.xml">
    <classpath>
      <fileset dir="${lib.dir}/buildtime">
        <include name="svnkit.jar" />
        <include name="svntask.jar"/>
      </fileset>
    </classpath>
  </typedef>
  <svn>
    <info path="." revisionProperty="revisionVersion" />
  </svn>

  <property name="svn.version" value="${revisionVersion}" />
</target>

This stores the SVN version number of your project root in the "svn.version" Ant property. Now, it's just a matter of copying the correct file from the source web directory to the target web directory before you package your .war file: (The following will require some modification depending on how you normally package your wars.) We use Ant's copy/filter tasks to replace all occurances of the token "@version@" in admin.jsp with the SVN version number.

<target name="war.pre" depends="version">
  <copy file="${src.web.dir}/WEB-INF/jsp/admin.jsp" tofile="${target.war.expanded.dir}/WEB-INF/jsp/admin.jsp" overwrite="true">
    <filterset>
      <filter token="version" value="${svn.version}" />
    </filterset>
  </copy>
</target>

Now, the following snippit in admin.jsp

<div id="footer">
  <p>Build Number @version@</p>
</div>

becomes

<div id="footer">
  <p>Build Number 1692</p>
</div>

This is good enough for production releases, where the package application will (or should) be compiled straight from the repository. However, during development, I often won't be checking in changes between builds. So, to tell those builds apart, I find it useful to include the build timestamp as well, which I can get using Ant's tstamp task. This isn't a perfect solution, but it's enough to give me some reassurance that I didn't accidentally deploy an old build to my local server.

<target name="war.pre" depends="version">
  <tstamp>
    <format property="war.tstamp" pattern="yyyy-MM-dd HH:mm:ss z" />
  </tstamp>
  <copy file="${src.web.dir}/WEB-INF/jsp/admin.jsp"
        tofile="${target.war.expanded.dir}/WEB-INF/jsp/admin.jsp"
        overwrite="true">
    <filterset>
      <filter token="version" value="${svn.version}" />
      <filter token="time" value="${war.tstamp}" />
    </filterset>
  </copy>
</target>

Now, inside of admin.jsp, I can include the following snippit

<div id="footer">
  <p>Build Number @version@ (@time@)</p>
</div>

and Ant will transform this into

<div id="footer">
  <p>Build Number 1692 (2009-03-30 11:20:15 PDT)</p>
</div>

which is exactly what I want.

comments powered by Disqus