CruiseControl.Net Tutorial – Part 1

1 06 2008


Suggested Books

Expert .Net Delivery .Net Architecting Applications For The Enterprise Patterns of  Enterprise Application Architecture Design Patterns

My AutoComplete Project on CodePlex

1. Introduction
2. Resources
3. Installation
3.1. Install CruiseControl.NET
3.2. Create a CCNet Website in IIS
3.3. Install Nunit
4. CruiseControl.NET Server Configuration – General
5. Structure of a ‘Project’ Configuration File
6. Source Control Block
7. Trigger Block
8. Labeller Block
9. Tasks Block (part 2)
10. MsBuild Task (part 2)
10.1. MSBuild and ReferencePath – CruiseControl.NET not resolving reference to Nunit (part 2)
10.2. An Alternative MSBuild Logger – Christian Rodemeyer’s MsBuildToCCNet (part 2)
10.3. CruiseControl.NET Webdashboard fails in finding images if not installed in virtual directory (part 2)
10.4. MSBuildToCCNET reports wrong number of compiled projects (part 2)
10.5. CruiseControl.NET, MsBuild Task and Resources – Assembly Linker (part 2)
10.6. CruiseControl.NET, MsBuild Task and Web Application projects (part 2)
11. Nunit Task (part 2)
11.1. Nunit Task (part 2)
11.2. Executable Task (part 2)
12. Publishers Block (part 2)
13. PreBuild Block (part 2)
13.1. Install Nant (part 2)
13.2. Nant Fundamentals (part 2)

1. Introduction

In this article series I will review the various steps needed to setup and configure a working CruiseControl.Net server.
The goal is to set up a Continuous Integration process for a sample project as close as possible to a real-life project.
I will point out several issues that might arise and I will provide solutions as well.
I will try to underline all the details that you need to be aware of.

Thanks to Frank Geerlings for making me aware of a casing problem with the xml samples.
By talking with the guys at WordPress support it came out that there was a little bug and they suggested me how to fix the problem.

→ top of post

2. Resources

During the article I will guide you through the installation process of the following software:

Subversion
CruiseControl.NET
Nunit

Nant
FxCop
NantContrib

The following are optional:

TortoiseSVN
AnkhSVN

You can find information about how to install: Subversion, TortoiseSVN and AnkhSVN in the article: Guide to Versioning a Visual Studio Solution with Subversion, TortoiseSVN and AnkhSVN.
There you can also find a quick guide about how to create a Subversion repository and how to add a Visual Studio solution to source control.

This tutorial assumes that you have Subversion 1.4.6 installed and that you have configured a Subversion repository at the url: svn://localhost/trunk as shown in the article: Guide to Versioning a Visual Studio Solution with Subversion, TortoiseSVN and AnkhSVN.

If you already have a working environment with a repository and versioned files, you can go on reading and replace the paths and names in the examples with the paths and names in your environment.

→ top of post
→ top of paragraph

3. Installation

This tutorial will assume that you install CruiseControl.NET on the same machine on which you had installed the Subversion repository. So, first of all, let’s go through the steps needed to install CruiseControl.NET on your server machine.

3.1. Install CruiseControl.NET

Download the latest CruiseControl.NET release from: SourceForge or the latest build from CCNetLive.
You can find release notes here. For this article I used the installer for version 1.4 (CruiseControl.NET-1.4-Setup.exe), downloaded from the CCNetLive website.

Run the setup executable file and, when prompted, you must specify your choices for a couple of actions:
‘Install CC.Net server as windows service’ must be checked so that the setup will install CruiseControl as a Windows service.
In the Services management console the CruiseControl service will be displayed with the name: CruiseControl.NET.
‘Create virtual directory in IIS for Web dashboard’ will create a virtual directory named ccnet in the machine’s IIS web server. If you have an IIS server installation supporting multiple web sites (this is not the case for Windows XP Professional) and prefer to have a separate web site for the CCNet web dashboard you should uncheck this option. This is my choice. In the next paragraph I will show you how to create an IIS web site for the CruiseControl.NET web dashboard.

