Driving On CruiseControl - Part 2

Lasse Koskela
Accenture Technology Solutions

In Part 1 of this tutorial, we set up the CruiseControl Continuous Integration server against a Subversion repository. In this second part, we'll continue where we left off by taking our build results online with the CruiseControl reporting web application.

Build results online

As we discussed in Part 1, there are some very good reasons for wanting to put your Continuous Integration builds' results online for everyone to see. Many don't like filling their inbox with full-blown reports, many projects don't have easy access to a mail server, and many projects would like to integrate the build results to other dashboard-like applications which don't quite fit in with the HTML email publisher solution.

In the case of CruiseControl, the web application used for presenting build results needs to work with the XML log files produced by CruiseControl during a build cycle. Not a surprise, the most used application used for exposing CruiseControl's build results over the Web is the reporting application that comes as part of the CruiseControl distribution.

Let's dig in.

Configuring the CruiseControl web application

The first step in getting the CruiseControl reporting application up and running is to build it from the sources and configure a few parameters.

Below is the familiar-looking directory structure from Part 1:

The top-level directory structure

Assuming you used the above directory structure, this is how you build the cruisecontrol.war web application:

C:\CIA\BuildServer\CruiseControl\reporting\jsp> build war
lib/ant.jar;lib/optional.jar;lib/junit.jar;lib/xerces.jar
Using Javac!
Buildfile: build.xml

clean:
   [delete] Deleting directory C:\CIA\BuildServer\CruiseControl\reporting\jsp\dist
   [delete] Deleting directory C:\CIA\BuildServer\CruiseControl\reporting\jsp\classes
   [delete] Deleting directory C:\CIA\BuildServer\CruiseControl\reporting\jsp\testresults
   [delete] Deleting directory C:\CIA\BuildServer\CruiseControl\reporting\jsp\tmp

init:
    [mkdir] Created dir: C:\CIA\BuildServer\CruiseControl\reporting\jsp\dist
    [mkdir] Created dir: C:\CIA\BuildServer\CruiseControl\reporting\jsp\classes
    [mkdir] Created dir: C:\CIA\BuildServer\CruiseControl\reporting\jsp\testresults
    [mkdir] Created dir: C:\CIA\BuildServer\CruiseControl\reporting\jsp\tmp

check-duplication:

checkstyle:

compile:
    [javac] Compiling 27 source files to 
	C:\CIA\BuildServer\CruiseControl\reporting\jsp\classes

test:
    [javac] Compiling 21 source files to 
	C:\CIA\BuildServer\CruiseControl\reporting\jsp\classes
    [junit] Running net.sourceforge.cruisecontrol.BuildInfoTest
    [junit] Tests run: 3, Failures: 0, Errors: 0, Time elapsed: 0,111 sec
    [junit] Testsuite: net.sourceforge.cruisecontrol.BuildInfoTest
    [junit] Tests run: 3, Failures: 0, Errors: 0, Time elapsed: 0,111 sec

    ...

-set.log.dir:
    [input] WARNING! Property user.log.dir not set!  
	Please enter the absolute path to the CruiseControl logs directory:
C:\CIA\BuildServer\CruiseControl\main\logs

-set.status.file:
    [input] WARNING! Property user.build.status.file not set!  
	Please enter the absolute path to the current build status file:
currentbuild.txt

-set.artifacts.dir:
    [input] WARNING! Property cruise.build.artifacts.dir not set!  
	Please enter the absolute path to the directory where additional build 
	artifacts are stored:
/

create-web-xml:
     [copy] Copying 1 file to 
	 C:\CIA\BuildServer\CruiseControl\reporting\jsp\tmp

war_jdk14:

war_pre14:
      [war] Building war: 
	  C:\CIA\BuildServer\CruiseControl\reporting\jsp\dist\cruisecontrol.war

war:

BUILD SUCCESSFUL
Total time: 56 seconds

C:\CIA\BuildServer\CruiseControl\reporting\jsp>

Notice how the -set.xxx.xxx targets are asking for input? That's the build script noticing that it's missing some essential details about the location of your CruiseControl logs directory, the currentbuild.txt file, and the artifacts directory. The build script inserts the given paths into the web.xml of the resulting cruisecontrol.war archive.

After building the reporting web application, we need to deploy it somewhere. I chose to use Jakarta Tomcat as my web container of choice. You could just as easily use another J2EE compliant web container such as Jetty or a full-blown J2EE application server such as JBoss.

