Chapter 6 described how to configure CruiseControl to monitor ClearCase branches for changes with the <modificationset> element and how to update specific files before building via the <clearcasebootstrapper> plug-in. In practice, this is probably the only additional setup that will be required to get CruiseControl working with ClearCase. However, there are other areas where you can start using CruiseControl to automate more of the activities you normally would carry out with ClearCase manually. One of these is the practice of labeling or baselining. This section describes how to use the build label that CruiseControl automatically generates to ClearCase label or baseline your builds. It also describes how to change the implementation of this build label so that it is more aligned with the recommendations in Chapter 3, "Configuring Your SCM Environment." I will show you how to do this through the implementation of a new ClearCase <labelincrementer> plug-in. Automating Labeling or BaseliningIn Figure 7.4 you might have noticed a field called label. CruiseControl creates and increments this label at each build. You can specify the label's format with the <labelincrementer> plugin, which you usually place under each project element as follows: <project name="RatlBankModel" buildafterfailed="false"> <labelincrementer defaultLabel="RATLBANKMODEL.1" separator="-"/> ... </project> In this example, the initial label that is created is RATLBANKMODEL-1; subsequent labels are RATLBANKMODEL-2 and so on. By default, this label is incremented only if the build succeeds. To use this label during the build process, CruiseControl makes it available to the Ant builder as a property called label. Therefore, when you execute your Ant build target, you can simply refer to this property in your Ant build.xml file. With Base ClearCase, you can use this property to create a label type and apply the label across the build directory structure, as shown in Listing 7.1. Listing 7.1. Base ClearCase CruiseControl Baselining
This example uses the macro cc-apply-label that was created in Chapter 5, "Apache Ant Best Practices." With UCM you could use the property to create a baseline and apply it across the build directory structure, as shown in Listing 7.2 Listing 7.2. UCM CruiseControl Baselining
This example uses the macro cc-apply-bl that was created in Chapter 5. In both of these examples, the label or baseline is applied after the build compiles successfully and the JUnit tests have passed. Given this fact, the Base ClearCase example in Listing 7.1 applies an attribute to the label to indicate a promotion level of BUILT (the creation of this attribute was explained in Chapter 3). Similarly, the UCM example in Listing 7.2 also promotes the baseline to BUILT. This is a good example of the level of automation that can be achieved using ClearCase, Ant, and CruiseControl. Granular Source Code CheckingIn Chapter 6, the CruiseControl example implemented a <modificationset> that checked for changes on the project integration branch and in the build top-level directory: <property name="dir.ratlbankmodel" value="C:\Views\RatlBankModel_bld\RatlBankSources\model"/> ... <modificationset quietperiod="90"> <clearcase branch="RatlBankModel_Int" viewpath="${dir.ratlbankmodel}"/> </modificationset> To calculate this modification set, CruiseControl constructs and executes a cleartool lshistory command, similar to the following:
This command determines if any changes have occurred by examining every file recursively down the viewpath, which in some projects could take some time. Also, probably quite a number of files in this directory structure might not have a direct impact on the build, such as text files, documentation, and so on. There are a number of ways to optimize this. First, you could point the viewpath at a lower directory level, such as the src directory: <modificationset quietperiod="90"> <clearcase branch="RatlBankModel_Int" viewpath="${dir.ratlbankmodel}/src"/> </modificationset> Additionally, you could specify multiple <clearcase> elements in the <modificationset>. For example, to check both the src and lib directories for changes, you could use the following: <modificationset quietperiod="90"> <clearcase branch="RatlBankModel_Int" viewpath="${dir.ratlbankmodel}/src" /> <clearcase branch="RatlBankModel_Int" viewpath="${dir.ratlbankmodel}/lib" /> </modificationset> If you want to ignore certain files when the <modificationset> is calculated, as in the case of text or log files, you can include an additional ignoreFiles attribute to the <modificationset> element: <modificationset quietperiod="90" ignoreFiles="*.txt,*.log"> <clearcase branch="RatlBankModel_Int" viewpath="${dir.ratlbankmodel}/src" /> <clearcase branch="RatlBankModel_Int" viewpath="${dir.ratlbankmodel}/lib" /> </modificationset> You might be wondering if this is a good idea, because any changes in the top-level directories will not be found. However, this directory normally contains just the controlling build files, such as build.xml, default.properties, and so on. In this case, although they aren't returned as part of the modification set, they are at least updated as part of the bootstrapping activity for a snapshot view. For a dynamic view, they obviously are up to date already. ClearCase Build Label Plug-inChapter 3 defined a convention for applying ClearCase labels or baselines. By default, Cruise Control-generated labels do not conform to this convention. However, there is no reason why this can't be rectified by implementing a new <labelincrementer> plug-in. The requirements for such a plug-in might be as follows:
To implement this plug-in, two Java classes need to be implemented. The first (which I will call ClearCaseLabelIncrementer.java) will contain the code to generate the label. The second (ClearCaseLabelIncrementerTest.java) will contain the JUnit code required to test the first class. Any <labelincrementer> plug-in class must implement the LabelIncrementer interface, which contains four methods:
Additionally, a single set method called setDefaultLabel is required so that a parameter can be passed to the ClearCase <labelincrementer> indicating what the initial label should be set to, such as RATLBANKMODEL-1-INT. Let's adopt a test-driven development approach and implement the JUnit test class first. This will help us identify all the success and failure conditions for the class. The JUnit test class is illustrated in Listing 7.3. Listing 7.3. ClearCaseLabelIncrementerTest.java Source Code
You might want to add tests and failure conditions to this class yourself, but for our purposes this is good enough. This file should be created in the CruiseControl test directory structure. For example, navigate to the JavaTools src/cruisecontrol-2.x.x directory that was created in Chapter 6, and place the file in main/test/net/sourceforge/cruisecontrol/labelincrementers Now that we have the test case, we can implement the class itself. With the knowledge of how it should pass and fail (from the JUnit test case), we make a better job of it too. Listing 7.4 shows the source code required to implement the ClearCase <labelincrementer>. Listing 7.4. ClearCaseLabelIncrementer.java Source Code
This file should be created in the CruiseControl src directory structure. For example, navigate to the JavaTools src/cruisecontrol-2.x.x directory that was created in Chapter 6 and place the file in main/src/net/sourceforge/cruisecontrol/labelincrementers Now that the source code is in place, the CruiseControl application can be recompiled. This was covered in detail in Chapter 6. Basically you go to the command line, navigate to the CruiseControl main directory, and execute the build.bat or build.sh command. (The unit test created earlier also is automatically executed.) Then when the build has finished, copy the new cruisecontrol.jar file in the dist directory into the JavaTools cruisecontrol/dist directory.
To use this plug-in, you need to register it first with CruiseControl. To do this, edit your existing CruiseControl config.xml file: directly under the <cruisecontrol> element, add the following:
Typically you will configure the <clearcaselabelincrementer> plug-in for every project, specifying the default label string to use as follows: <project name="RatlBankModel" buildafterfailed="false"> <clearcaselabelincrementer defaultLabel="RATLBANKMODEL_1_INT"/> ... This creates labels in the format that was specified at the beginning of this sectionRATLBANKMODEL_1_INT, RATLBANKMODEL_2_INT, and so on. Adding CruiseControl Shortcuts to the ClearCase ExplorerOn Windows, ClearCase Explorer can act as your entry into the world of ClearCase, presenting everything you might need to know about ClearCase from a single interface. It is also possible to customize this interface by adding new shortcuts. Since you can actually link into Web pages from inside ClearCase Explorer, this is a great way to see the CruiseControl build status directly alongside your source code. Figure 7.8 shows an example of the CruiseControl Build Results web running in ClearCase Explorer. Figure 7.8. CruiseControl build results inside ClearCase ExplorerTo create these shortcuts, you first create a new shortcut page by right-clicking any existing shortcut page, selecting Add Page, and naming the page "CruiseControl" or something similar. You can right-click this new shortcut page and select Add Tool Shortcut or Add URL Shortcut, depending on whether you are adding a shortcut to a physical program or a Web page. For example, you can link to the CruiseControl Status Page by entering the URL http://build-server:8080/cruisecontrol. If you want to make these shortcuts available for other users, you can export them to a file and configure each user's ClearCase Explorer so that it automatically loads the shortcuts at startup. |