Section 5.3. Setting Up a Continuous Integration Build


5.3. Setting Up a Continuous Integration Build

An easily reproducible build and testing system allows your development team to focus on coding rather than some complex and error-prone build tool based on a specific local environment. Using a build container such as Maven also reduces the amount of tedious work involved in setting up everyone's local build environment. When you're working in a team, developers will commit code to the SCM only after they have verified that their changes are appropriately tested and that their local build passes. In reality, there are several reasons why a local build would pass on your machine but fail on another developer's: you could have forgotten to update your working copy before committing, you could be using a different database instance, etc. What you'd like to do is find out as quickly as possible if the code that everyone commits is working. A bug introduced by one developer may be an obstacle to another developer's progress, and ideally, you want to build and test a system after each commit so that you can identify problems as they occur. This is known as Continuous Integration.[2]

[2] See Martin Fowler's reference article on Continuous Integration (http://www.martinfowler.com/articles/continuousIntegration.html).

5.3.1. How do I do that?

The best solution found so far is to set up what is called a Continuous Integration build. You're going to do that now using Maven and CruiseControl (http://cruisecontrol.sourceforge.net/). You're going to set up a continuous build for the Quote of the Day (QOTD) web application introduced in Chapter 3.

The architecture is simple (see Figure 5-3) and is composed of three entities


Developer workstations

This is where developers commit code changes to the SCM.


SCM repository

You are going to use the Subversion repository where we have stored the web application source code. The only thing you'll need for this is an Internet connection that allows HTTP on port 80 (this should be a pretty common setup!). Note that CruiseControl supports a host of SCMs (Subversion, CVS, ClearCase, CM Synergy, Starteam, VSS, Surround, etc.).


CruiseControl server

This is a server which continuously polls the SCM to see if there are changes, and if so, it starts a Maven build to build the QOTD project, generate build logs, publish build results (send email, deploy artifacts to a web site, etc.), and make them available for viewing through the CruiseControl web application.

Figure 5-3. The Continuous Integration build architecture using CruiseControl and Maven


Let's go through the following steps:

  1. Install CruiseControl on your machine.

  2. Install the Subversion command-line client.

  3. Create a work directory for the QOTD project's build and check out the qotd project from Subversion.

  4. Modify the qotd project so that you can use the Maven CruiseControl plug-in to generate a valid CruiseControl configuration.

  5. Start CruiseControl.

  6. Make a change to a file in the SCM and observe CruiseControl rebuilding the project.

  7. Configure the CruiseControl web application and view the build results.

For the sake of simplicity you'll run CruiseControl on your local machine for this lab. However, you would normally install CruiseControl on a separate server machine.

To install CruiseControl, download it from http://cruisecontrol.sourceforge.net/ and unzip it to a convenient place on your hard drive. Let's imagine you wish to have it in c:/apps/cruisecontrol-.2.2.1 (we used version 2.2.1 for this lab). Add c:/apps/cruisecontrol-2.2.1/main/bin to your PATH environment variable so that you can later type cruisecontrol on the command line to start the CruiseControl server.

Now let's install the Subversion command-line client, as it will be required by CruiseControl and by Maven for performing SCM actions (such as updating the files, performing a checkout, etc.). Download it from http://subversion.tigris.org/ and use the package corresponding to your operating system. Make sure that you can type svn from any directory. If not, add to your PATH environment variable the bin/ directory where the svn executable has been installed.

Now we need to set up a work directory where we will put the CruiseControl configuration for the QOTD project. This work directory will also be the location where the Maven build will execute and where CruiseControl will generate its logs. Create the following directory structure:

c:/dev/mavenbook/work/cruisecontrol/   checkout/   logs/

Check out the qotd source code by typing the following into the checkout/ directory:

C:\dev\mavenbook\work\cruisecontrol\checkout>svn co ^  More? http://www.mavenbook.org/svn/mdn/code/qotd    A  qotd\.classpath A  qotd\project.properties A  qotd\.project A  qotd\project.xml [...]

You need to perform this step only once. Thereafter, the CruiseControl build loop will be able to perform an SCM update to download the latest changes.

Your next step is to create a CruiseControl config.xml configuration file. This is the file that completely describes the CruiseControl setup. Here's what the file looks like:

