JaVa
   

Basics of Using CruiseControl

This section is a quick tutorial demonstrating how to get CruiseControl up and running over an existing project, with an existing Ant build script. You will learn how CruiseControl can detect changes, how it can invoke build scripts, and how you can publish the results. Upon completion of this chapter, you should understand CruiseControl well enough to use it with your own projects. As an example, we create a CruiseControl configuration file for the MVCHelloWorld project described earlier. We describe what we are doing at each step, and we then give a more thorough explanation later on.

The MVCHelloWorld Project

Let's create a CruiseControl configuration file for the MVCHelloWorld file, with some assumptions. The main one is that we are using CVS as a source control system.

The Configuration File

The first step is to create the configuration file. CruiseControl uses an XML-based configuration file format, and by convention, the configuration file is normally called cruise-config.xml. An otherwise empty configuration file would look like this:

<?xml version="1.0"?>
<cruisecontrol>
</cruisecontrol>


Inside the <cruisecontrol> tag, you can define projects. A single CruiseControl configuration file can hold details about many projects, and as you will see later, these projects can interact. For now, however, we have only one:

<?xml version="1.0"?>
<cruisecontrol>
 <project >
 </project>
</cruisecontrol>


Project entries in CruiseControl must have a unique name. By convention, this is typically the same as the name given to the Ant project (if Ant is used). Inside the <project> tag, we define many other tags. These can be entered in any order, but it is easiest to describe them in a logical order. The first of these is the <modificationset> element, which tells CruiseControl where to look for changes. A project can have only one <modificationset>, but it can contain a number of places to look. For this project, we assume that we are using CVS, and that the local copy already has all the details needed (in the CVS subdirectories):

<modificationset quietperiod="30" >
 <cvs localWorkingCopy="." />
</modificationset>


The quietperiod parameter is extremely important. It specifies how long ago (in seconds) the most recent change has been made. This allows people to commit related changes to the repository in several steps. If you make this value too low, you will sometimes get builds occurring that are inconsistent, with only some of the recently applied changes present. If you make the value too high, then you may have difficulty getting a build to occur, because of developers checking code in frequently. If the most recent change is within the quiet period, CruiseControl will wait until enough time has passed and then look again. As an example, if the most recent change occurred 10 seconds ago, then with the setting in the example, CruiseControl would wait for 20 seconds, and then look for changes again.

Java Start Sidebar
Timing Difficulties

The way CruiseControl works out when the most recent change was made is typically based on the source code control server's clock, but the decision as to how long to wait is based on the CruiseControl server's clock. It is important to ensure that your CruiseControl server and your source code control server have reasonably synchronized clocks. If, for example, your CruiseControl machine is a few hours behind the source code control server, then you will see CruiseControl sleeping for hours every time it detects changes.

Keeping machine clocks synchronized is an easy task these days. Modern operating systems can easily be configured to obtain their current time from a Network Time Protocol (NTP) server. Nonetheless, synchronization remains a common source of problems.

Java End Sidebar

Having decided where CruiseControl will look for changes, our next step is to configure how often it will look, and what it will do when it detects changes. This is done via the <schedule> element:

<schedule interval="30" >
 <ant antscript="build.sh" target="cruise-build" />
 <pause startTime="2100" endTime="0300" />
</schedule>


