CruiseControl Scheduling Scenarios
Overview
Although you can create a CruiseControl schedule quite simply, it is clear that different users have different requirements. There are a number of capabilities in CruiseControl that can meet these requirements but they are often not understood or well documented. This page is therefore an attempt to describe a number of common scheduling scenarios and how they can be implemented in CruiseControl.
Note: Please comment or modify this page if you have a better or alternate way of realising these scenarios!
The Continuous Integration (CI) build
The default CruiseControl mode of working is to execute a build on a schedule - only if modifications have been made:
<modificationset>
<cvs localworkingcopy="C:\Sources\project">
</modificationset>
<schedule interval="1200">
<ant
antscript="${dir.javatools}\ant\bin\ant.bat"
antWorkingDir="${dir.project}"
buildfile="${dir.project}\build.xml"
target="integration"/>
</schedule>
This example will execute an Ant build every 20 minutes (1,200 seconds) but only if something has been committed to the repository.
The nightly build
To execute a nightly build you can use the time attribute to the Ant builder:
<modificationset>
<cvs localworkingcopy="C:\Sources\project">
</modificationset>
<schedule>
<ant
antscript="${dir.javatools}\ant\bin\ant.bat"
antWorkingDir="${dir.project}"
buildfile="${dir.project}\build.xml"
time="2300"
target="integration"/>
</schedule>
This example will execute a single nightly build at 11PM (2300), but again only if something has been committed during the day.
The forced nightly build
To execute a nightly build even if no modifications have been made you can specify that the project element does not require any modifications using the requiremodification attribute:
<project name="project-nightly-build" requiremodification="false">
...
<modificationset>
<cvs localworkingcopy="C:\Sources\project">
</modificationset>
<schedule>
<ant
antscript="${dir.javatools}\ant\bin\ant.bat"
antWorkingDir="${dir.project}"
buildfile="${dir.project}\build.xml"
time="2300"
target="integration"/>
</schedule>
...
</project>
This example will execute a nightly build at 11PM as before, but this time it will build even if nothing new has been committed to the repository.
The fallback build - CI during the day, falling back to a forced nightly build
To execute a CI build as normal during the day but then force a nightly build (if no build has been executed during the day) you can use the timebuild plug-in as follows:
<modificationset>
<cvs localworkingcopy="C:\Sources\project">
<timebuild username="bldadmin" time="2300"/>
</modificationset>
<schedule interval="1200">
<ant
antscript="${dir.javatools}\ant\bin\ant.bat"
antWorkingDir="${dir.project}"
buildfile="${dir.project}\build.xml"
target="integration"/>
</schedule>
This example will potentially execute a build every 20 minutes (1,200 seconds) if something has been committed to the repository, however if nothing has been committed during the day, the timebuild plugin will create a "fake" modification to force a nightly build at 11PM.
The mixed build - CI during the day and nightly build but calling different build targets
If you work on a large project that takes several hours to compile from scratch, and receives dozens of submissions from lots of developers every day, you probably don't want to wait all those hours to get feedback from your CI builds. One solution is to do CI builds incrementally, letting the compiler work through dependencies to compile only what's needed when a submission is made to the source code. But it's still probably a good practice to do a full build from scratch at least nightly, because incremental builds may not always find every possible problem. You can use the incremental build to give very quick but imperfect feedback on the status, catching the most common problems developers will submit, while the nightly build full gives more rigorous, but slower, feedback, catching those few problems that fell through the cracks of the incremental build.
To execute a quick CI build as normal during the day and then a complete build at night you can create different CruiseControl projects that check the same repository location but call different build targets:
<project name="project-CI-build">
<modificationset>
<cvs localworkingcopy="C:\Sources\project">
</modificationset>
<schedule interval="1200">
<ant antWorkingDir="${dir.project2}"
buildfile="${dir.project}\build.xml"
target="partial-build"/>
</schedule>
</project>
<project name="project-nightly-build" requiremodification="false">
<modificationset>
<cvs localworkingcopy="C:\Sources\project">
</modificationset>
<schedule interval="1200">
<ant
antscript="${dir.javatools}\ant\bin\ant.bat"
antWorkingDir="${dir.project}"
buildfile="${dir.project}\build.xml"
time="2300"
target="complete-build"/>
</schedule>
</project>
This example has two projects which monitor the same location C:\Sources\project. The CI project will build every 20 minutes if changes have been committed to the repository and execute the Ant target partial-build. The nightly build project on the other hand will execute at 11PM whether anything has been committed to the repository or not and execute the Ant target complete-build. Typically the partial-build target would not execute an ant clean before building, however the complete-build target would.
The dependent build
To execute a build only if a build in another project succeeds, you can use the buildstatus plug-in as follows:
<project name="project1">
<schedule interval="1200">
<ant
antscript="${dir.javatools}\ant\bin\ant.bat"
antWorkingDir="${dir.project}"
buildfile="${dir.project}\build.xml"
target="deploy-application-to-webserver"/>
</schedule>
</project>
<project name="project2">
<modificationset>
<buildstatus logdir="logs\project1"/>
</modificationset>
<schedule interval="1200">
<ant
antscript="${dir.javatools}\ant\bin\ant.bat"
antWorkingDir="${dir.project}"
buildfile="${dir.project}\build.xml"
target="run-functional-tests"/>
</schedule>
</project>
This example will only build project2 if project1 has been successfully built.
The Pause build
To obtain fine grained control over your build schedule you can use the pause plugin. This allows you to stop builds happening at certain times, for example if you want to backup your source control repository, you can use the pause plug-in as follows:
<schedule>
<ant
antscript="${dir.javatools}\ant\bin\ant.bat"
antWorkingDir="${dir.project}"
buildfile="${dir.project}\build.xml"
target="integration"/>
<pause starttime="0200" endtime="0600"/>
</schedule>
This example will pause (prevent any builds happening) between 2am and 6am in the morning. You can have multiple pause elements so you can also use this as a way to manipulate any schedule.
The forced periodic build
To execute a periodic build even if no modifications have been made:
<project name="periodic-build" requiremodification="false">
<modificationset>
<cvs localworkingcopy="C:\Sources\project">
</modificationset>
<schedule interval="1200">
<ant
antscript="${dir.javatools}\ant\bin\ant.bat"
antWorkingDir="${dir.project}"
buildfile="${dir.project}\build.xml"
target="integration"/>
</schedule>
</project>
This example will execute a build every 20 minutes (1,200 seconds), even if nothing new has been committed to the repository. This build will still check the repository for modifications in order to add them to the cruise email. If you don't want the overhead of checking the repository (since we are running regardless of changes) you can also do this:
<project name="every-20-minutes" requiremodification="false">
<modificationset>
<alwaysbuild/>
</modificationset>
<schedule interval="1200">
<ant
antscript="${dir.javatools}\ant\bin\ant.bat"
antWorkingDir="${dir.project}"
buildfile="${dir.project}\build.xml"
target="integration"/>
</schedule>
</project>
This build will always run every 20 minutes (1,200 seconds).
Different Builds on different Days
An attempt to answer Glenn's question: Build A runs Monday, Wednesday, Friday. Build B runs Tuesday Thurdsay. Just add several ant tasks within your schedule task.
<project name="Build A monday, wednesday, friday" requiremodification="false">
...
<modificationset>
<cvs localworkingcopy="C:\Sources\projectA">
</modificationset>
<schedule>
<ant
antscript="${dir.javatools}\ant\bin\ant.bat"
antWorkingDir="${dir.projectA}"
buildfile="${dir.projectA}\build.xml"
time="2300"
day="monday"
target="build"/>
<ant
antscript="${dir.javatools}\ant\bin\ant.bat"
antWorkingDir="${dir.projectA}"
buildfile="${dir.projectA}\build.xml"
time="2300"
day="wednesday"
target="build"/>
<ant
antscript="${dir.javatools}\ant\bin\ant.bat"
antWorkingDir="${dir.projectA}"
buildfile="${dir.projectA}\build.xml"
time="2300"
day="friday"
target="build"/>
</schedule>
...
</project>
<project name="Build B tuesday, thursday" requiremodification="false">
...
<modificationset>
<cvs localworkingcopy="C:\Sources\projectB">
</modificationset>
<schedule>
<ant
antscript="${dir.javatools}\ant\bin\ant.bat"
antWorkingDir="${dir.projectB}"
buildfile="${dir.projectB}\build.xml"
time="2300"
day="tuesday"
target="build"/>
<ant
antscript="${dir.javatools}\ant\bin\ant.bat"
antWorkingDir="${dir.projectB}"
buildfile="${dir.projectB}\build.xml"
time="2300"
day="thursday"
target="build"/>
</schedule>
...
</project>
This example will execute Build A's build script on mondays, wednesdays and fridays at 11 pm. It will execute Build B's build script on tuesdays and thursdays at 11 pm. All builds will run even if nothing new has been committed to the repository (due to requiremodification="false").
Other scenarios?
If you have any other scenarios, please add them here...
Can we have two seperate child elements in the <schedule> tag. For the example below I would like <ant> to run first and then <exec>
<schedule interval="86400">
<ant ...
<exec ...
</schedule>
Yes, you can have two separate child elements in the schedule tag but that probably won't give you what you expect.
<schedule> <ant ... > <exec ... > </schedule>Would only execute the ant builder.
<schedule> <ant ... > <exec multiple="3" ... > </schedule>Would run the exec builder ever third build. (Usually this multiple attribute is used to run a different target, like 'clean', every few builds.)
To get both builders to run on a build you'd need to use the composite builder:
<schedule> <composite> <ant ... > <ant ... > </composite> </schedule>What would you recommend for the following scenario:
projects A and B are independent projects and project C depends on the both - A and B.
Every time A or B are built successfully, I would like to have C to be built as well.
Here my questions are:
1/ If A failed, B succeeded that triggers C to be built and C fails because A is fail. I would like C won't be triggered in this case at all,
until A is fixed.
2/ A and B do not share any code and I would like to run them simultaneously - in different threads. However, C must not be run while A or B is running
I did not find a good way to configure neither 1/ nor 2/. Would you have some recommendation on that?
This is a real case environment - our code base contains projects in C++ and Java and the setup includes the artifacts from the both of them, thus
projects A and B are compiling C++ and java and project C compiles setups. We can't afford ourself to compile everything on every change,
just because of the size of the projects (C++ takes about 20 min to compile, the same for java)
Moisei:
You can accomplish #1 by using a combination of the build status and veto source controls. It is the veto in particular that would have C about a build if A is broken.
You can accomplish #2 by using the lockfilelistener/bootstrapper combination. A and C would share one lock file while B and C would share another.
(Note, this answer is likely to be merged into the main document and have both comments removed.)
What about this scenario:
- I want to run a shortened build (basically just tests) whenever a scm change is made. (mvn verify)
- I want to run a much longer suite (metrics, creating web-sites, etc) every night at midnight (either every night, or only if something has changed in scm since the previous midnight, independent of the "short" build running successfully since then. (mvn install site-deploy | ch.hortis.sonar:sonar-maven-plugin::sonar)
And this is complicated by the fact that I am using the same configuration of <plugin name="project"> for like 20 projects. To do this, do I have to make 2 different plugin names? And if so, do I have to declare all my instances of the projects twice?
How can i achieve a forced build at say 4 AM, but only if i have pushed the force button within the last 24hours.
I have a production site which builds continuously, but I do not always i want my release server to be built every night. Therefore i need a way to click the button when i leave my office, and then know that my release server will be built at 4AM in the morning, ready for the next workday.
Any tips appreaciated!