CruiseControl Best Practices: Publish with a Publisher

Welcome to the first article in the CruiseControl Best Practices series here at build-doctor.com.

Today's article is about Publishers: Many projects use the concept of publishing: placing built artifacts into a repository, or making test results available to end users. The ArtifactsPublisher is a very popular way to publish to CruiseControl's own repository of timestamped directories, making logs and archives available via the CruiseControl dashboard or legacy reporting application. But ArtifactsPublisher is just one of a family of Publishers, my favourite being the AntPublisher. If your Ant build finishes by publishing artifacts to a repository or tagging your version control system, there may be another way to do things. Consider the Ant example below:


<project>
<target name="dist" description="build everything">
 </target>
<target name="clean" description="delete all build artifacts">
</target>
<target name="test" description="run unit tests">
</target>
<target name="publish" description="publish to repository">
</target>
<target name="cruise" depends="clean,dist,test,publish"/>
</project>

The end goal of the build is to publish unit-tested artifacts to an
unspecified repository of some kind via the publish target. This
is well and good, but the concept of publishing doesn't really fit the
developer build; if we can disconnect the publishing activity from the
rest of the build, we can run the same build in CruiseControl as the
developers. To do this, have CruiseControl invoke your developer
build, leaving publishing as a separate Ant target:


<project>
<target name="dist" description="build everything">
</target>
<target name="clean" description="delete all build artifacts">
</target>
<target name="test" description="run unit tests">
</target>
<target name="publish" description="publish to repository" if="logfile">
</target>
<target name="dev" depends="clean,dist,test"/>
</project>

The 'if' attribute on the 'publish' target ensures that the target can
only ever be run by a publisher or a determined person. Next, you
need to make some changes to your CruiseControl configuration:


<!-- some config removed from this example -->
<schedule interval="60">
<ant antWorkingDir="checkout.dir}" buildfile="build.xml" target="dev"/>
</schedule>
<publishers>
<onsuccess>
<antpublisher antWorkingDir="checkout.dir}" buildfile="build.xml" target="publish">
<onsuccess>
</publishers>

And you're done. Once you apply the new configuration to
CruiseControl, it will start to run the same Ant build as the
developers, meaning that there's no mystery when the build
breaks. It may also shorten the build feedback loop by reporting
success faster. While the developers celebrate or lament the
state of the build, the AntPublisher can get on with the work of
pushing artifacts around your network. I also use it to tag the
codebase on a successful build - another thing that is specific to
Continuous Integration. Publishers can be configured unadorned
inside the <publishers> element in the config file to run every
time a build completes regardless of status, or they can be wrapped in <onsuccess> or <onfailure> to run conditionally.

Publishers have a cousin element called Bootstrappers, but I'll cover that another time.

DevOps New Zealand