Continuous Integration, or
CI, is a simple, yet powerful concept. Automatically build, regression test,
and deploy a software application to a test environment whenever a developer
commits a code change to version control. If the build, regression test, or
deployment fails, the problem can be isolated to the code change that triggered
the CI build. Once isolated, the source of the failure can be identified and
corrected to allow the build to complete successfully.
Today, CI is a practical
approach to ensure that a software application always builds while it undergoes
development. However, this was not always the case. Until open source
CruiseControl was developed, CI was not possible without creating the necessary
infrastructure from scratch.
Years after it was first
released, open source CruiseControl remains a popular tool for implementing CI.
Not only does CruiseControl trigger CI builds, but it also notifies the
development team of the build results via email and on an easy-to-read
dashboard. Getting started with CruiseControl requires some effort to
understand the structure and contents of the configuration file. With
additional effort, CruiseControl can be optimized to support CI for parallel
development of a software application and for software development projects across
an enterprise.
Extending CruiseControl to Support Several Projects
Configuring CruiseControl
for Continuous Integration Builds describes the steps to configure one
CruiseControl project. A CruiseControl project corresponds to a software
development effort in which all activity takes place in one codeline in the
version control tool. However, it is rare for development to be restricted to
one codeline for the duration of a software development project. Typically,
parallel development along multiple codelines is the practice used by software
development projects.
To implement CI for a software
development project, CruiseControl needs to monitor each codeline in which
development takes place. This means one CruiseControl project needs to be
created for each active codeline. However, the configuration of each
CruiseControl project is likely to be similar. The differences among the CruiseControl
projects may be limited to the workspace in which the build occurs, the branch
of the version control tool used to populate the workspace, and the test
environment in which the build is deployed.
Rather than specifying the
same configuration information for each CruiseControl project, common
configuration settings can be specified once in the CruiseControl configuration
file, config.xml, but referenced in each project that uses that information. Plugin
preconfiguration is the mechanism provided by CruiseControl for this
purpose.
Configuring Plugins to Support Multiple CruiseControl
Projects
Typically, the following
elements are nested inside the <project> element to define each
CruiseControl project.
- <listeners>
- <bootstrappers>
- <modificationset>
- <schedule>
- <log>
- <publishers>
Recall from Configuring
CruiseControl for Continuous Integration Builds that each XML element
nested inside the <project> element maps to a plugin that is executed
during the build loop. Configuration settings for these elements can be
specified using plugin preconfiguration. Rather than including the
configuration details in the XML element that is nested inside the
<project> element, these details can be specified once at the beginning
of the config.xml file.
Configuring
CruiseControl for Continuous Integration Builds included the following
example for configuring the <bootstrappers> element.
<bootstrappers>
<accurevbootstrapper
workspace="/home/accurev_user/workspaces/${project.name}"
verbose="true"/>
</bootstrappers>
Notice that the nested
<accurevbootstrappers> element specifies values for the workspace and verbose
attributes. While the value of the verbose
attribute is constant, the value of the workspace
attribute is not. However, the value of the workspace attribute is specified using the value of the CruiseControl variable project.name. As written, the configuration of the <accurevbootstrapper>
is independent of the project, i.e., the same definition can be used in every
project.
Using plugin preconfiguration,
the detailed specification of the <accurevbootstrapper> can be removed
from the <project>. The accurevbootstrappers plugin is preconfigured at
the beginning of the config.xml file by specifying the following.
<plugin
name="accurevbootstrapper"
workspace="/home/accurev_user/workspaces/${project.name}"
verbose="true"/>
By preconfiguring the
accurevbootstrappers plugin, each project that uses that plugin only needs to
specify the following.
<bootstrappers>
<accurevbootstrapper/>
</bootstrappers>
Not only does plugin
preconfiguration prevent identical configuration information from being
specified in each project, but it makes it easier to support future changes. If
the configuration information for a plugin ever needs to change, the change can
be made in one place in the config.xml file, rather than in each project
definition in that file.
Using Plugin Preconfiguration to Support CI for
Different Software Applications
Plugin preconfiguration is
not limited to CruiseControl projects that correspond to parallel codelines for
a software development project. Instead, plugin preconfiguration can be used
for CruiseControl projects that implement CI for different software
applications under development. The example of preconfiguring the
accurevbootstrappers plugin is applicable in an enterprise in which different
software development projects use the same version control system.
A configuration management
team interested in standardizing CI for Java development projects across an
enterprise can make use of plugin preconfiguration for all CruiseControl
projects that run in the same CruiseControl instance. As new CruiseControl
projects for new software applications are added to the config.xml file, existing
preconfigured plugins can be referenced in the new projects. Not only does this
reduce maintenance, but it promotes consistency. All CruiseControl projects in
the config.xml file can follow the same pattern.
Using the CompositeBuilder
While CI may begin as an
effort to build after changes are committed to a codeline, CI can be extended
to validate the deployment process. In the same way that a change to a codeline
triggers a CI build, each change to a codeline should trigger a deployment to
an integration environment. The deployment should begin once the CI build
completes.
Typically, deployments of a
software application are scripted so that they can be automated. Scripts that
are used to deploy an application to a test environment can be used to deploy
each CI build to an integration environment.
One approach for validating
the deployment is to configure the
CompositeBuilder to invoke the build and deployment scripts as part of the CruiseControl
build loop. The CompositeBuilder is configured by nesting the
<composite> element inside the <schedule> element. The child
elements of <composite> are the elements that invoke the different builders.
One of the child elements of
<composite> is <exec>, the element for the
ExecBuilder. The ExecBuilder invokes a command from the operating system
shell. <exec> can be configured to invoke the top-level script to deploy
a build to an integration environment. The example below shows how the
deployment script, deploy.sh, is invoked after Ant
completes the build. The CompositeBuilder is designed to execute the builders
in the order that they are listed. If the script invoked by one of the builders
fails, the remaining builders are not executed. In the example below, deploy.sh will not be invoked if build.sh does not complete successfully.
<schedule
interval="300">
<composite>
<ant antscript="/opt/cruisecontrol/build.sh"
antworkingdir="/opt/cruisecontrol/projects/${project.name}"
uselogger="false"/>
<exec
workingdir="/opt/cruisecontrol/projects/${project.name}" command="/opt/cruisecontrol/projects/${project.name}/deploy.sh"/>
</composite>
</schedule>
Maintaining CruiseControl Configuration Files Under
Version Control
As more projects are added
to CruiseControl, the configuration file config.xml becomes more critical, and
more difficult to reconstruct from scratch. In additional to config.xml, other
files are created or modified to support CruiseControl projects. Some files are
stored in the top-level directory where CruiseControl is installed. Other files
reside in the subdirectories that correspond to the CruiseControl projects. For
example, project-specific build and deployment scripts are likely to be stored
in the subdirectory for a CruiseControl project.
To protect CruiseControl files
from accidental loss or corruption, the files should be maintained under
version control. To ensure that the files under version control match those in
operation, all configuration files, including project-specific files, should be
kept in the directory that serves as the workspace for the version control
tool.
If CruiseControl is
installed on a Unix or Linux server, symbolic links can be created from the
CruiseControl installation directory to the configuration files and
subdirectories in the directory that contains the workspace for the version
control tool. This means the
CruiseControl instance is running from the configuration files that are in the
workspace of the version control tool. If the workspace is kept synchronized
with the version control repository, the files used by the CruiseControl
instance are those under version control.
The example below shows
symbolic links in the top-level directory where CruiseControl is installed.
These links are to a file and subdirectory in the directory on the file system
that maintains the workspace for the version control tool.
config.xml
-> /opt/versionControlTool/workspace/config.xml
projects
-> /opt/versionControlTool/workspace/projects
Summary: Optimizing CruiseControl
Implementing CI begins with
installing and configuring CruiseControl. Optimizing a CruiseControl
installation involves structuring the config.xml file so that it can be
extended and maintained to support multiple projects. By using plugin
preconfiguration, configuration settings can be specified at the beginning of
the config.xml file then referenced in all projects that use this information.
Optimizing a CruiseControl
installation also involves using this open source tool to validate deployments.
The CompositeBuilder can be used to invoke a script to deploy each successful
CI build to an integration environment.
Finally, optimizing a
CruiseControl installation entails keeping configuration files under version
control to prevent against accidental loss or corruption.
Michael
Sayko is a software configuration management consultant based in Austin, Texas.
From serving as a build engineer on several projects, he is experienced with Continuous
Integration and build and deployment automation of J2EE applications. You
can reach Michael by email at
This e-mail address is being protected from spam bots, you need JavaScript enabled to view it
.
Trackback(0)
|