I’ve done something simple, yet cool and useful in our Ant builds to make them work a little nicer with Hudson.  I’ve modified things so our Jars/Wars get stamped with version control information from Hudson.  To do this, I take advantage of the fact that when Hudson starts an Ant build, it puts certain key values in the environment variables, so I grab them and stuff them into the manifests for the jars.

<macrodef name="make-jar" description="Create a jar file">
  <attribute name="basedir" description="Root directory for the JAR" />
  <attribute name="name" description="Name of the JAR file to create" />
  <sequential>
    <!--
    These property tasks will not do anything if run from within Hudson, because
    Hudson passes these in, and Ant properties are immutable.  Effectively, this
    sets default values for these properties.
     -->
    <property environment="env" />
    <property name="env.BUILD_NUMBER" value="Not built from Hudson" />
    <property name="env.BUILD_TAG" value="Not built from Hudson" />
    <property name="env.BUILD_ID" value="Not built from Hudson" />
    <property name="env.JOB_NAME" value="Not built from Hudson" />
    <mkdir dir="dist" />
    <jar basedir="@{basedir}" destfile="dist/@{name}">
      <manifest>
        <attribute name="Built-By" value="${user.name}" />
        <attribute name="Hudson-Job" value="${env.JOB_NAME}" />
        <attribute name="Build-Number" value="${env.BUILD_NUMBER}" />
        <attribute name="Build-Date-Time" value="${env.BUILD_ID}" />
        <attribute name="Build-Tag" value="${env.BUILD_TAG}" />
      </manifest>
    </jar>
  </sequential>
</macrodef>	

This <macrodef> gets used whenever we make a jar file. Inside the <sequential> block, there is a <property> tag that first loads properties for all the environment variables and puts a env. prefix on them–this will defined properties for the values Hudson passes in.  These are followed by four <property> tags which define default values of “Not built from Hudson” for certain properties in case Hudson did not invoke the Ant script (like on a local developer machine).  Since all properties in Ant are immutable, if Hudson sets them before calling Ant, these last four <property> tasks won’t do anything.  Then, in the <jar> task, the properties I grabbed from the environment are added to the manifest so it looks like this:

Manifest-Version: 1.0
Ant-Version: Apache Ant 1.6.5
Created-By: 1.5.0_14-b03 (Sun Microsystems Inc.)
Built-By: SYSTEM
Hudson-Job: MyProject
Build-Number: 337
Build-Date-Time: 2008-07-02_17-28-56
Build-Tag: hudson-MyProject-337

And we simply make all our jars by invoking the <macrodef>:

<make-jar basedir="bin" name="MyProject.jar" />
Leave a Reply