Copyright 2007 Julian Simpson. All rights reserved.
Original article: discovery ing cruisecontrol the cruisecontrol way
I'm an infrastructure specialist at thoughtworks. in my role I make sure that we are building our software so it can successfully be deployed to production. in this series of blog posts I hope to pass on my top ten tips for using cruisecontrol enterprise quota tively. i'm writing these with the developers or systems administrators in mind: the people who most often manage cruisecontrol. however, I hope that anybody who is interested in continuous integration will get something from these articles.
#3: Configuring ing cruisecontrol the cruisecontrol way: Use cruisecontrol to configure cruisecontrol.
You have just started using cruisecontrol. You use a version control system to manage your code. You have installed cruisecontrol on an idle machine in the office. everything is good. After your code is changed, it can immediately give you feedback. then the hard disk on the idle machine is finished, so your build server has to continue with its previously idle door-bolt role.
"No problem", you think: "All code changes are in the version control system. We can regenerate any components we need. in fact, all we need is the configuration file... ". yes, the configuration file. the configuration file on the hard disk can no longer work. this blog will briefly describe how to manage your cruisecontrol configuration without fear of losing it. like many tools, cruisecontrol will be ineffective, if not configured.
In previous thoughtworks projects, we always need to grant a person the permission to access the building server to modify the cruisecontrol configuration. once the project grows to no longer a few developers, it will become very difficult to familiarize everyone with the installation and configuration of the project. in the end, someone (sometimes me, your humble speaker) becomes a full-time project cruisecontrol administrator. this situation creates a bottleneck for the development team: all the modifications to the cruisecontrol are collected by one person for processing.
The first step to improve this situation is to find a way for cruisecontrol to apply configuration changes on its own. let's get started. in addition to the <project> for building and testing your code, you can also have a special <project> to apply configuration changes to the build server. we keep doing this and place the configuration files in the correct place. When they change, we will use the <bootstrapper> plugin of cruisecontrol to update the Configuration:
<?xml version="1.0"?>
<cruisecontrol>
<project name="config">
<labelincrementer defaultLabel="${project.name}-1" separator="-"/>
<listeners>
<currentbuildstatuslistener file="/var/spool/cruisecontrol/logs/${project.name}/
currentbuildstatus.txt"/>
</listeners>
<bootstrappers>
<svnbootstrapperlocalWorkingCopy="/etc/cruisecontrol"/>
</bootstrappers>
<modificationsetquietperiod="30">
<svnlocalWorkingCopy="/etc/cruisecontrol"/>
</modificationset>
<schedule interval="60">
<ant antWorkingDir="/etc/cruisecontrol" antscript="/var/spool/cruisecontrol/tools/apache-ant-1.6.5
/bin/ant" uselogger="true"/>
</schedule>
<publishers>
<artifactspublisher
file="${project.name}/build.log"
dest="logs/${project.name}"/>
</publishers>
</project>
</cruisecontrol>
This will update the configuration mechanically until the end of the world. it is simple but effective. Now we no longer rely on the guy who can change the cruisecontrol. suddenly, they do not need to make trivial changes on behalf of others in the team, because everyone can safely change the configuration. if someone does check in a problematic configuration file, it doesn't matter. Everything is in the version control system. you can revert this change, find out who made the change, and try to understand why they want to change it.
This is a huge step forward. however, if you check in a faulty configuration, it will still be applied to cruisecontrol. fortunately, cruisecontrol has good judgment and does not apply problematic configurations, but this will cause you to lose important feedback. to solve this problem, you need to write a simple validator, as shown below:
Package org. juliansimpson;
Import java. Io. file;
Import net. SourceForge. cruisecontrol. cruisecontrolexception;
Import net. SourceForge. cruisecontrol. config. xmlconfigmanager;
Import org. Apache. Tools. Ant. buildexception;
Import org. Apache. Tools. Ant. task;
Public class configvalidator extends task {
Public String configfile;
Public void execute () throws buildexception {
Try {
File file = new file (configfile );
New xmlconfigmanager (File );
} Catch (cruisecontrolexception e ){
Throw new buildexception ("invalid cruisecontrol config ");
}
}
Public void setconfigfile (string config ){
Configfile = config;
}
}
This validator uses a class inside the cruisecontrol to verify the configuration. it is best to have a public interface to do this-it can be a command line option or an "official" ant task. I have requested the cruisecontrol enterprise team to consider this issue in future release. this verification method does mean you need to set classpath so that your validator can find the class it references from inside the cruisecontrol. however, you will find that it does ensure that the current configuration is effective for the cruisecontrol version you are using. I tend to run the verification in ant Task Mode. it is very simple, and everyone can easily see what it does. below is a simple ant script:
<project name="cruisevalidator" default="publish" >
<import file="build-library.xml"/>
<target name="validated-config" depends="cruise-validator.jar">
<taskdef name="validate" classname="org.juliansimpson.ConfigValidator" classpathref="main"/>
<echo message="validating ${config}" />
<validate configFile="${config}" />
</target>
<target name="publish" depends="validated-config">
<echo level="info" message="copying CruiseControl config to server" />
<copy file="${config}" todir="${cruisecontrol.dir}" failonerror="true"
description="Copy configuration to CruiseControl server" />
<echo level="info" message="forcing a reload of config on server" />
<get src="http://localhost:8000/invoke?operation=reloadConfigFile&objectname=CruiseControl+Manager%3Aid%3Dunique"
dest="${build.dir}/reload.html" />
</target>
</project>
They work together like the following: The bootsstrapper of the cruisecontrol gets the latest configuration file, but it is placed in a directory different from the installation directory of the cruisecontrol. you still don't know whether it is a valid configuration file. then "validated-config" target will call the ant task configvalidator. this will call enough logic in the cruisecontrol to ensure that the configuration is legal, and some directories involved in the configuration file exist. if this step is passed, the "publish" target copies the configuration to the directory of the cruisecontrolserver to overwrite the original file. finally, "publish" target will send a simple HTTP request to the JMX interface to force the cruisecontrol to re-load the configuration. this will ensure that the new configuration will be loaded immediately, so that the team will know that the new configuration is legal. thanks to Tim Brown for his extraordinary idea.
I have to admit that sometimes I accidentally break the xml configuration file. this method works especially well for me because I have a verified protection network. I have done something similar to my email server and web server, hoping to write them quickly. the validator source code and build script can be downloaded on my website: http://www.juliansimpson.org /.
Julian Simpson 2007. All rights reserved.
I think the core of this practice is:
1. Check the configuration file of cruisecontrol in the version control system to solve unexpected damages.
2. Use a dedicated "project" to automatically update the configuration to solve the bottleneck that requires someone to log on to the build server to update each time.
3. Reuse but not rely on the validation of the configuration file by cruisecontrol, in order to simultaneously obtain the ability to "prevent problematic configuration files from being applied to build server" and "quickly learn that someone has checked in the problematic configuration capabilities"