This is slightly out of date, if you're using a more recent version (e.g. 2.1 or later)
Cruise Control Installed by Jonathan Julian, jonjulian at earthlink.net
Purpose of this document
This document is meant to help you get running with CruiseControl 2.0 (CC). Starting from the download, it will take you through installing, configuring, and starting CC for the first time. Once you've got CC running, you won't want it to ever stop!
I am assuming that you wish to download the binary distribution of CC. I am also assuming that your project's build is being built using Ant scripts. Before tackling CC to automate your build process, you need Ant scripts to compile, package, deploy, and test your project. If you don't have this yet, do it now! You should be able to type 'ant doitall' and have all the code compile, unit tests run (using JUnit, of course), your application started and any functional tests run. Any failures along that way should cause Ant to report that the BUILD FAILED. A successful build should report BUILD SUCCEEDED.
I do not explain the installation of the webapp here. First, it is pretty simple, just edit the web.xml file, put it back into the war, and drop the war into your container for deployment. Secondly, it does not yet provide any 'killer' features over the email notification system. But I'm sure this is only temporary - using a webapp as a central "meeting place" for continuous integration will be invaluable! Hopefully the future of the webapp will include features such as build loop start/stop, force build, detailed current status, repository history, etc.
Download Cruise Control
Download the latest Cruise Control binaries from SourceForge. The cruisecontrol2.0.zip contains two zip files - one for the CC build loop app (cruisecontrol-2-bin.zip), and one for the buildresults display webapp (cruisecontrol-2-jsp-bin.zip). For now, we just want to get the build loop running (more on the webapp some other time, but first things first). Unzip the cruisecontrol-2-bin.zip file into an empty dir - this will be your INSTALL_DIR.
INSTALL_DIR
|_bin
cruisecontrol.sh
cruisecontrol.bat
|_dist
cruisecontrol.jar
|_docs
...many docs here...
|_lib
...many jars here...
Configure Cruise Control
You should not need to modify any files. It is possible that the two launch scripts in the bin dir need you attention depending on your OS - have a look to be sure. The jar file containing all the code is in the dist dir. This is a convenient spot for it that makes it easy to upgrade when a newer version is released. 3rd party jars are in the lib dir. I recommend not trying to "swap" any of your own versions of these libraries - if you do, "buyer beware". And of course, the CC docs are installed into the docs subdir.
Set Up Ant build scripts to wrap your project
Reading the CC docs, some docs suggest adding targets for CC into your build. I don't recommend this for a few reasons:
#. I like CC to run my builds as an "outside agent". If I decide to stop using CC, I don't want artifacts in my build scripts.
#. Code control - all my build scripts are in code control. CC needs a build script to run, so I get into a chicken-and-egg situation. CC 2.0 has a nifty feature to allow a "bootstrap" task so you can fetch a file from code control, but I have chosen not to use it. Perhaps someone out there can change my mind. I prefer to create a cc-build.xml file that will make calls "into" my fetched build file to build the project. This build file will contain the CC targets and all the "smarts" to tell CC how to build, deploy and test my project. Put it into the INSTALL_DIR. Here is an example file:
<project name="myproject-cc" default="masterbuild">
<target name="checkout" description="Update packages from CVS">
<cvs cvsroot=":pserver:user@host:/home/cvs/cvsroot" package="myproject" dest="."/>
</target>
<target name="clean" description="Clean all build products">
<delete dir="myproject"/>
</target>
<target name="build">
<ant dir="myproject" target="build"/>
</target>
<target name="rununittests" depends="build">
<ant dir="myproject" target="test"/>
</target>
<target name="smoketest" depends="build">
<ant dir="myproject" target="smoketest"/>
</target>
<target name="masterbuild"
depends="checkout,rununittests,smoketest"
description="Cruise control master build"/>
<target name="cleanbuild"
depends="clean,masterbuild"
description="Cruise control clean build"/>
</project>
Note the masterbuild and cleanbuild tasks - these are the CC "hooks". We will cover these next. My example uses the cvs task to fetch code from a code control repository. And I've decided to break out the individual tasks. There are literally a million ways to code a simple ant scripts, this is just one simple example. Please modify to suit your own needs! (At this point I advise you to test your wrapper script. Make sure all tasks get execute as you expect. Especially pay attention to the masterbuild and cleanbuild tasks.
Create a config.xml your project
Here's where the great power of CC is! Here is a complete sample config.xml; I'll go through each section separately.
<cruisecontrol>
<project name="myproject">
<bootstrappers>
<currentbuildstatusbootstrapper file="currentbuild.txt"/>
</bootstrappers>
<modificationset quietperiod="300" dateformat="yyyy-MMM-dd HH:mm:ss">
<cvs cvsroot=":pserver:user@host:/home/cvs/cvsroot"/>
</modificationset>
<schedule interval="60" intervaltype="relative">
<ant buildfile="myproject-cc.xml" target="cleanbuild" multiple="3"/>
<ant buildfile="myproject-cc.xml" target="masterbuild" multiple="1"/>
<pause starttime="1900" endtime="2359"/>
<pause starttime="0000" endtime="0659"/>
<pause day="saturday" starttime="0000" endtime="2359"/>
<pause day="sunday" starttime="0000" endtime="2359"/>
</schedule>
<log dir="logs" encoding="ISO-8859-1">
<merge dir="myproject/subproj/test-results"/>
</log>
<publishers>
<currentbuildstatuspublisher file="currentbuild.txt"/>
<email mailhost="localhost"
returnaddress="me@mydomain.com"
defaultsuffix=""
buildresultsurl="http:
css="dist/css/cruisecontrol.css"
logdir="logs" xsldir="dist/xsl">
<always address="me@mydomain.com"/>
<failure address="me@mydomain.com"/>
<map alias="joe" address="joe@mydomain.com"/>
<map alias="rick" address="rick@mydomain.com"/>
<map alias="bill" address="bill@mydomain.com"/>
<map alias="greg" address="me@mydomain.com"/>
</email>
</publishers>
<plugin name="cvs"
classname="net.sourceforge.cruisecontrol.sourcecontrols.CVS" />
<plugin name="currentbuildstatusbootstrapper"
classname="net.sourceforge.cruisecontrol.bootstrappers.CurrentBuildStatusBootstrapper"/>
<plugin name="ant"
classname="net.sourceforge.cruisecontrol.builders.AntBuilder"/>
<plugin name="pause"
classname="net.sourceforge.cruisecontrol.PauseBuilder"/>
<plugin name="email"
classname="net.sourceforge.cruisecontrol.publishers.HTMLEmailPublisher"/>
<plugin name="currentbuildstatuspublisher"
classname="net.sourceforge.cruisecontrol.publishers.CurrentBuildStatusPublisher"/>
<plugin name="labelincrementer"
classname="net.sourceforge.cruisecontrol.labelincrementers.DefaultLabelIncrementer"/>
</project>
</cruisecontrol>
bootstrapper
<bootstrappers>
<currentbuildstatusbootstrapper file="currentbuild.txt"/>
</bootstrappers>
This section describes the bootstrappers that will run before your build. I do not use any. The currentbuildstatusbootstrapper is needed so that CC can keep track of when the current build started. Use a descriptive name for the file, which will contain a timestamp.
modificationset
<modificationset quietperiod="300" dateformat="yyyy-MMM-dd HH:mm:ss">
<cvs cvsroot=":pserver:user@host:/home/cvs/cvsroot"/>
</modificationset>
This is important. Set your path to version control here, using one of the supported code control elements. Here is also where you define your "quiet period".
The quiet period is the amount of time CC should ensure passes without any files being committed before starting a build. This makes sure that a build is not kicked off while a developer is in the middle of committing a bunch of files. CC ships sample files with this value set to 30 seconds. My setting (5 minutes) may be too long for some of you, but I really think 30 seconds to too short for many developers. Not everyone gets all their stuff together and commits all files at once. Often a junior developer will forget that one last file for a few minutes, and then the build attempt fails. I'd rather wait to be sure.
schedule
<schedule interval="60" intervaltype="relative">
<ant buildfile="myproject-cc.xml" target="cleanbuild" multiple="3"/>
<ant buildfile="myproject-cc.xml" target="masterbuild" multiple="1">
<pause starttime="1900" endtime="2359"/>
<pause starttime="0000" endtime="0659"/>
<pause day="saturday" starttime="0000" endtime="2359"/>
<pause day="sunday" starttime="0000" endtime="2359"/>
</schedule>
The schedule section defines the build process. Here is the heart of continuous integration! The interval attribute describes how long CC should sleep in between checking the repository for modifications. This can be relative sleep time in between checks, or actual time passed since the last time a modification check was begun. I prefer "relative", this just defines the amount of time to sleep in between. In my example, CC will sleep for one minute in between each check.
The child elements of the schedule describe what should be done when a build is needed. The "ant" elements describe a single build. The multiple attribute tells CC to do this task every "multiple" builds - in this case, do a masterbuild every time, but every 3rd time do a clean build instead.
The pause elements are also very important - they tell CC when to relax and take some time off. I have my CC configured to not do any repository checks from 7pm to 7am, as well as over the weekend.
log
<log dir="logs" encoding="ISO-8859-1">
<merge dir="myproject/subproj/test-results"/>
</log>
The log section is very simple and very helpful. CC logs are xml. First of all, due to a bug in the first release of CC2.0, you may need to explicitly set the log encoding. If you get xml parsing or translation errors anytime, here is the place to fix it. Since CC creates one master xml log file for each build (or build attempt), it is very easy for it to pull in the ant results log xml. You can use this feature to your advantage, to also include any xml output from your build process. Here I am "merging" all the xml files in the test-results dir into the CC log.
publishers (email notifications)
<publishers>
<currentbuildstatuspublisher file="currentbuild.txt" />
<email mailhost="localhost"
returnaddress="me@mydomain.com"
defaultsuffix=""
buildresultsurl="http://webhost:8080/cruisecontrol/buildresults"
css="dist/css/cruisecontrol.css"
logdir="logs" xsldir="dist/xsl" >
<always address="me@mydomain.com" />
<failure address="me@mydomain.com" />
<map alias="joe" address="joe@mydomain.com"/>
<map alias="rick" address="rick@mydomain.com"/>
<map alias="bill" address="bill@mydomain.com"/>
<map alias="greg" address="me@mydomain.com"/>
</email>
</publishers>
After a build completes (success or failure), results can be "published". This section allows you to define where the results go. Email is the most popular "publisher", so let's configure for that.
email setup
The default CC setup has an email sent to you with a link to the reporting app. You would click the link in your email, and then see the results in your browser. I like the reporting app, don't get me wrong, but I'm impatient and I want the results of the build embedded into the email! So I skip the setup of the ?LinkEmailPublisher and go straight to the HTMLEmailPublisher. The email publishers are well documented in the CC docs. We'll hit some highlights: reportsuccess should be set if you do not want email reports when the build succeeds (not recommended - I like having the team know the current status. I recommend 'always'). 'never' will only sent results when the build breaks...("I didn't get an email, is the build fine, or is the mailserver down?" - again, not recommended) To use the HTMLEmailPublisher, we will need to copy some of the files from the jsp-report-app into our INSTALL_DIR. Fortunately, it's easy. Here is our dir structure, with 2 new directories created under dist:
INSTALL_DIR
|_bin
cruisecontrol.sh
cruisecontrol.bat
|_dist
|_css
|_xsl
cruisecontrol.jar
|_docs
...many docs here...
|_lib
...many jars here...
Open the cruisecontrol2.0.zip file you downloaded, and open the cruisecontrol-2-jsp-bin.zip file. You will need to open the cruisecontrol.war file to retrieve the css and xsl files. Copy css/cruisecontrol.css into INSTALL_DIR/dist/css and copy xsl/*xsl into INSTALL_DIR/dist/xsl. Trust me, it's worth the work.
always/failure
<always address="me@mydomain.com" />
<failure address="me@mydomain.com" />
Often times there is one person playing the role of "integrator". I get the feeling you know who I'm talking about. This person may want to be informed of all build events, whether the succeed or fail. Or maybe your team wants all build notifications to go to everybody (via a distribution list). Here is where you'd do that.
email mappings
<map alias="joe" address="joe@mydomain.com"/>
CC is automatically set up to send build notifications to the users who committed files that went into the build (depending on your setting for "reportsuccess"). The mails will go to the code control user on the local box who committed code. This is often useless! (depending on your development environment) You need a way to MAP those userid's to real email addresses. For this, use a map. Also useful for those users who NEVER want to see an email from CC...you can map their email address to a bogus one (or your own). (We have a QA person here who commits test plans and such to CVS - if he were to get a build email he wouldn't know what to do with it! So his userid is mapped to my address.)
plugins
<plugin name="cvs"
classname="net.sourceforge.cruisecontrol.sourcecontrols.CVS" />
<plugin name="email"
classname="net.sourceforge.cruisecontrol.publishers.HTMLEmailPublisher" />
The plugins tell CC what implementation to use for various interfaces in the code. The CC docs are great on this subject, so the only advice I have for you is to make sure you replace the ?LinkEmailPublisher with the HTMLEmailPublisher.
Run CruiseControl for the first time Now that you are done configuring, it is time to kick off your first build loop. You need to figure out two things: a name for your project, and a label (version) format.
The name of your project will be myproject.
The label format (for the ?DefaultLabelFormatter) should be <any string>.<a number>. So you can choose MYBUILD.1, or 1.0, v307b.1 or whatever. The first build will be called this. Each subsequent build will have the number to the right of the decimal incremented.
The "last build" we will set to be distinctly in the past. This is just to get things rolling.
/bin/cruisecontrol.sh -projectname myproject -lastbuild 20020101000000 -label 1.0
Off you go! Watch the log...CC first goes out and checks the repository. Assuming you don't commit anything, it will say "nothing to do", and then go to sleep. Now commit a change to a file. Just something trivial. CC will find it, and kick off a build. When it's complete, you should get an email with details.
Run CruiseControl for the second time (and any other time) /bin/cruisecontrol.sh -projectname myproject
When CC is first run, it serializes the project data to a file in the current dir. That's why you do not have to pass all the parameters again. The lastbuild will be discovered from the currentbuild.txt file. The version label is kept in the project's serialized data file.
Solving problems
- Check the CC log. Look here first for all problems.
- Increase the verbosity of the CC log - place a copy of log4j.properties on the classpath (create log4j.properties in INSTALL_DIR and add INSTALL_DIR to the front of the classpath in bin/cruisecontrol.sh) and change INFO to DEBUG
- Re-read the CC docs. They will get better as more releases go out and the user base increases.
- Search the devel and user mailing lists at SourceForge.
Helpful Hints
jonjulian at earthlink.net, 2002/10/11
Has the -lastbuild command line option gone away with v2.5? Can't seem to get it to work, and I don't see anything in the code that would make use of it. Are there any alternatives?
Thanks!