Tomcat has an auto-deployment directory named "webapps" where you can just drop a .war file and it gets deployed automatically within a few seconds (or whenever you restart Tomcat if it's not running at the time). That's exactly what we're going to do next.

With Tomcat installed (unzipped) to C:\CIA\BuildServer\Tomcat, it can be started by double-clicking on bin\startup.bat:

25.9.2004 16:39:57 org.apache.coyote.http11.Http11Protocol init
INFO: Initializing Coyote HTTP/1.1 on http-8080
25.9.2004 16:39:57 org.apache.catalina.startup.Catalina load
INFO: Initialization processed in 1322 ms
25.9.2004 16:39:57 org.apache.catalina.core.StandardService start
INFO: Starting service Catalina
25.9.2004 16:39:57 org.apache.catalina.core.StandardEngine start
INFO: Starting Servlet Engine: Apache Tomcat/5.0.28
25.9.2004 16:39:58 org.apache.catalina.core.StandardHost start
INFO: XML validation disabled
25.9.2004 16:39:58 org.apache.catalina.core.StandardHost getDeployer
INFO: Create Host deployer for direct deployment ( non-jmx )
25.9.2004 16:39:58 org.apache.catalina.core.StandardHostDeployer install
INFO: Processing Context configuration file URL 
file:C:\CIA\BuildServer\Tomcat\conf\Catalina\localhost\admin.xml
25.9.2004 16:39:58 org.apache.struts.util.PropertyMessageResources <init>
INFO: Initializing, config='org.apache.struts.util.LocalStrings', 
returnNull=true
25.9.2004 16:39:58 org.apache.struts.util.PropertyMessageResources <init>
INFO: Initializing, config='org.apache.struts.action.ActionResources', 
returnNull=true
25.9.2004 16:39:59 org.apache.struts.util.PropertyMessageResources <init>
INFO: Initializing, config='org.apache.webapp.admin.ApplicationResources', 
returnNull=true
25.9.2004 16:40:01 org.apache.catalina.core.StandardHostDeployer install
INFO: Processing Context configuration file URL 
file:C:\CIA\BuildServer\Tomcat\conf\Catalina\localhost\balancer.xml
25.9.2004 16:40:01 org.apache.catalina.core.StandardHostDeployer install
INFO: Processing Context configuration file URL 
file:C:\CIA\BuildServer\Tomcat\conf\Catalina\localhost\manager.xml
25.9.2004 16:40:01 org.apache.catalina.core.StandardHostDeployer install
INFO: Installing web application at context path /jsp-examples from URL 
file:C:\CIA\BuildServer\Tomcat\webapps\jsp-examples
25.9.2004 16:40:01 org.apache.catalina.core.StandardHostDeployer install
INFO: Installing web application at context path  from URL 
file:C:\CIA\BuildServer\Tomcat\webapps\ROOT
25.9.2004 16:40:01 org.apache.catalina.core.StandardHostDeployer install
INFO: Installing web application at context path /servlets-examples from URL 
file:C:\CIA\BuildServer\Tomcat\webapps\servlets-examples
25.9.2004 16:40:01 org.apache.catalina.core.StandardHostDeployer install
INFO: Installing web application at context path /tomcat-docs from URL 
file:C:\CIA\BuildServer\Tomcat\webapps\tomcat-docs
25.9.2004 16:40:01 org.apache.catalina.core.StandardHostDeployer install
INFO: Installing web application at context path /webdav from URL 
file:C:\CIA\BuildServer\Tomcat\webapps\webdav
25.9.2004 16:40:01 org.apache.coyote.http11.Http11Protocol start
INFO: Starting Coyote HTTP/1.1 on http-8080
25.9.2004 16:40:02 org.apache.jk.common.ChannelSocket init
INFO: JK2: ajp13 listening on /0.0.0.0:8009
25.9.2004 16:40:02 org.apache.jk.server.JkMain start
INFO: Jk running ID=0 time=0/50  
config=C:\CIA\BuildServer\Tomcat\conf\jk2.properties
25.9.2004 16:40:02 org.apache.catalina.startup.Catalina start
INFO: Server startup in 4447 ms

Dropping the cruisecontrol.war into the webapps directory should result in a bit more activity in the Tomcat window:

25.9.2004 16:41:42 org.apache.catalina.core.StandardHostDeployer install
INFO: Installing web application at context path /cruisecontrol from URL 
file:C:/CIA/BuildServer/Tomcat/webapps/cruisecontrol

Looking familiar? Good. You've just put your build results online!

Exploring the reporting application UI

With Tomcat running and the reporting application deployed, it's time to verify the installation by pointing a web browser at the front page:

The front page of the CruiseControl reporting application

As you can see, the front page gives a very brief summary of all projects for which the reporting application can find reports under the logs directory we configured it to look at. In addition to the projects' names, the front page lists the latest status of each project (passed/failed) and when the last build was made.

Now try clicking one of the projects listed. Do you see an all-blue page like this?

There's a bit more work to do for you...

If you see a page like that and your web container's log file has a stack trace saying "org.apache.xml.utils.WrappedRuntimeException: The output format must have a '{http://xml.apache.org/xalan}content-handler' property!", the problem is a version clash between Xerces and Xalan under JDK 1.4. Some solutions you should try to fix this are:

Hopefully, with more or less tweaking, you should be looking at a page like this:

The project build results page

First of all, the navigation pane on the left-hand side shows you the project's scheduling status, i.e. tells you when the current build was started or when the next build starts (depending on whether CruiseControl is currently waiting for the next build cycle or doing a build). Below the scheduling status, there's a list of dated builds. Clicking on the date of a build opens up that particular build's results (or whatever tab you had selected when clicking the link). Once you've got more than 10 builds under your belt, only the first 10 will be displayed as links and the rest will be collected into the dropdown box below those links.

See those tabs in the top of the main view? The reporting application splits the information in the CruiseControl log file into smaller views so you can look at just the information you want.

The first tab, "Build Results", displays a summary of the selected build including date information, a list of failed unit tests, and a very useful list of modifications in the source repository since the previous build (a.k.a. "the suspects" if the build has turned from green to red). A quick peek at this page is most often enough to give you the information you're looking for. Also, the "Build Results" tab includes a link named "Build Artifacts", which leads to a directory listing of the project's artifacts directory -- the place where CruiseControl gathers a project's build output files (such as sample.jar for the sample project we used in Part 1).

If you feel like digging deeper, the "Test Results" tab displays a full listing of all tests run and their pass/fail status and the execution time. The "XML Log File" page renders the raw XML log file for you to look at (to date, I have not needed to but it's good to know it's there just in case). The "Metrics" tab displays a couple of graphs showing the green/red stats for your project, which is a more recent and very nice little "extra" for the reporting application.

The last tab, "Control Panel", is probably displaying an error page to you. Why is that? Well, if you look at the HTML generated by CruiseControl, you'll see that the error page comes from an embedded IFRAME pointing to port 8000 on the build server. What it's expecting to find from that port is the CruiseControl JMX server (or, more accurately, the HTTP adapter for it).

At this point, let's go and restart the CruiseControl process with the JMX features enabled:

C:\CIA\BuildServer\CruiseControl\main\bin> cruisecontrol -port 8000
"C:\j2sdk1.4.2_05\bin\java" -cp "..." CruiseControl -port 8000
[cc]syys-25 18:38:24 Main          - CruiseControl Version 2.1 Compiled on 
September 12 2004 1552
[cc]syys-25 18:38:24 trolController- projectName = [SampleCCProject]
[cc]syys-25 18:38:24 Project       - Project SampleCCProject:  reading 
settings from config file [C:\CIA\BuildServer\CruiseControl\main\bin\config.xml]
[cc]syys-25 18:38:24 trolController- projectName = [SampleCCProject2]
[cc]syys-25 18:38:24 Project       - Project SampleCCProject2:  reading 
settings from config file [C:\CIA\BuildServer\CruiseControl\main\bin\config.xml]
[cc]syys-25 18:38:25 ontrollerAgent- Starting HttpAdaptor with CC-Stylesheets
[cc]syys-25 18:38:25 ontrollerAgent- starting httpAdaptor
[cc]syys-25 18:38:25 Project       - Project SampleCCProject starting
[cc]syys-25 18:38:25 Project       - Project SampleCCProject:  idle
...

The key here is to give the CruiseControl startup script the port number for the JMX adapter as an argument. We're using port 8000 here as it's the default for the reporting web application. If you need to use a different port, you'll have to start CruiseControl with a different port number and edit controlpanel.jsp under reporting/jsp (yes, I know...).

With CruiseControl running JMX enabled, reload the "Control Panel" tab in your browser and you should see the CruiseControl JMX Console:

The CruiseControl JMX Console

Tip: You might want to customize the reporting web application a little by making the "Control Panel" link open the JMX Console in a new window instead of squeezing it into a tiny IFRAME.

The JMX Console is a very handy tool for changing different configurations at runtime without restarting CruiseControl. Try navigating to your project (link named "CruiseControl Project:name=SampleCCProject") to see all the nice things you can change or trigger through the JMX Console.

For example, you can change the project's build interval by putting a new value for the "BuildInterval" attribute and clicking the "set" button right next to the text field. You can also force a build by clicking on the "Invoke" button for an operation named "build". Play around with the console and keep the output of the CruiseControl process open to see how your doings affect CruiseControl's. Makes you wonder why more products don't ship with similar JMX utilities, doesn't it.

That's all for now

I'm afraid that's all for now. In the next part of my series of CruiseControl tutorials, I might show how to connect your CruiseControl server to the developers' desktops. "I might" means that's what I'm going to do unless I get feedback to tell me otherwise.