In the previous chapter, I created a basic CruiseControl schedule that would monitor the repository for changes and, if required, execute the build every 20 minutes. This might be fine for some projects, but others might want more control over this schedule. For example, they might want to carry out builds at predefined times, pause the build, or execute different targets every so often. One of the most important aspects of implementing any build process is identifying your "project rhythm"how often you build, what types of builds you create, and what you should do with their outputs. This obviously depends on the environment in which you are working. I discuss this concept and how you can start to identify it for your own environment in Chapter 12, "Putting It All Together." However, CruiseControl has capabilities within its schedule to implement any "project rhythm" you choose, such as the nightly build. This section therefore discusses how to implement the following scheduling scenarios:
There are other ways of implementing CruiseControl build schedules, but the preceding are the most common. Continuous Integration BuildThe default CruiseControl mode of working is to execute a build on a schedule only if modifications have been made. This schedule was described in the preceding chapter and is often called a continuous integration build. A continuous integration build can be scheduled using the following: <schedule interval="1200"> <ant antscript="${dir.javatools}\ant\bin\ant.bat" antWorkingDir="${dir.project}" buildfile="${dir.project}/build.xml" target="integration"/> </schedule> This example executes an Ant build every 20 minutes (1200 seconds), but only if something has been committed to the repository. Nightly BuildIf you want to execute a build at a specific timefor example, as part of a nightly buildyou can specify a time attribute on the Ant builder element: <schedule> <ant antscript="${dir.javatools}\ant\bin\ant.bat" antWorkingDir="${dir.ratlbankmodel}" buildfile="${dir.ratlbankmodel}/build.xml" time="2300" target="integration-baseline"/> </schedule> In this example, the Ant build will be executed at 11 p.m. (2300). You will notice that the target being called is integration-baseline, the target that was defined earlier for building the project and also applying a baseline. You could also use this to carry out any long-running activities using this time-based builderfor example, running a comprehensive set of integration tests.
Forced Nightly BuildThe only caveat to the preceding nightly build schedule is that the build occurs only if modifications have occurred. This probably is what you want. After all, what is the point of building something if nothing has changed? However, if you want to build regardless of changes, you can specify that no modifications are required for the modification set by using the requiremodification attribute as follows: <modificationset requiremodification="false"> <clearcase branch="RatlBankModel_Int" viewpath="${dir.ratlbankmodel}"/> </modificationset> In this example, a ClearCase branch is checked for changes, but there is no requirement for any changes to be found before the build starts. Fallback BuildIf you want to execute a continuous integration build during the day but fall back to executing a nightly build (if no build has been executed during the day), you can use the <timebuild> plugin. This plug-in triggers a build after a particular time threshold. It returns a single modification (from a fake user) only if no successful build has happened since the last specified time threshold: <modificationset> <clearcase branch="RatlBankModel_Int" viewpath="${dir.ratlbankmodel}"/> <timebuild username="bldadmin" time="2300"/> </modificationset> <schedule interval="3600"> <ant antscript="${dir.javatools}\ant\bin\ant.bat" antWorkingDir="${dir.ratlbankmodel}" buildfile="${dir.ratlbankmodel}/build.xml" target="integration"/> </schedule> In this example the <timebuild> plug-in is mixed in the same project as a schedule-based builder to meet the following requirements:
This is a way of building at least once a day. Although it is not strictly necessary to build if nothing has changed, from experience I know that this is something people still like to do. Index BuildIf you want to execute different build targets in the scope of a single projectfor example, to execute a completely clean build or apply a ClearCase baselineyou can specify a build index as follows: <schedule> <ant antscript="${dir.javatools}\ant\bin\ant.bat" antWorkingDir="${dir.ratlbankmodel}" buildfile="${dir.ratlbankmodel}/build.xml" multiple="5" target="clean-integration"/> <ant antscript="${dir.javatools}\ant\bin\ant.bat" antWorkingDir="${dir.ratlbankmodel}" buildfile="${dir.ratlbankmodel}/build.xml" target="integration"/> </schedule> In this example, the target clean-integration is executed every five builds. This target executes a clean before executing the build. For the remaining builds the target integration is carried out, which does not execute a clean. You could use this feature in a number of ways. For example, you could put down a UCM baseline and recommend it every few builds. Note You cannot specify both the multiple attribute and the time attribute for a single builder. Mixed BuildIf you are working on a large project and your build takes several hours, you probably don't want to execute a full build every time a developer commits a change to your repository. One solution is to execute incremental continuous integration builds during the day and then a full build at night. The continuous integration build typically would not execute an Ant clean target before the build and therefore would rebuild only files that have changed. The nightly build, however, would execute the clean target, as well as a full build and test phase. Since each type of build requires the invocation of different Ant targets, the only way to achieve this and to be able to report on the <modificationset> for both builds is to create two CruiseControl projects as follows: <project name="project-CI-build"> <modificationset> <clearcase branch="RatlBankModel_Int" viewpath="${dir.ratlbankmodel}"/> </modificationset> <schedule interval="1200"> <ant antWorkingDir="${dir.project2}" buildfile="${dir.project}/build.xml" target="integration"/> </schedule> </project> <project name="project-nightly-build"> <modificationset requiremodification="false"> <clearcase branch="RatlBankModel_Int" viewpath="${dir.ratlbankmodel}"/> </modificationset> <schedule> <ant antscript="${dir.javatools}\ant\bin\ant.bat" antWorkingDir="${dir.project}" buildfile="${dir.project}/build.xml" time="2300" target="clean-integration-baseline"/> </schedule> </project> This example has two projects that monitor the same ClearCase branch. The CI project builds every 20 minutes if changes have been committed to the repository and executes the Ant target integration. The nightly build project, on the other hand, executes at 11 p.m. whether or not anything has been committed to the repository and executes the Ant target clean-integration-baseline.
Dependent BuildIn some cases you might want to make the invocation of one CruiseControl project dependent on the successful completion of another. An example of this is if you want to carry out some basic, automated functional testing of a deployed Web application to see whether it "stands up."
To execute these tests, the application first needs to be deployed to the web or application server (a mechanism to achieve this is discussed in the next section). Only if the application has been deployed successfully should the tests be executed. To achieve this you can use the CruiseControl <buildstatus> plug-in as part of the <modificationset> element: <project name="RatlBankWeb"> ... </project> <project name="RatlBankModelWeb_LinkTest"> ... <modificationset requiremodification="true"> <buildstatus logdir="logs/RatlBankWeb"/> </modificationset> <schedule interval=<600<> <ant antWorkingDir=<${dir.ratlbankweb}< buildfile=<${dir.ratlbankweb}/build.xml< target=<junit-all</> </schedule> <log> <merge file=<${dir.ratlbankweb}/build/TESTS- TestSuites.xml</> </log> ... </project> The <buildstatus> plug-in basically monitors the log directory for the CruiseControl project that you want the project to be dependent onin this case, the RatlBankWeb project (which is the HTML front end for RationalBank). Only if the RatlBankWeb project is built successfully is this project triggered. You will notice that this example invokes the Ant junit-all target and merges the generated test results. This is because the test cases have been written using HTTPUnit, which executes functional tests on a deployed application. Obviously these tests cannot be run until the application has been successfully deployed. For more information on using HTTPUnit, see Hightower, Onstine, Visan, Payne, and Gradecki [Hightower04]. |