<?xml version="1.0" encoding="UTF-8"?>    <cruisecontrol>   <project name="qotd">     <bootstrappers>       <currentbuildstatusbootstrapper            file="c:/dev/mavenbook/work/cruisecontrol/logs/qotd/status.txt"/>     </bootstrappers>     <modificationset>       <svn localWorkingCopy="c:/dev/mavenbook/work/cruisecontrol/checkout/qotd"            repositoryLocation="http://www.mavenbook.org/svn/mdn/code/qotd"/>     </modificationset>     <schedule interval="300">       <maven goal="scm:update|clean qotd:build"            projectfile=               "c:/dev/mavenbook/work/cruisecontrol/checkout/qotd/project.xml"           mavenscript="c:\apps\maven-1.0.2/bin/maven.bat"/>     </schedule>     <log dir=         "c:/dev/mavenbook/work/cruisecontrol/logs/qotd" encoding="ISO-8859-1">       <merge dir=           "c:/dev/mavenbook/work/cruisecontrol/checkout/qotd" pattern="TEST-*.xml"/>     </log>     <publishers>       <currentbuildstatuspublisher            file="c:/dev/mavenbook/work/cruisecontrol/logs/qotd/status.txt"/>       <htmlemail spamwhilebroken="false" reportsuccess="always"              css="C:/apps/cruisecontrol-2.2.1/reporting/jsp/webcontent/css/cruisecontrol.css"           mailhost="localhost" subjectprefix="[BUILD]"            buildresultsurl="http://www.mavenbook.org/[...]"           defaultsuffix="@apache.org" returnaddress="vmassol@apache.org"           xsldir="C:/apps/cruisecontrol-2.2.1/reporting/jsp/webcontent/xsl"            logdir=             "c:/dev/mavenbook/work/cruisecontrol/logs/qotd" skipusers="false">         <map address="vmassol@apache.org" alias="vmassol"/>         <map address="tobrien@apache.org" alias="tobrien"/>         <failure address="vmassol@apache.org"/>         <success address="vmassol@apache.org"/>       </htmlemail>     </publishers>   </project> </cruisecontrol>

Don't bother trying to understand the different elements in this file, as that's not required for this lab. If you want to dive into CruiseControl configuration, check the excellent documentation at http://cruisecontrol.sourceforge.net/main/configxml.html. The point we wish to make here is that the information found in the CruiseControl configuration file (the SCM information, the location of Maven home, email addresses, the name of the project, etc.) can also be found in your project's Project Object Model (POM). It's a shame to have to duplicate this information in two separate places. Fortunately, there is an existing CruiseControl plug-in for Maven that can automatically generate this file for you by using the POM information and some additional information that you pass to it. Let's use this plug-in and start by adding the following properties to our build.properties file (because these properties are environment-dependent):

maven.cruisecontrol.home = c:/apps/cruisecontrol-2.2.1 maven.cruisecontrol.work.dir = c:/dev/mavenbook/work/cruisecontrol