When the install process is finished all the content will be installed in the folder:
C:\%ProgramFiles%\CruiseControl.NET (e.g. C:\Program Files\CruiseControl.NET).
Under this path you will find a directory called server, containing all the CCNet binary files and executables, and a directory called webdashboard, containing the CruiseControl.NET web interface.

→ top of post
→ top of paragraph

3.2. Create a CCNet Website in IIS

Here I will add and configure a Website in IIS for the CruiseControl.NET Webdashboard: the administrative interface of CruiseControl.NET.
Open IIS Manager in Administrative Tools, right-click on the Web Sites node and select New Web Site.
The Web site creation wizard will start.
Click Next and you will be prompted for a Web Site Description.
Type CCNet and click Next, leave Unassigned the IPAddress, choose a port number (say: 222) and leave empty the ‘Host Header for this site’ field, then click Next.
Choose C:\%ProgramFiles%\CruiseControl.NET\webdashboard as the path for the Website and click Next.
Allow ‘Read’ and ‘Run scripts’, the default, and click Next. The wizard is finished and the new Website created.

→ top of post
→ top of paragraph

3.3. Install Nunit

For the sake of our example we will need Nunit so, if you haven’t already done, install it on the same machine on which you have installed CruiseControl.NET.

You can find the latest Nunit release here at SourceForge.
This article is based on the release 2.4.6, currently the latest. You can install it by downloading: NUnit-2.4.6-net-2.0.msi.

After the installation you will have a new directory under %ProgramFiles% : C:\%ProgramFiles%\NUnit 2.4.6.

→ top of post
→ top of paragraph

4. CruiseControl.NET Server Configuration – General

All the configuration files we’re going to talk about are placed or are to be placed in:
C:\%ProgramFiles%\CruiseControl.NET\server.

CruiseControl.NET comes with two server executables: ccservice.exe which is the windows service installed by the installation setup and ccnet.exe which is a console application included for testing purposes.
It is much easier to debug a console application that a service so I strongly suggest to make your initial tests with ccnet.exe and carefully read the console output to get familiar with CCNet behavior.

Each of the two executables comes with a default configuration file (i.e.: ccservice.exe.config and ccnet.exe.config) that you don’t need to change at the moment.
Moreover both the server processes (windows service or console application) look for a file named ccnet.config in which you will place all the actual information needed by CCNet to learn what it is supposed to do and how it is supposed to do it.

ccnet.config is an xml file with a root element named <cruisecontrol> and a child element, named <project>, for each set of activities that we want CruiseControl.NET to execute, as shown in the following example:

<cruisecontrol>
<project name="project1">
    ...
  </project>
<project name="project2">
    ...
  </project>
</cruisecontrol>

In this tutorial we will setup our CruiseControl.NET configuration with two logical sets of activities.
For the sake of clarity we will benefit of the usage of xml entities.
We’ll define each ‘project’ configuration in a separate file and import all the files in ‘ccnet.config’ by means of entity definitions and entity declarations:

< !DOCTYPE cruisecontrol [
	< !ENTITY project1 SYSTEM "file:project1.xml.config">
	< !ENTITY project2 SYSTEM "file:project2.xml.config">
]>
<cruisecontrol>
  &project1;
  &project2;
</cruisecontrol>

Let’s focus, at first, only on the first project, so delete the second entity reference (i.e.: &project2; ) thus obtaining:

< !DOCTYPE cruisecontrol [
	< !ENTITY project1 SYSTEM "file:project1.xml.config">
	< !ENTITY project2 SYSTEM "file:project2.xml.config">
]>
<cruisecontrol>
  &project1;
</cruisecontrol>

→ top of post
→ top of paragraph

5. Structure of a ‘Project’ Configuration File