The interval attribute states how long (in seconds) CruiseControl should wait between builds before checking again. Nested inside of the <schedule> element are one or more types of builders. In this case, we have an Ant builder that will invoke the provided build.sh shell script (telling it to build the cruise-build target), and a Pause builder that stops this project between 9 p.m. and 3 a.m. every night (so that it doesn't interfere with backups).

Java Start Sidebar
Use “Antscript” by Preference

The Ant builder for CruiseControl can actually launch Ant "in-process." This approach provides a slightly faster build time, but it leads to some serious complications. The most annoying one is that Ant, or rather, some Ant tasks, might have some slight memory leaks. In typical Ant usage, these leaks don't cause problems. However, when you run it inside a long-lived process, they add up over time. Another issue is that you have to supply the class path required for your Ant build script when launching CruiseControl.

Java End Sidebar

One common misconception about CruiseControl is that the <modificationset> element, in addition to detecting the changes, will obtain the latest version. This turns out not to be the case. It is obviously going to be necessary to get the latest version of files before doing a build. The <bootstrappers> element provides this functionality:

<bootstrappers>
 <currentbuildstatusbootstrapper file="logs/helloWorld/currentbuild.txt" />
 <cvsbootstrapper localWorkingCopy="." />
</bootstrappers>


This example shows two pieces of functionality. The first is that a file will be updated to show that a build is being started. The second invokes CVS to obtain an up-to-date version of the project.

Java Start Sidebar
Keeping Track of Your Builds

An easy way to monitor the progress of your builds is to output messages into the build status file. The Ant <echo> task can be used to achieve this.

Another more complicated way is to use a tool that will observe your build. The Dashboard project (dashboard.sf.net) is one such tool.

Java End Sidebar

After the build is complete, CruiseControl stores the build log away for you. This build log is then used by the uploaders to announce the success or failure of the build:

<log dir="../logs/helloWorld">
</log> 


The log file is created in the specified directory. The name of the log file is a combination of a date-timestamp indicating when the build was done and, if the build was successful, a label for the build. A typical log name is log20040304093642LhelloWorld.1.xml. The log file is an XML-based format, and it contains various data about the build. The log file would include, at a minimum, the set of detected changes, information about the build, and the Ant (or Maven) build log. Also, it is possible to specify in the <log> element additional XML-based files to be included in the log. This makes it easy to merge in reports generated as part of the build.

Java Start Sidebar
What Sort of Information Do You Want in Your Builds?

CruiseControl can merge any XML-based data into its log files. A good question, then, is what sort of data would you want to merge. One excellent example is JUnit results. When a test failure breaks the build, having the information of the failure present in the CruiseControl log makes it easy to see what broke. The Ant JUnit task has support for supplying output in an XML format.

Java End Sidebar

This log file will later be transformed using Extensible Style Sheet Language Transformations (XSLT) style sheets. CruiseControl comes with style sheets for displaying information about several common Ant tasks, as well as support for JUnit and Checkstyle XML log files. Assuming you know XSLT, it is relatively easy to create additional style sheets to display other information that you want to see. The last step involved in creating the configuration file is to enter how you want the results published. CruiseControl has support for many ways of publishing build information. For this example, let's send an e-mail notification as well as update the build status file:

<uploaders>
 <currentbuildstatusuploader file="logs/helloWorld/currentbuild.txt" />
 <email mailhost="localhost" returnaddress="cruise@localhost"
 defaultsuffix=""
 buildresultsurl="http://localhost:8080/cruisecontrol/buildresults/helloWorld">
 <failure address="buildmaster@localhost" />
 </email>
</uploaders>


This code creates a very simple e-mail message, which is sent to the people who made changes in the build. For this example, information on failed builds is also sent to the "buildmaster." CruiseControl can also be configured to send messages on successful builds in a similar manner, or simply send include an address on all notices. The e-mail sent by this uploader is a simple one-line message, with a hyperlink to the reporting page (as specified in the buildresultsurl attribute). The subject of the message indicates success or failure, allowing developers to use the filter rules in their e-mail client to sort messages appropriately.

Java Start Sidebar
Where's the Address Book?

When CruiseControl gets the list of changes from the source control system, it also gets the user IDs of the people who made the changes. The assumption made here is that the user ID in the source control system will be a valid local e-mail address.

That isn't always the case. Fortunately, you can use CruiseControl to map user IDs to e-mail addresses. You can also sometimes get the source control system to do it for you. For CVS, this is done using the special CVSROOT/users admin file.

Java End Sidebar

Other ways of publishing results include using a fancier e-mail message, with an HTML view of the log file included, or announcing the build results using an instant messaging server (support for IBM's SameTime software is included in CruiseControl). In addition, uploaders can be used to transfer the build log, and artifacts of the build process, to another location (for example, to be published via a Web server). That's the complete configuration file. To make the picture a bit clearer, this is what it looks like now it's finished:

<?xml version="1.0"?>
<cruisecontrol>
 <project >
 <bootstrappers>
 <currentbuildstatusbootstrapper file="logs/helloWorld/currentbuild.txt" />
 <cvsbootstrapper localWorkingCopy="." />
 </bootstrappers>
 <modificationset quietperiod="30" >
 <cvs localWorkingCopy="." />
 </modificationset>
 <schedule interval="30" >
 <ant antscript="build.sh" target="cruise-build" />
 <pause startTime="2100" endTime="0300" />
 </schedule>
 <log dir="../logs/helloWorld">
 </log> <uploaders>
 <currentbuildstatusuploader file="logs/helloWorld/currentbuild.txt" />
 <email mailhost="localhost" returnaddress="cruise@localhost"
 defaultsuffix=""
 buildresultsurl="http://localhost:8080/cruisecontrol/buildresults/helloWorld">
 <failure address="buildmaster@localhost" />
 </email>
 </uploaders>
 </project>
</cruisecontrol>


The order of the elements inside the project directory is not important; the order that is presented is a common one, largely because it is the order used in the examples provided with CruiseControl.

Tying Up the Loose Ends

There are still some loose ends we need to tie up. The first one is that the Ant target that we want to run (cruise-build) does not exist in the build.xml file yet. It is not a complex task, but it needs to do the basic steps common to all automated builds: clean the environment, build from scratch, then verify the build. Targets exist in the build.xml file for each of these, but there isn't any single target that will do it all. Adding this target is a simple step, however:

<target name="cruise-build" depends="clean,package,test" />


The second loose end is that we do not yet have an easy way to run CruiseControl. The most common way to do this include creating a shell script or batch file that lets us invoke CruiseControl. Fortunately, example scripts are included with the CruiseControl distribution. For the sake of this example, we've provided a simple UNIX shell script:

#!/bin/bash
# The root of the CruiseControl directory. The key requirement is that this is the parent
# directory of CruiseControl's lib and dist directories.
CCDIR=../cruisecontrol/main LIBDIR=$CCDIR/lib DISTDIR=$CCDIR/dist CRUISE_PATH=$DISTDIR/cruisecontrol.jar:$LIBDIR/log4j.jar:\
$LIBDIR/jdom.jar:$LIBDIR/mail.jar:$LIBDIR/activation.jar EXEC="java -cp $CRUISE_PATH CruiseControl $@"
echo $EXEC
$EXEC


Running CruiseControl

To run CruiseControl, all you need to do is invoke the shell script and tell it where the configuration file is:

sh ./cruisecontrol.sh -configfile cruise_config.xml


You can also supply a port address that can be used by an in-built HTTP server. This allows the CruiseControl service to be controlled remotely:

sh ./cruisecontrol.sh -configfile cruise_config.xml -port 8180


Java Start Sidebar
Cruise RemoteControl

The in-built HTTP server uses the HTTP Java Management Extensions (JMX) adapter supplied by Oracle. It is also possible to use Remote Management Interface (RMI), and in future versions of CruiseControl, full support for JMX Remoting will be included.

Java End Sidebar

When first run, CruiseControl creates a label for the project based on the project name; for our example, the first label would be helloWorld.1, the second label would be helloWorld.2, and so forth. It also assumes that the last build (for modification purposes) was performed at midnight. Both of these options can be changed via the Web interface, if desired. These values (and other dynamic values about each project) are saved in a [project].ser file, after the first build attempt (though you can force the serialization through the Web interface). Typically, CruiseControl will be run as a service in the background, similar to how a Web server is run. On UNIX or Linux machines, this is easy to do; simply add the shell script to the appropriate runlevel. For Windows, it is somewhat more complicated. One program to assist with this is JavaService, from Alexandria Software Consulting (http://www.alexandriasc.com/software/JavaService/index.html); however, there are a number of other options, and no particular solution is recommended.

CruiseControl has extensive logging built into it, using the Jakarta log4J libraries. An example log4j configuration file is included in the CruiseControl distribution.

Viewing the Logs

The CruiseControl log files, while very detailed, are not exactly easily readable. Fortunately, CruiseControl comes with two ways of viewing them in a human-readable form. The HTML e-mail uploader has already been discussed. The other is a Web app that can index the logs and display them in a human-readable format. The first step in installing the Web app is to compile it; just like the main CruiseControl program, the Web app comes in source-only form. This is simple enough; all that you need to do is go into the directory and run the build script. You can take advantage of this process to customize the Web app slightly for your own environment:

cd ../cruisecontrol/jsp sh ./build.sh -Duser.log.dir=/path/to/logs \
-Duser.build.status.file=currentbuild.txt \
-Dcruise.build.artifacts.dir=/path/to/artifacts war


You can insert the properties you are overriding into an override.properties file, so that you do not have to enter them again if you rebuild. The user.log.dir property must match that used in the cruise-config.xml file, with the project name stripped (this is part of the multiproject support in CruiseControl). Similarly, if you have used an Artifactuploader in your cruise-config.xml file, the cruise.build.artifacts.dir property must match this path (if you haven't used an Artifactuploader, you can enter any value). The user.build.status property should be the path to the build status file, relative to the project log directory.

The result of this build process is a WAR file that can be deployed into any Java Web app Server, such as Tomcat. Assuming that it is deployed into Tomcat running on port 8080, the URL to the reporting Web app will be http://localhost:8080/cruisecontrol/buildresults/helloWorld; note that this matches the buildresultsurl property specified in the e-mail uploader in the cruise-config.xml file.

Wrapping It Up

With the CruiseControl service installed and running, and the Web app built, the helloWorld project is ready to go. To trigger some builds, however, you need to have some activity in the CVS repository. That's where your developers come in, and where we leave you to it.


JaVa
Comments