Now add the following two properties to the qotd/project.properties file (this is the master QOTD project's configuration file; see Chapter 3 for a refresher):

maven.cruisecontrol.goals = scm:update|clean qotd:build maven.cruisecontrol.mail.host = [your SMTP mail server here]

Many properties control the CruiseControl plug-in, but these are the four main ones that are required to get a working CruiseControl configuration for the QOTD multiproject:


maven.cruisecontrol.home

This is the location where you have installed CruiseControl on your machine.


maven.cruisecontrol.work.dir

This is your CruiseControl work directory that you created earlier in this lab.


maven.cruisecontrol.goals

This property contains the list of goals that the CruiseControl Maven builder will pass to Maven to build the qotd project. The first goal is scm:update. It uses the Maven SCM plug-in to perform an SCM update and download all changes. This is how we ensure that we always build with the latest changes. The pipe symbol (|) is used by the Maven builder to denote a different Maven session. Thus, in practice the Maven builder will call Maven twice: once to run the scm:update goal and once to run the clean and qotd:build goals. The qotd:build goal is the one that you created in Chapter 3 and that builds the full project.


maven.cruisecontrol.mail.host

This is the name of the SMTP server that CruiseControl will use to send failure or success emails.

You'll also need to make sure that you have defined where your SCM is located in your POM (qotd/project.xml):

  <repository>     <connection>scm:svn:http://www.mavenbook.org/svn/mdn/code/qotd   </connection>   </repository>

Let's try it out and generate the config.xml file. Go into the qotd/ directory and type the following:

C:\dev\mavenbook\code\qotd>maven cruisecontrol [...] scm:find-connection:     [echo] Using connection: scm:svn:http://www.mavenbook.org/svn/mdn/code/qotd    scm:parse-connection:     [echo] Using SCM method: svn     [echo] Using SVN repository: http://www.mavenbook.org/svn/mdn/code/qotd    scm:validate:    cruisecontrol:validate:    cruisecontrol:configure:     [mkdir] Created dir: C:\dev\mavenbook\code\qotd\target\cruisecontrol     [copy] Copying 1 file to C:\dev\mavenbook\code\qotd\target\cruisecontrol     [delete] Deleting: C:\dev\mavenbook\code\qotd\target\cruisecontrol\config-temp.xml BUILD SUCCESSFUL Total time: 2 seconds

This generates a config.xml file in C:\dev\mavenbook\code\qotd\target\cruisecontrol. This file needs to be copied to your CruiseControl work directory (remember that the CruiseControl server will run from there). The CruiseControl plug-in has a cruisecontrol:install-local goal for installing the generated configuration in the working directory. Let's run it:

C:\dev\mavenbook\code\qotd>maven cruisecontrol:install-local [...] cruisecontrol:configure:     [copy] Copying 1 file to C:\dev\mavenbook\code\qotd\target\cruisecontrol     [delete] Deleting: C:\dev\mavenbook\code\qotd\target\cruisecontrol\config-temp.xml    cruisecontrol:install-local:     [copy] Copying 1 file to C:\dev\mavenbook\work\cruisecontrol BUILD SUCCESSFUL Total time: 2 seconds

The config.xml file has been copied to c:\dev\mavenbook\work\cruisecontrol, which now contains:

C:/dev/mavenbook/work/cruisecontrol/   checkout/     qotd/   logs/   config.xml

As you may have noticed the cruisecontrol:install-local goal actually calls the cruisecontrol:configure goal. Thus, whenever you wish to regenerate the CruiseControl configuration file you can do it all in one step by calling cruisecontrol:install-local.

Note that if CruiseControl was installed on another machine you would need to copy the config.xml file by another means (possibly using the Ant FTP task or the Ant SCP task).

Now you're ready to turn on CruiseControl. Go to c:/dev/mavenbook/work/cruisecontrol and type cruisecontrol:

C:\dev\mavenbook\work\cruisecontrol>cruisecontrol [...] [cc]feb.-19 10:37:57 Main          - CruiseControl Version 2.2.1 [cc]feb.-19 10:37:57 trolController- projectName = [qotd] [cc]feb.-19 10:37:57 trolController- No previously serialized project found:                                      C:\dev\mavenbook\work\cruisecontrol\qotd [cc]feb.-19 10:37:57 Project - Project qotd: reading settings from config file                             [C:\dev\mavenbook\work\cruisecontrol\config.xml] [cc]feb.-19 10:37:58 Project       - Project qotd starting [cc]feb.-19 10:37:58 Project       - Project qotd:  idle [cc]feb.-19 10:37:58 BuildQueue    - BuildQueue started [cc]feb.-19 10:37:58 Project       - Project qotd started [cc]feb.-19 10:37:58 Project       - Project qotd: next build in 5 minutes [cc]feb.-19 10:37:58 Project       - Project qotd: waiting for next time to                                       build

The build sleeps for five minutes. This is the default build schedule interval, which you can change by using the maven.cruisecontrol.schedule.interval property. For example, to set it to one minute:

maven.cruisecontrol.schedule.interval = 60

After this interval, CruiseControl starts building the qotd project (it always does it the very first time, even if there have been no changes in the SCM):

[cc]feb.-19 11:29:20 Project       - Project qotd: in build queue [cc]feb.-19 11:29:20 BuildQueue    - now adding to the thread queue: qotd [cc]feb.-19 11:29:20 Project   - Project qotd: reading settings from config file                                [C:\dev\mavenbook\work\cruisecontrol\config.xml] [cc]feb.-19 11:29:20 Project       - Project qotd:bootstrapping [cc]feb.-19 11:29:20 Project       - Project qotd:checking for modifications [cc]feb.-19 11:29:39 Project       - Project qotd:No modifications found,                                       build not necessary. [cc]feb.-19 11:29:39 Project       - Project qotd: Building anyway, since                                       build was explicitly forced. [cc]feb.-19 11:29:39 Project       - Project qotd:  now building build:start:    scm:find-connection:     [echo] Using connection: scm:svn:http://www.mavenbook.org/svn/mdn/code/qotd    scm:update:     [echo] Updating from scm:svn:http://www.mavenbook.org/svn/mdn/code/qotd [INFO] Executing: svn --non-interactive update [INFO] Working directory: c:\dev\mavenbook\work\cruisecontrol\checkout\qotd BUILD SUCCESSFUL Total time: 40 seconds    build:start:    clean:clean:    clean:    qotd:build: [...]

As you can see, the CruiseControl Maven builder has started by calling a Maven session with the scm:update goal, followed by another Maven session with the clean qotd:build goals.

The default CruiseControl configuration you have used sends an HTML email on every build (success or failure):

[cc]feb.-19 11:30:37 Project       - Project qotd:  merging accumulated log                                       files [cc]feb.-19 11:30:38 Project       - Project qotd:  build successful [cc]feb.-19 11:30:38 Project       - Project qotd:  publishing build results [cc]feb.-19 11:30:42 EmailPublisher- Sending mail notifications.

Figure 5-4 shows the type of HTML mail you should have received.

Figure 5-4. HTML email sent by CruiseControl upon build success and/or failure


The CruiseControl server will then periodically poll your SCM for changes, and if none is found it goes back to sleep:

[cc]feb.-19 15:56:23 Project       - Project qotd: idle [cc]feb.-19 15:56:23 Project       - Project qotd: next build in 5 minutes [cc]feb.-19 15:56:23 Project       - Project qotd: waiting for next time to                                       build [cc]feb.-19 16:01:23 Project       - Project qotd:in build queue [cc]feb.-19 16:01:23 BuildQueue    - now adding to the thread queue: qotd [cc]feb.-19 16:01:23 Project    - Project qotd: reading settings from config file                                [C:\dev\mavenbook\work\cruisecontrol\config.xml] [cc]feb.-19 16:01:23 Project       - Project qotd:bootstrapping [cc]feb.-19 16:01:23 Project       - Project qotd:checking for modifications [cc]feb.-19 16:01:41 Project       - Project qotd:No modifications found,                                       build not necessary.

The last step of this lab on Continuous Integration is to configure and start the CruiseControl web application, which allows you to browse build results and see some statistics. Grab the cruisecontrol.war file located in the reporting/jsp/dist directory of your CruiseControl install directory (c:/apps/cruisecontrol-2.2.1/ in our case). Unfortunately, you need to configure this web application by telling it where the CruiseControl log directory is located on your hard disk, and this configuration parameter is located... in the WEB-INF/web.xml file of the cruisecontrol.war file! Fortunately, the CruiseControl Maven plug-in is here to help us once again, and executing the cruisecontrol:configure-war goal will generate a properly configured CruiseControl web application WAR:

C:\dev\mavenbook\code\qotd>maven cruisecontrol:configure-war [...] cruisecontrol:configure-war:     [unwar] Expanding: C:\apps\cruisecontrol-2.2.1\reporting\jsp\dist\cruisecontrol.war  into C:\dev\mavenbook\code\qotd\target\cruisecontrol\cruisecontrolwar     [war] Building war: C:\dev\mavenbook\code\qotd\target\cruisecontrol\cruisecontrol. war BUILD SUCCESSFUL Total time: 3 seconds

Drop the generated c:/dev/mavenbook/code/qotd/target/cruisecontrol/cruisecontrol.war file in your favorite Servlet container (for Tomcat, drop it in [TOMCAT_HOME]/webapps) and start it. See the "Creating Your Own Remote Maven Repository" lab earlier in this chapter for help on how to install/start Tomcat.

Open your browser and point it to http://localhost:8080/cruisecontrol. You'll see the CruiseControl dashboard that lists all the projects being built (see Figure 5-5).

Figure 5-5. CruiseControl dashboard page showing all the projects built by CruiseControl


Click the qotd link to display the build status page for the QOTD project (see Figure 5-6). On the left it shows the list of builds, and in the middle it shows the selected build results. You can see that the shown build was successful, that three unit tests were executed, and that vmassol made one change since the last successful build. This is a very useful feature for finding out why a build breaks.

Figure 5-6. CruiseControl build result page for the qotd project


We invite you to explore the different tabs to learn more details about the data gathered by CruiseControl during the build.

5.3.2. What about...

...defining one CruiseControl project per Maven subproject?

That would sound like a sensible approach. However, that would mean letting CruiseControl handle inter-project dependencies. Unfortunately, this is not a strong point of CruiseControl and is best left to Maven's Multiproject feature. In addition, Maven's CruiseControl plug-in does not handle well the use of one CruiseControl project per Maven subproject. At this point in time, we do not recommend using this strategy.

You could use other Continuous Integration tools, such as Gump (http://gump.apache.org/), DamageControl (http://damagecontrol.codehaus.org/ ), or Continuum (http://maven.apache.org/continuum/). Note that a Gump plug-in is available for Maven that automatically generates a Gump descriptor. However, the tool that has the most support at the time of this writing is certainly CruiseControl, and we highly recommend it.


Tip: At the time of this writing Continuum is still in its infancy. Continuum is a project developed by the Maven team and is targeted primarily at Maven projects. Thus, we expect it to become the preferred Continuous Integration tool for Maven projects in the future.


Maven. A Developer's Notebook
Maven: A Developers Notebook (Developers Notebooks)
ISBN: 0596007507
EAN: 2147483647
Year: 2003
Pages: 125

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net