What we need to do now is creating a file named: project1.xml.config in C:\%ProgramFiles%\CruiseControl.NET\server
and use it to setup CruiseControl.NET main activities.
This file will contain what is called the ‘Project Configuration Block’ for the first CCNet activity that we want to configure.
First of all we need to assign a unique name to the root of the Project Configuration Block: the <project> tag. We then write:

<project name="1 - testProject">
  <webURL>http://192.168.15.2:222</weburl>
  <workingDirectory>C:\develop\CCnet\project1WorkingDir
  </workingDirectory>
  <artifactDirectory>C:\develop\CCnet\project1CCnetArtifacts
  </artifactDirectory>
  ...
</project>

Let’s talk about the first three children nodes:

represents the URL at which the current project is available through the web interface. We will see later why it is useful.
For now just make sure to set it to the IP of the server machine (in which you installed CCNet) and to the port that you chose for the WebDashboard website when you configured the web site in IIS (see: 3.2. Create a CCNet Website in IIS).

is the path to the main directory of this project and is meant to contain the checked out version of the project under integration.
This path will be accessible as an environment variable: %CCNetWorkingDirectory%, available to external scripts (we will see it later).
I use to place all the projects managed with CCNET in folders under a common directory named: C:\develop\CCnet.
For this test project I chose: C:\develop\CCnet\project1WorkingDir.

It is convenient to choose a directory in which to place all the stuff that will be used by CCNet (script files or executable files that you may want CruiseControl.NET to execute) as well as the workingDirectory in which CCNET will checkout the versioned files and the artifactDirectory in which it will output log files.
In the example above I chose the directory: C:\develop\CCnet as the container of all CCNet related stuff.

is the path to the directory where all the build logs for this project will be placed.

Apart from the three tags described above, the main blocks that we’re going to add to the project configuration file are:

→ top of post
→ top of paragraph

6. Source Control Block

Source Control configuration block tells CruiseControl.NET that the project named ‘1 – testProject’ is bound to a Subversion repository.
This means that the task performed when executing this project depends on the status of that particular Subversion repository.
As soon as CruiseControl.NET detects a new revision in the repository it updates its working copy and executes the tasks related to the current project.
Here is the xml excerpt:

<sourcecontrol type="svn">
<trunkUrl>svn://localhost/trunk</trunkUrl>
  <workingDirectory>C:\develop\CCnet\project1WorkingDir
  </workingDirectory>
  <username>ccnet </username>
<password> ccnet </password>
</sourcecontrol>

contains the url of the repository that we want to check for modifications (e.g., svn://svnserver/pathToRepo).
As we saw in the post Guide to Versioning a Visual Studio Solution with Subversion, TortoiseSVN and AnkhSVN, Subversion could host several repositories under a common folder, say: C:\develop\TestRepo.
But in that article, as well as in the current example, we set up only one repository and run svnserve with the command line: svnserve -d -r “C:\develop\test\repo”.
So, specifying the server name (localhost) and the path to the particular repository we’re interested in, turns out to be simply: svn://localhost/trunk (instead of: svn://localhost/SpecificRepositoryFolder/trunk);
is the directory that will contain the working copy checked out by CCNET;
sets the timeout for the source control operation. It defaults to 10 minutes and you can set it to a different amount of time in milliseconds (default) or specifying units (“millis”, “seconds”, “minutes”, “hours”); I left it out thus accepting the default.
If you want to set it to a different value remember to not choose a too short timeout value because if the timeout is exceeded the build will fail without providing information about the reason.
In that case the only way you can retrieve the actual reason of the build failing is by analyzing CCNET log file in the CruiseControl.NET\server folder (if you set log4net to the debug log level)
and must be set to a valid svn account that CCNET can use to access Subversion repository.

→ top of post
→ top of paragraph

7. Trigger Block

A trigger block is needed to specify when CruiseControl.NET will start a new integration cycle.
We want to check for the repository status continuously so we need an ‘Interval Trigger’ to tell CruiseControl.NET to perform integration periodically after a specified amount of time:

<triggers>
  <intervalTrigger name="Subversion" seconds="10" />
</triggers>

CruiseControl.NET, as far as project ‘1 – TestProject’ is concerned, polls the repository every 10 seconds to see if any changes has been committed.
The name attribute is used by CruiseControl.NET GUI to identify the trigger that requested the build;
The seconds attribute is the amount of time before triggering the next integration cycle.

Each time the time interval elapses, CCNET checks for modifications and, by default, runs integration only if changes are detected.

→ top of post
→ top of paragraph

8. Labeller Block

A label is created, at each integration cycle, to identify the specific build occurred.
Different labellers can be used to generate the label that CCNet will use to track the builds.

Other than the Labeller Blocks that come with the CruiseControl.NET distribution, many people provided plugin Labeller Blocks to target the generation of labels with specific formats.

A very good one, IMHO, is SvnRevisionLabeller by David Keaveny (much important to me because I recently contributed to the project).
This plugin allows labelling CruiseControl.NET builds with Subversion’s repository revision numbers and I think this is a really useful feature.
So this example will use SvnRevisionLabeller as the Labeller Block.
For detailed information about this plugin see my post: CruiseControl.NET and Subversion – SvnRevisionLabeller.

To use the SvnRevisionLabeller plugin in your installation of CruiseControl.NET you need to unzip the downloaded package and copy the assembly: ccnet.SvnRevisionLabeller.plugin.dll in the server folder directory under the CruiseControl.NET install path (e.g.: ‘C:\Program Files\CruiseControl.NET\server’).

Next you need to configure the Labeller Block in your project:

<labeller type="svnRevisionLabeller">
	<major>7</major>
	<minor>11</minor>
	<url>svn://localhost/trunk</url>
</labeller>

SvnRevisionLabeller will produce build labels in the format:

major.minor.svnRevision.build

where major and minor are the two values you set in the configuration block while svnRevision is the current version in the Subversion’s repository related to this project.
The build number is automatically incremented each time a new build is forced if no further modification has been committed to the repository.

<url> is the path to the repository used to retrieve the revision number (e.g. svn://svnserver/pathToRepo/trunk). Actually it should be filled with the same path used in the <trunkUrl> field of the Subversion Source Control Block.
In our example it is:

<url>svn://localhost/trunk</url>

Following is a configuration for SvnRevisionLabeller with the complete set of fields:

<labeller type="svnRevisionLabeller">
<prefix>Test-</prefix>
  <major>7</major>
  <minor>11</minor>
  <url>svn://localhost/trunk</url>
  <username>ccnet</username>
<password>ccnet</password>
</labeller>

Such a configuration will produce a label with the following format: Test-major.minor.svnRevision.build.
<username> and <password> are the username and password of a valid Subversion account for the repository specified in the <url> field.

You can use in an external script the build label produced, which is stored in an environment variable.
It can be useful to flag release version of output dlls.
You can access the build number from a script with the syntax: %CCNetLabel% or from a C# application with the following row:

Environment.GetEnvironmentVariable("ccnetlabel");

If you used the SolutionInfo approach in your Visual Studio solution (see my post: SolutionInfo and Partitioned Single Solution) you can use the build label produced by SvnRevisionLabeller to update the AssemblyFileVersion attribute in the SolutionInfo.cs file.
In this way you can provide consistent versioning of the released assemblies together with easy trackability of the corresponding source code’s revision.

Be careful not to use the <prefix> tag in this case because you need to set AssemblyFileVersion to a string in the format:
major.minor.svnRevision.build
with all of the 4 fields being numerical values.

→ top of post
→ top of paragraph

CruiseControl.Net Tutorial – Part 2 >>


kick it on DotNetKicks.com

Advertisements







%d bloggers like this: