You are on page 1of 73

CRUISE CONTROL.

NET

SLNo Content Page


Study & Overview

1. Introduction to Continuous Integration and Cruise Control .Net 2

2. Installation Process 11

3. CCNet server configuration(CCNet.config) 12

4. File Merge task 22

5. Configure CruiseControl.Net to Automatically Update its Config File 24

6. CCTray 26
Build Configuration - Nant

7. Integration on a project built using Nant 29

8. Nant element in configuration file 31

9. Nant O/p in XML File 32

10. Nant and Nunit 32

11. CCNet build labels in Nant 33

12. CCNet build from Nant script 35


Build Configuration - MSBuild

13. Integration on a project built using MSBuild 43

14. MSBuild element in configuration file 43


Build Configuration - Visual Studio

15. Integration on a project built using Visual Studio 51

16. Visual Studio element in configuration file 52


Web Dashboard

17. Installation 53

18. Configuring the web dashboard 54


CRUISE CONTROL.NET

19. Using Web dashboard 67

20. Developing web dashboard plug-ins 69

Study & Overview


Introduction of Continuous Integration

Continuous Integration is a software development practice where members of a team integrate


their work frequently; usually each person integrates at least daily - leading to multiple
integrations per day. Integration is verified by an automated build (including test) to detect
integration errors as quickly as possible. Many teams find that this approach leads to
significantly reduced integration problems and allows a team to develop cohesive software more
rapidly.

Feature with Continuous Integration

Maintain a Single Source Repository.

Software projects involve lots of files that need to be orchestrated together to build a product.
Keeping track of all of these is a major effort, particularly when there's multiple people involved.
So it's not surprising that over the year’s software development teams have built tools to manage
all this. These tools - called Source Code Management tools, configuration management, version
control systems, repositories, or various other names - are an integral part of most development
projects.

So as a simple basis make sure you get a decent source code management system. The current
open source repository of choice is Subversion. (The older open-source tool CVS is still widely
used, and is much better than nothing, but Subversion is the modern choice.).

Once you get a source code management system, make sure it is the well known place for
everyone to go get source code. Everything should be in the repository.

The basic rule of thumb is that you should be able to walk up to the project with a virgin
machine, do a checkout, and be able to fully build the system.

You must put everything required for a build in the source control system; however you may also
put other stuff that people generally work with in there too. IDE configurations are good to put in
there because that way it's easy for people to share the same IDE setups.

One of the features of version control systems is that they allow you to create multiple branches,
to handle different streams of development. Keep your use of branches to a minimum. In
particular have a mainline: a single branch of the project currently under development. Pretty
CRUISE CONTROL.NET

much everyone should work off this mainline most of the time. In general you should store in
source control everything you need to build anything, but nothing that you actually build.

Automate the Build

Getting the sources turned into a running system can often be a complicated process involving
compilation, moving files around, loading schemas into the databases, and so on. However like
most tasks in this part of software development it can be automated - and as a result should be
automated.

Automated environments for builds are a common feature of systems. The .NET community has
had Nant and now has MSBuild. Make sure you can build and launch your system using these
scripts using a single command.

A common mistake is not to include everything in the automated build. The build should include
getting the database schema out of the repository and firing it up in the execution environment.
I'll elaborate my earlier rule of thumb: anyone should be able to bring in a virgin machine, check
the sources out of the repository, issue a single command, and have a running system on their
machine.

A big build often takes time; you don't want to do all of these steps if you've only made a small
change. So a good build tool analyzes what needs to be changed as part of the process. The
common way to do this is to check the dates of the source and object files and only compile if the
source date is later. Dependencies then get tricky: if one object files change those that depend on
it may also need to be rebuilt. Compilers may handle this kind of thing, or they may not.

Depending on what you need, you may need different kinds of things to be built. You can build a
system with or without test code, or with different sets of tests. Some components can be built
stand-alone. A build script should allow you to build alternative targets for different cases.

Make Your Build Self-Testing

Traditionally a build means compiling, linking, and all the additional stuff required to get a
program to execute. A program may run, but that doesn't mean it does the right thing. Modern
statically typed languages can catch many bugs, but far more slip through that net.

A good way to catch bugs more quickly and efficiently is to include automated tests in the build
process. Testing isn't perfect, of course, but it can catch a lot of bugs - enough to be useful. For
self-testing code you need a suite of automated tests that can check a large part of the code base
for bugs. The tests need to be able to be kicked off from a simple command and to be self-
checking. The result of running the test suite should indicate if any tests failed. For a build to be
self-testing the failure of a test should cause the build to fail.

Everyone Commits Every Day


CRUISE CONTROL.NET

Integration is primarily about communication. Integration allows developers to tell other


developers about the changes they have made. Frequent communication allows people to know
quickly as changes develop.

My general rule of thumb is that every developer should commit to the repository every day. In
practice it's often useful if developers commit more frequently than that. The more frequently
you commit, the less places you have to look for conflict errors, and the more rapidly you fix
conflicts.

Frequent commits encourage developers to break down their work into small chunks of a few
hours each. This helps track progress and provides a sense of progress. Often people initially feel
they can't do something meaningful in just a few hours, but we've found that mentoring and
practice helps them learn.

Every Commit Should Build the Mainline on an Integration Machine

Using daily commits, a team gets frequent tested builds. This ought to mean that the mainline
stays in a healthy state. You should ensure that regular builds happen on an integration machine
and only if this integration build succeeds should the commit be considered to be done. Since the
developer who commits is responsible for this, that developer needs to monitor the mainline
build so they can fix it if it breaks.

A continuous integration server acts as a monitor to the repository. Every time a commit against
the repository finishes the server automatically checks out the sources onto the integration
machine, initiates a build, and notifies the commitment of the result of the build. The committer
isn't done until she gets the notification - usually an email.

At ThoughtWorks, we're big fans of continuous integration servers - indeed we led the original
development of Cruise Control and CruiseControl.NET, the widely used open-source CI servers.
Since then we've also built the commercial Cruise CI server. We use a CI server on nearly every
project we do and have been very happy with the results.

Not everyone prefers to use a CI server. I agree with him that CI is much more than just
installing some software. All the practices here need to be in play to do Continuous Integration
effectively. But equally many teams who do CI well find a CI server to be a helpful tool.

Many organizations do regular builds on a timed schedule, such as every night. This is not the
same thing as a continuous build and isn't enough for continuous integration. The whole point of
continuous integration is to find problems as soon as you can. Nightly builds mean that bugs lie
undetected for a whole day before anyone discovers them. Once they are in the system that long,
it takes a long time to find and remove them.

A key part of doing a continuous build is that if the mainline build fails, it needs to be fixed right
away. The whole point of working with CI is that you're always developing on a known stable
base. It's not a bad thing for the mainline build to break, although if it's happening all the time it
suggests people aren't being careful enough about updating and building locally before a commit.
CRUISE CONTROL.NET

When the mainline build does break, however, it's important that it gets fixed fast. To help avoid
breaking the mainline you might consider using a pending head.

When teams are introducing CI, often this is one of the hardest things to sort out. Early on a team
can struggle to get into the regular habit of working mainline builds, particularly if they are
working on an existing code base. Patience and steady application does seem to regularly do the
trick, so don't get discouraged.

Keep the Build Fast

The whole point of Continuous Integration is to provide rapid feedback. Nothing sucks the blood
of a CI activity more than a build that takes a long time

For most projects, however, the XP guideline of a ten minute build is perfectly within reason.
Most of our modern projects achieve this. It's worth putting in concentrated effort to make it
happen, because every minute you reduce off the build time is a minute saved for each developer
every time they commit. Since CI demands frequent commits, this adds up to a lot of time.

If you're staring at a one hour build time, then getting to a faster build may seem like a daunting
prospect. It can even be daunting to work on a new project and think about how to keep things
fast. For enterprise applications, at least, we've found the usual bottleneck is testing - particularly
tests that involve external services such as a database.

Probably the most crucial step is to start working on setting up a staged build. The idea behind a
staged build (also known as build pipeline) is that there are in fact multiple builds done in
sequence. The commit to the mainline triggers the first build - what I call the commit build. The
commit build is the build that's needed when someone commits to the mainline. The commit
build is the one that has to be done quickly; as a result it will take a number of shortcuts that will
reduce the ability to detect bugs. The trick is to balance the needs of bug finding and speed so
that a good commit build is stable enough for other people to work on.

Once the commit build is good then other people can work on the code with confidence.
However there are further, slower, tests that you can start to do. Additional machines can run
further testing routines on the build that take longer to do.

A simple example of this is a two stage build. The first stage would do the compilation and run
tests that are more localized unit tests with the database completely stubbed out. Such tests can
run very fast, keeping within the ten minute guideline. However any bugs that involve larger
scale interactions, particularly those involving the real database, won't be found. The second
stage build runs a different suite of tests that do hit the real database and involve more end-to-end
behavior. This suite might take a couple of hours to run.

In this scenario people use the first stage as the commit build and use this as their main CI cycle.
The second-stage build is a secondary build which runs when it can, picking up the executable
from the latest good commit build for further testing. If the secondary build fails, then this
doesn't have the same 'stop everything' quality, but the team does aim to fix such bugs as rapidly
CRUISE CONTROL.NET

as possible, while keeping the commit build running. Indeed the secondary build doesn't have to
stay good, as long as each known bug is identified and dealt with in a next few days. As in this
example, secondary builds are often pure tests since these days it's usually tests that cause the
slowness.

If the secondary build detects a bug, that's a sign that the commit build could do with another
test. As much as possible you want to ensure that any secondary build failure leads to new tests
in the commit build that would have caught the bug, so the bug stays fixed in the commit build.
This way the commit tests are strengthened whenever something gets past them. There are cases
where there's no way to build a fast-running test that exposes the bug, so you may decide to only
test for that condition in the secondary build. Most of time, fortunately, you can add suitable tests
to the commit build.

This example is of a two-stage build, but the basic principle can be extended to any number of
later builds. The builds after the commit build can also be done in parallel, so if you have two
hours of secondary tests you can improve responsiveness by having two machines that run half
the tests each. By using parallel secondary builds like this you can introduce all sorts of further
automated testing, including performance testing, into the regular build process. (I've run into a
lot of interesting techniques around this as I've visited various ThoughtWorks projects over the
last couple of years - I'm hoping to persuade some of the developers to write these up.)

Make it Easy for Anyone to Get the Latest Executable

One of the most difficult parts of software development is making sure that you build the right
software. We've found that it's very hard to specify what you want in advance and be correct;
people find it much easier to see something that's not quite right and say how it needs to be
changed. Agile development processes explicitly expect and take advantage of this part of human
behavior.

To help make this work, anyone involved with a software project should be able to get the latest
executable and be able to run it: for demonstrations, exploratory testing, or just to see what
changed this week.

Doing this is pretty straightforward: make sure there's a well known place where people can find
the latest executable. It may be useful to put several executables in such a store. For the very
latest you should put the latest executable to pass the commit tests - such an executable should be
pretty stable providing the commit suite is reasonably strong.

If you are following a process with well defined iterations, it's usually wise to also put the end of
iteration builds there too. Demonstrations, in particular, need software whose features are
familiar, so then it's usually worth sacrificing the very latest for something that the demonstrator
knows how to operate.

Everyone can see what's happening


CRUISE CONTROL.NET

Continuous Integration is all about communication, so you want to ensure that everyone can
easily see the state of the system and the changes that have been made to it.

One of the most important things to communicate is the state of the mainline build. If you're
using Cruise there's a built in web site that will show you if there's a build in progress and what
was the state of the last mainline build. Many teams like to make this even more apparent by
hooking up a continuous display to the build system - lights that glow green when the build
works, or red if it fails are popular. A particularly common touch is red and green lava lamps -
not just do these indicate the state of the build, but also how long it's been in that state. Bubbles
on a red lamp indicate the build's been broken for too long. Each team makes its own choices on
these build sensors.

Cruise provides an indication not just of who is building, but what changes they made. Cruise
also provides a history of changes, allowing team members to get a good sense of recent activity
on the project. I know team leads who like to use this to get a sense of what people have been
doing and keep a sense of the changes to the system.

Another advantage of using a web site is that those that are not co-located can get a sense of the
project's status. In general I prefer to have everyone actively working on a project sitting
together, but often there are peripheral people who like to keep an eye on things. It's also useful
for groups to aggregate together build information from multiple projects - providing a simple
and automated status of different projects.

Good information displays are not only those on a computer screens. One of my favorite displays
was for a project that was getting into CI. It had a long history of being unable to make stable
builds. We put a calendar on the wall that showed a full year with a small square for each day.
Every day the QA group would put a green sticker on the day if they had received one stable
build that passed the commit tests, otherwise a red square. Over time the calendar revealed the
state of the build process showing a steady improvement until green squares were so common
that the calendar disappeared - its purpose fulfilled.

Automate Deployment

To do Continuous Integration you need multiple environments, one to run commit tests, one or
more to run secondary tests. Since you are moving executables between these environments
multiple times a day, you'll want to do this automatically. So it's important to have scripts that
will allow you to deploy the application into any environment easily.

A natural consequence of this is that you should also have scripts that allow you to deploy into
production with similar ease. You may not be deploying into production every day (although I've
run into projects that do), but automatic deployment helps both speed up the process and reduce
errors. It's also a cheap option since it just uses the same capabilities that you use to deploy into
test environments.

If you deploy into production one extra automated capability you should consider is automated
rollback. Bad things do happen from time to time, and if smelly brown substances hit rotating
CRUISE CONTROL.NET

metal, it's good to be able to quickly go back to the last known good state. Being able to
automatically revert also reduces a lot of the tension of deployment, encouraging people to
deploy more frequently and thus get new features out to users quickly. (The Ruby on Rails
community developed a tool called Capistrano that is a good example of a tool that does this sort
of thing

Continuous Integration with CruiseControl.net

CruiseControl.net is the application which I will be discussing in particular. At its most basic it
can be used simply to create automatic builds which can at least prove that the application will
compile on a development server and not just on the developer's own desktop.

Setting up continuous integration for a project does take some time and effort but the end result
is that you can be much lazier: just let the automated process do it all for you.

So why would you want to implement continuous integration in the first place? Well, it
eliminates many of the concerns regarding integrating code that has been created by individual
developers and then has to be integrated into the final application. By building the application on
a clean machine any missing files or dependencies will be instantly recognized as these will
cause the build to fail. Continuous integration need not stop at just building the software it can
also automate unit testing (e.g. Nunit), code coverage (e.g. Ncover) which indicates the amount
of code that is actually being tested by unit test, documentation (e.g. Sandcastle) and standards
compliance (e.g. FxCop) amongst others.

Now you can begin to see the real value of this automation. Developers can feel much more
assured that the code they check into source control will build and, provided that it has adequate
code coverage, that it doesn't break any other code in the process.

I must point out that this process does not test the display of the GUI, it only tests the
functionality. As such it cannot replace all manual testing but it does cover a great deal.

CruiseControl.net
Definition of Cruise control.Net: It is set of application aimed towards an automated integration
with the help of CCNET Server.

Cruise Control is a free, Java-based framework, open-source software for a continuous build
process. It allows one to perform a continuous integration of any software development process.
CRUISE CONTROL.NET

Cruise Control is, distributed under a BSD-style license. It was originally created by employees
of Thought Works to allow for continuous integration on a project they were working on. It was
later extracted into a stand-alone application.

CruiseControl.NET (CCNet) consists of a suite of applications, but at its core is the CruiseControl.NET
Server which is an automated integration server.
The Server automates the integration process by monitoring the team's source control repository directly.
Every time a developer commits a new set of modifications, the server will automatically launch an
integration build to validate the changes. When the build is complete, the server notifies the developer
whether the changes that they committed integrated successfully or not.
Effectively, integration becomes as easy as checking in code. Using an automated integration server not
only makes integration easy, it also guarantees that an integration build will happen. There is no danger of
developers forgetting to validate their changes after checking in.
The CCNet Server offers several key features:
• Integration with a variety of Source Control systems
• Integration with other external tools, such as NAnt and Visual Studio
• Can build multiple projects on one server
• Remote management and reporting

Automatic Integration is done by monitoring Source control repository. In case, if you have
versioning servers like SVN, VSTS. By monitoring (i.e. by looking at the code) Source control
server (i.e. SVN, VSTS) your CCNet server will do the automatic integration process .As it
contains various applications, it will do various activities like Automatic Unit testing, Auto
Documentation, Static Code analysis, Code coverage and Error reports are generated and it will
sent them through mail.

CCTray & Web dashboard are application inbuilt in Cruise control.

The Web Dashboard is an ASP.NET application running on IIS. It provides you with details
about all your builds including reports and stats on individual builds. See screen grab below:
CRUISE CONTROL.NET

Here is an example of a unit testing stats page:


CRUISE CONTROL.NET

Here is a build report:

Installation Prerequisites - CruiseControl.NET

CruiseControl.NET Server

To get CruiseControl.NET server up and running, you need to have the following environments set up
and installed:
Microsoft.NET Framework Version 2.0 (download)

CruiseControl.NET Web Dashboard

Microsoft.NET Framework Version 2.0 (download)


ASP.NET-enabled web server (typically IIS with ASP.NET configured)

Developer desktop running CCTray

Microsoft.NET Framework Version 2.0 (download)


CRUISE CONTROL.NET

Basic Installation
CruiseControl.NET is distributed in 3 formats:
Two Installers, one for CruiseControl.NET proper (the Server and Web Dashboard), and a
second for the optional CCTray utility. The Installers are conventional Windows installation
programs, which perform some useful early setup work for you, such as copying files to good
locations, setting up a Virtual Directory for the Dashboard, etc. For most people starting out,
this is the way to go.

A binary zip file includes the same files as the installers but gives you more control over
what you can do with them.

A source zip which allows you to read or make your own changes to the CruiseControl.NET
source code.
The binary zip file will give you several sub-folders:
/server: holds the assemblies for the CruiseControl.NET Server, including both the Server
Console Application and the Server Service Application .

/webdashboard: contains the ASP.NET Web Dashboard application

/cctray: contains the assemblies for the CCTray application

/doc: contains HTML documentation for CruiseControl.NET

CruiseControl.Net Server Configuration


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.
CRUISE CONTROL.NET

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 xmlns:cb="urn:ccnet.config.builder">
<!-- This is your CruiseControl.NET Server Configuration file. Add your projects below!
-->
<!--
<project name="MyFirstProject" />
-->
</cruisecontrol>

Structure of a ‘Project’ Configuration File


Sample Structure:

<project name="1 - test Project">

<webURL>http://192.168.15.2:222</weburl>
<workingDirectory>C:\develop\CCnet\project1WorkingDir </workingDirectory>

<artifactDirectory>C:\develop\CCnet\project1CCnetArtifacts

</artifactDirectory>

</project>

<webURL> Tag:

It represents the URL at which the current project is available through the web interface. 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 Web Dashboard website when you configured the web site 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.

<workingDirectory> Tag:

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.
CRUISE CONTROL.NET

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.

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

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 sample source control Block

<sourcecontrol type="svn">

<trunkUrl>svn://localhost/trunk</trunkUrl>

<workingDirectory>C:\develop\CCnet\project1WorkingDir

</workingDirectory>

<username>ccnet </username>

<password> ccnet </password>

</sourcecontrol>

<trunkUrl> 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.
CRUISE CONTROL.NET

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);

This 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.

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:

Sample Trigger Block

<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.

Labeller Block
CRUISE CONTROL.NET

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:
CRUISE CONTROL.NET

<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:
CRUISE CONTROL.NET

major.minor.svnRevision.build
with all of the 4 fields being numerical values.

Tasks Block

The tasks block represents how the build of the project actually takes place.
In our example we will use an MsBuild Task to accomplish the main purpose of our project,
which is to compile the versioned Visual Studio solution.
After that we will use an Executable Task to run our unit tests, if the build succeeds.
Let’s see the whole Tasks Block, at first:

<tasks>

<!-- compiles working copy -- >

<msbuild>

<executable>C:\WINDOWS\Microsoft.NET\Framework\

v2.0.50727\MSBuild.exe

</executable>

<workingDirectory>C:\develop\CCnet\project1WorkingDir

</workingDirectory>

<projectFile>DummySolution.sln</projectFile >

<buildArgs>/noconsolelogger /v:quiet

/p:Configuration=Debug

/p:ReferencePath="C:\Program Files\NUnit 2.4.7\bin"

</buildArgs>

<targets>ReBuild</targets >

<timeout>600</timeout >

<logger>c:\Program Files\CruiseControl.NET\server\

Rodemeyer.MsBuildToCCNet.dll</logger >
CRUISE CONTROL.NET

</msbuild>

<!-- launches nunit tests on working copy -- >

<exec>

<executable>C:\Program Files\NUnit 2.4.7\

bin\nunit-console.exe

</executable >

<buildArgs>/xml:..\project1CCnetArtifacts\nunit-results.xml

/nologo Dummy.sln.nunit

/exclude:LongRunning,AnotherCategoryName

</buildArgs>

</exec>

</tasks>

Let’s focus on the MsBuild Task first and see how we can configure and customize it:

MsBuild Task

Let’s have a look at the meaning of the xml nodes children of the <msbuild> node:

<executable>: contains the path to the msbuild executable file. You don’t really need to set it
because the default value is the standard installation path:
C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\MSBuild.exe.
I decided to set it explicitly just to be sure about it .
<workingDirectory>: is the directory in which MsBuild will be run, so it must be the directory
containing our projects checked out working copy. You can provide a path relative to the current
project’s workinDirectory but I preferred to provide the full path. Actually, the path to the
CCNET checked out working copy is the same as the <workingDirectory> field of the Source
Control Block.
<projectFile>: is the name of the project to build. MsBuild accepts a Visual Studio solution file
as the project file to build. Obviously the MsBuild Task accepts it as well.
<buildArgs> This row provides additional command line arguments to MsBuild. We tell it not to
log events to the console (/noconsolelogger), to build the Debug configuration
(/p:Configuration=Debug) and to provide a reduced output (/v:quiet).
As far as the /p:ReferencePath buildArg is concerned it is worth to talk extensively about a
problem that could arise with Nunit,.
CRUISE CONTROL.NET

CruiseControl.NET, MsBuild Task and Web Application projects

A particular note is due for Web projects.


Updating Visual Studio 2005 you get the SP1. Together with the Service Pack 1 for Visual Studio
you get the WebApplication project template.
Such template lets us add a new kind of project to our solution: a web site project structured
exactly like any other Visual Studio project.
So you can quit creating new websites (File –> New –> Web Site…) and start creating new
WebApplication projects (File –> New –> Project… and then choose ‘ASP.NET Web
Application‘).

In order to use WebApplication projects you need to have Visual Studio installed on your
machine and the WebApplication project plugin (that comes with the Visual Studio 2005 SP1).
If the server in which CruiseControl.NET server is running is not a develpment workstation you
will get an error when trying to build a WebApplication project, because you miss those two
prerequisites.

You can easily fix this problem: you simply need to copy the file:
Microsoft.WebApplication.targets that you can find under:
“C:\Program Files\MSBuild\Microsoft\VisualStudio\v8.0\WebApplications\”
from a development workstation and paste it to the corresponding path on the server machine
(creating the directories in the path if needed).

Additionally, if you’re using an ASP.NET AJAX Enabled WebApplication as the web project
template you need to install the aspnet-ajax extensions as well.
You can find the installer (ASPAJAXExtSetup.msi) for .NET framework 2.0 here

PreBuild Block

There’s another issue to solve when integrating Nunit using either an Exec Task or the Nunit
Task: the Nunit log file is not deleted after the build succeeds or fails.
So upon the next build we’ll still have the old Nunit log file until the Task running Nunit is
executed.
To understand what I’m going to explain now, keep in mind that if a task in the Tasks Block fails
all the subsequent tasks in the block will be skipped while the tasks in the Publishers Block will
be executed.

If, during the next build, the MSBuild Task fails, the Exec Task (Nunit Task) launching Nunit
isn’t executed at all so the File Merge Task will merge the previous Nunit log file with the
current Xml Log Publisher output, thus leading to an incorrect report: still displaying the Nunit
results relative to the previous build.
We would obtain the current MSBuild report but the old Nunit report.
This behavior can lead to misunderstanding of the results so it is a good practice to delete the old
Nunit log file before every new build takes place.
CRUISE CONTROL.NET

The place to accomplish this task is the PreBuild Block.


I used a Nant build file to drive the steps needed to obtain the desired result (simply delete a file
if it exists).

Publishers Block

We will add a File Merge Task at the beginning of the Publishers section. You can see below the
publishers section as it is defined in our project configuration file:

<publishers>

<merge>

<files>

<file>..\project1CCnetArtifacts\nunit-results.xml

</file>

</files>

</merge>

<xmllogger />

<statistics />

<modificationHistory onlyLogWhenChangesFound="true" />

<artifactcleanup cleanUpMethod="KeepLastXBuilds"

cleanUpValue="20" />

...

</publishers>

The File Merge Task specifies the paths to the files that we want to be merged by the Xml Log
Publisher Task with the rest of its own output (you don’t need to specify nunit output file if you
used the Nunit Task as in paragraph 11.1. Nunit Task).
All of this output is placed by default in the buildlogs directory under the Project’s Artifact
Directory.
So the File Merge Task should appear before the Xml Log Publisher Task in the publishers
section.
CRUISE CONTROL.NET

The Xml Log Publisher Task (’xmllogger‘) is needed for making the web dashboard work
correctly.
The ‘statistics‘ field collects and updates statistics for each build. You can see them clicking:
View Statistics on the left side of the Web Dashboard.
The ‘modificationHistory‘ field logs all the modifications for each build. With
onlyLogWhenChangesFound you can choose to log info only for builds happened when
changes take place (not for forced builds). You can see the modification history by clicking:
View Modification History on the left side of the Web Dashboard.

I then added an ‘artifactcleanup‘ field in order to keep memory of the last 20 builds only.
This task allows us to choose between two clean up modes of the past build logs:
- deleting logs older than a specified number of days
- keeping only a specified number of logs: the more recent ones
(cleanUpMethod=”KeepLastXBuilds”)

In the sample above we typed the second choice specifying 20 as cleanUpValue thus telling
CruiseControl.NET to keep the log files for the last 20 builds only.

File Merge task


Most build processes interact with external tools that write their output to file (e.g. NUnit, FxCop, or
Ncover). To make the output of these tools available to CruiseControl.NET to be used in the build process
or displayed in the CruiseControl.NET web page or included in CruiseControl.NET emails, these files
need to be merged into the CruiseControl.NET integration.
To merge these files, you need to include a File Merge Task in your CruiseControl.NET project. To do
so, you need to modify your ccnet.config file as follows:
<cruisecontrol>
<project name="project">
...
<publishers>
<merge>
<files>
<file><!-- path to NUnit test file --></file>
<file><!-- path to FxCop file --></file>
</files>
</merge>
</publishers>
</project>
</cruisecontrol>
CRUISE CONTROL.NET

You should place your File Merge Tasks in the <publishers /> section of your Project
Configuration Block before your Xml Log Publisher.

The files processed by File Merge Task must be in XML format.

Modify the contents of the <files> element to contain the path of the files that you wish to merge. The file
can be specified using an asterisk ("*") wildcard in order to include multiple files that match the specified
pattern (i.e. "*-results.xml" will merge all files ending with the suffix "-results.xml"). The asterisk
wildcard can only be used in the filename, not in the path.
If a relative <file> location is specified, this is relative to the Project Working Directory.

Why are the merged results not showing up in the [Project Report Web Application]?
If you have set up the configuration for the File Merge Task as described above and you are still not
ending up with the appropriate results showing up within the web application, please try the following
steps:
1. Click the original log link and check to see if the merged content is included in the xml. If it is missing
then got onto step 2. If it is present and is still not showing up in the web page then try emailing the
CCNet users list .
2. Have you put the File Merge Tasks in the <publishers /> section of your Project Configuration Block
before your Xml Log Publisher?
3. Check the folder that contains the files that should be merged. If they are not there then you need to dig
into your build script to find out why they aren't getting created.
4. If the files are there but aren't getting merged, double-check your ccnet.config file. Is the configuration
specified correctly as specified above? Remember that case matters in XML tag and attribute names.
5. Check the ccnet.log file. You should see Info-level log messages stating that the files have been merged.
6. Does the file contain valid XML data? The File Merge Task only expects to process XML files. It will
attempt to clean up non-XML files and write errors to the ccnet.log file, but it isn't always successful.
Comments (Hide Comments)

It would be nice to define new tag where file should be merged.


<file tag="MyTag">MyFile1.xml</file>
<file tag="MyTag" useExist="true">MyFile2.xml</file>
Both file will be merged to <MyTag></MyTag>
And second won't be create new <MyTag></MyTag>, it will be added inside.
In such way it is possible correctly to add new modification or anything else to existent tags.
It could be usefull if you can’t directly control output files.

Configure CruiseControl.Net to Automatically Update its Config File

Step 1: Get your configuration file under source control


CRUISE CONTROL.NET

At minimum this involves checking the file in. But there are cleaner and less clean ways to do
this. Rather than checking the entire CruiseControl.Net folder in, I like to have a config folder
underneath the main program folder that only has the config file in it.

This is not the default location for ccnet's config file, so it needs to be told to look in a different
place as well. If you are using CC.Net as a service, then the "ccnet.config" key can be added to
the <appSettings> section in ccservice.exe.config to point to the new configuration file, as shown
in the next code block. If you are running CC.Net in a console, using ccnet.exe.config, then you
can pass the new path as a command-line parameter in the form "-config:config\ccnet.config".
The path can be relative to the exe or an absolute path. More information about moving the
configuration file is available on the Server Application Config File page.
<configuration>
...
<appSettings>
<!-- Without this appSetting ccservice will look for ccnet.config in its own directory. -->
<add key="ccnet.config" value="config\ccnet.config" />
...
</appSettings>
...
</configuration>

Step 2: Add a CruiseControl.Net project to update the config file


At this point, someone could manually update the working copy on the cruise box when changes
to the config are committed. But, we can have ccnet itself automatically perform this step by
adding a project to ccnet. This project will check for changes to the configuration file in the
CRUISE CONTROL.NET

source control repository and update it on disc. We only need a trigger block and a source control
block. For the example worked above, this project would look like:
<project name="cc-config">
<triggers>
<intervalTrigger seconds="30" />
</triggers>
<sourcecontrol type="svn">
<trunkUrl>file:///c:/Repo/sandbox/config</trunkUrl>
<workingDirectory>C:\Program
Files\CruiseControl.NET\server\config</workingDirectory>
</sourcecontrol>
</project>
Now, when someone commits changes, the next time the cc-config project runs it will pull the
changes on to the local disc. CruiseControl.Net will notice the changes and reload the
configuration file. If you have the console visible you should see lines similar to the following:

CCTray
CCTray is a little application that helps you monitor your build. Simply access you Web
Dashboard, and it the left menu, there is an option to download CCTray.
CRUISE CONTROL.NET

Then you need to add the projects you want to monitor. You do that first by entering the name of
the server and then selecting the projects you want. I’m usually using the “Connect directly using
.NET remoting.

Cruisecontrol Tray
CRUISE CONTROL.NET

CruiseControl.net comes with a client side application which is shown in the sys tray and can be
viewed via a double click on the icon:

Here is the application:

OK, in this window you will see four separate builds. The bottom three builds have been created
for just one application. I will discuss these three as they are the most interesting.

SSE Main Build this simply builds the application in its entirety. It runs every 30 seconds
looking for any new code that has been checked into source control.

SSE-NightlyBuild creates a version of the application that is the latest build which can be run on
the server itself. It also performs all unit tests. This runs at 1am every day.

SSE-Documentation simply creates all the documentation from the comments.xml files created
when each assembly is built. This relies on the developer adequately commenting their code
using Xml comments and predefined tags preceding any method or property.

You can choose to view as many builds as you wish and they do not have to be on the same
CruiseControl.net server. To do this select Settings by right clicking on the CCTray icon:
CRUISE CONTROL.NET

Now you can add a CruiseControl.net server and any builds it has that you wish to monitor.

If any or all of the builds are currently building, the icon changes colour to orange. When a build
is complete the icon is either green for successful or red when there has been an error. The same
colour keys are used in the Cctray window itself.

Build Configuration - Nant

NAnt
NAnt (& Ant) is an automated build tool that enables you to perform all kinds of different build-related
tasks. It should not replace but rather enhance the IDE (VS.NET). NAnt is a free .NET build tool based
on Ant (a build tool for Java). NAnt, like Ant, is similar to make in that it is used to generate output from
your source files. But where Ant is Java-centric, NAnt is .NET-centric. NAnt has built-in support for
compiling C#, VB.NET, and J# files and can use Visual Studio .NET solution files to do builds. NAnt also
has built-in support for NUnit and NDoc (.NET version of JUnit and JDoc, respectively).

NAnt is a useful tool for automating the build process. The build process can include tasks such as
compiling source code and resource files into assemblies, running unit tests, configuring build-specific
settings, and so on. The benefit of tools like NAnt is that they help automate the build process by
providing enough power and flexibility to highly customize build actions for specific applications.

1. Fast and easy to run (simply type nant on the command line)
2. The concept of build files that specify the build procedure. These files are XML files
which potentially gives you platform-independence.
3. Includes a lot of predefined tasks (NAnt and NAntContrib distributions)
4. Extensible: if something is missing you can simply write your own tasks.

NAnt defines a recipe or procedure for composing the program.

What is this thing you call Build Tool?

A “build tool” is a tool that you use to build your source code and resources files into assemblies. We use
build tools everyday in development. Here are some tasks that are performed during the “entire” build
process:
CRUISE CONTROL.NET

• Get latest source code from source code control (SVN/VSS/CVS).

• Configure the build (put files in specific folders based on build number).

• Compile the code

• Run Unit Tests

• Create Documentation from the source code comments

• Include non-code output files in the output of the build (images, database files, config files, etc...)

• Package the output for deployment

NAnt is different. Instead of a model where it is extended with shell-based commands, NAnt is extended
using task classes. Instead of writing shell commands, the configuration files are XML-based, calling out
a target tree where various tasks get executed. Each task is run by an object that implements a particular
Task interface.

The system requirements are pretty obvious and simple. To use Nant you need one of the following
CLR’s:

• Microsoft .NET Framework 1.0

• Microsoft .NET Framework 1.1

• Microsoft .NET Framework 2.0

• Mono 1.x

We will instruct CruiseControl.NET to run a Nant task by adding a CruiseControl.NET Nant


Task Block.
Such block lets us instruct CruiseControl.NET to execute Nant and lets us specify a Nant build
file and the list of Nant targets to execute.
Remember that we named the build file: nant. Build and we placed it in the directory:
C:\develop\CCnet.
Now we provide this information to the CruiseControl.NET Nant Task Block as shown in the
following example:

Example:
<nant>
CRUISE CONTROL.NET

<executable>c:\fromcvs\myrepo\myproject\tools\nant\nant.exe</executable>
<baseDirectory>c:\fromcvs\myrepo\myproject</baseDirectory>
<buildArgs>-D:cvs.executable=c:\putty\cvswithplinkrsh.bat</buildArgs>
<nologo>false</nologo>
<buildFile>cruise.build</buildFile>
<logger>My.Other.XmlLogger</logger>
<targetList>
<target>run</target>
</targetList>
<buildTimeoutSeconds>1200</buildTimeoutSeconds>
</nant>

Configuration Elements:
Node Description Type Required Default
executable The path of the version of nant.exe string false nant.exe
you want to run. If this is relative,
then must be relative to either (a)
the base directory, (b) the CCNet
Server application, or (c) if the path
doesn't contain any directory details
then can be available in the system
or application's 'path' environment
variable
baseDirectory The directory to run the NAnt string false Project Working
process in. If relative, is a Directory
subdirectory of the Project Working
Directory
buildFile The name of the build files to run, string false no build file specified
relative to the baseDirectory. (NAnt will use the
default build file in the
working directory)
buildArgs Any arguments to pass through to string false no args specified
NAnt (e.g. to specify build
properties)
nologo Whether to use the -nologo Boolean false true
argument when calling NAnt
logger The NAnt logger to use. If you are string false NAnt.Core.XmlLogger
using a version of NAnt prior to
0.8.3, you may need to specify this
CRUISE CONTROL.NET

as SourceForge.NAnt.XmlLogger.
buildTimeoutSeconds Number of seconds to wait before int false 600 (10 minutes)
assuming that the process has hung
and should be killed.
targetList A list of targets to be called. string list false no targets specified
CruiseControl.NET does not call (NAnt will use the build's
NAnt once for each target; it uses default target
the NAnt feature of being able to
specify multiple targets.
description If filled in, this will be shown in the string false n/a
build stage as the process name

NAnt output in Xml
CruiseControl.NET expects NAnt to generate its output as Xml so that the build results can be parsed and 
rendered appropriately. To accomplish this, CruiseControl.NET will, by default, launch NAnt using the 
"­logger: NAnt.Core.XmlLogger" argument. If you want to override this behavior, specify the logger 
property in the NAntBuilder configuration in the CCNet.config file. If this element is specified but is empty 
then NAnt will be started with the default logger (though this may cause some problems for CCNet). It is 
also possible to instruct NAnt to log its output to an Xml file and then merge the file into the build using the 
File Merge Task.

NOTE: the configuration of which NAnt logger to use was originally specified in the ccnet.exe.config 
file. This has now been deprecated, and the "NAnt. Logger" element in the <appSettings> section can 
now be removed.

NUnit and NAnt


CruiseControl.NET uses xml to process the build log and produce html for display on the web page. Since 
xml is so easy to parse the nunit2 task in NAnt can produce xml output. The tasks must be configured to 
do that in order for test results to show up on the web page. Typically this is done by adding a formatter 
element to the nunit2 task and setting the type to be "Xml". Additionally the usefile flag of the formatter 
element must be set to "false". If it isn't the nunit2 task will try and save the output to a file and not write it 
out to the build log.

<target name="test.unit" depends="compile" description="runs unit tests">


<nunit2>
<formatter type="Xml" usefile="false"/>
<test assemblyname="${build.dir}\${core.dll}" fork="true"/>
<test assemblyname="${build.dir}\${console.exe}" fork="true"/>
</nunit2>
CRUISE CONTROL.NET

</target>
It would be pretty tedious for developers to read the xml output when they run the build locally. Define a 
property for the build output type and set it to "Plain" and use the property in the formatter element...

<property name="outputType" value="Plain"/>


...
<formatter type="${outputType}" usefile="false"/>
...

Then in the CCNet.config file pass in a different value for outputType.
<nant>
...
<buildArgs>"-DoutputType=Xml"</buildArgs>
...
</nant>

Accessing CruiseControl.NET build labels in NAnt
CCNet will pass the current build label to NAnt via the NAnt property CCNetLabel. This means that you
can access use this property to, for example, archive the newly built assemblies in a folder with the same
name as the build label (this is what we do on CCNetLive). Here's some example NAnt script
demonstrating how to do this:
<target name="dist.publish" depends="dist">
<ifnot propertyexists="CCNetLabel">
<fail message="CCNetLabel property not set, so can't create labelled distribution
files" />
</ifnot>
<property name="publish.dir" value="D:\download-area\CCNet-Builds\${CCNetLabel}" />

<mkdir dir="${publish.dir}" />


<copy todir="${publish.dir}">
<fileset basedir="dist">
<includes name="*"/>
</fileset>
</copy>
</target>
CRUISE CONTROL.NET

Integration Properties
The following parameters are passed to NAnt as command­line arguments:

Label  Description  Example 

CCNetBuildCondition  The condition  Force Build 


used to trigger the 
build, indicating if 
the build was 
triggered by new 
modifications or if 
it was forced. 
Legal values are: 
"IfModificationExis
ts" or "Force 
Build" 

CCNet  The status of the  Success 


IntegrationStatus  current 
integration. Could 
be Success, 
Failure, Exception 
or Unknown 

CCNetLabel  The label used to  1.0.2.120 


identify the CCNet 
build. This label is 
generated by the 
CCNet labeler. 

CCNetLastIntegration The status of the  Success 


Status  previous 
integration. Could 
be Success, 
Failure, Exception 
or Unknown 

CCNetProject  The name of the  MyProject 


CCNet project that 
is being 
integrated. 

CCNetBuildDate  The date of the  2005­08­10 


build (in yyyy­MM­
dd format) 
CRUISE CONTROL.NET

CCNetBuildTime  The time of the  08:45:12 


start of the build 
(in HH:mm:ss 
format) 

CCNetArtifactDirector The project  c:\program


y  artifact directory  files\CruiseControl.NET\Server\MyProject\Artifa
cts 
(as an absolute 
path) 

CCNet  The project  c:\program


WorkingDirectory  working directory  files\CruiseControl.NET\Server\MyProject\Workin
gDirectory 
(as an absolute 
path) 

CCNetRequestSource  The source of the  Interval Trigger 


integration 
request; this will 
generally be the 
name of the 
trigger that raised 
the request. 
(Added in CCNet 
1.1) 

CCNetFailureUsers  The list of users  John, Smith


who have 
contributed 
modifications to a 
sequence of 
builds that has 
failed. 

CCNetListenerFile  Viewing build  c:\Project\Artifact\listener.xml 


progress with 
Nant and MSBuild 
(Added in CCNet 
1.4) 

CCNetProjectUrl  The URL where  http://myhost/ccnet/server/ 


the project is 
located 

CCNetNumericLabel  Contains the label  1 
as an integer if 
conversion is 
CRUISE CONTROL.NET

possible, 
otherwise zero. 

CCNetModifyingUsers  The list of users  Smith


who have 
contributed to the 
current build only 

CCNet build from Nant script


Sometimes (e.g.: if you want to build a list of projects in sequence) it can be convenient to trigger builds 
from a NAnt script.

For that purpose one can use the launchccnetbuild NAnt task (source available here: 
LaunchCruiseControlBuildTask.cs).

using System;
using System.Runtime.Remoting;
using System.Threading;
using NAnt.Core;
using NAnt.Core.Attributes;
using ThoughtWorks.CruiseControl.Remote;

namespace LoGeek.BuildServer.CustomTasks
{
/// <summary>
/// A NAnt task to launch a build on a CCNet server.
/// </summary>
[TaskName("launchccnetbuild")]
public class LaunchCruiseControlBuildTask : Task
{
#region Private Instance Fields

private string _serverUrl;


private string _projectName;
private int _timeOutInSeconds = 30*60;
private int _pollingIntervalInSeconds = 5;
private ICruiseManager _cruiseManager;

#endregion Private Instance Fields

#region Public Instance Properties

[TaskAttribute("serverurl", Required=true)]
public string ServerUrl
{
get { return _serverUrl; }
CRUISE CONTROL.NET

set { _serverUrl = value; }


}

[TaskAttribute("projectname", Required=true)]
public string ProjectName
{
get { return _projectName; }
set { _projectName = value; }
}

/// <summary>
/// Time out in seconds. Default to 1800 seconds (30 minutes)
/// </summary>
[TaskAttribute("timeoutinseconds", Required=false)]
public int TimeOut
{
get { return _timeOutInSeconds; }
set { _timeOutInSeconds = value; }
}

/// <summary>
/// Polling interval in seconds. Default to 5 seconds.
/// </summary>
[TaskAttribute("pollinginterval", Required=false)]
public int PollingInterval
{
get { return _pollingIntervalInSeconds; }
set { _pollingIntervalInSeconds = value; }
}

#endregion Public Instance Properties

#region implementation of Task

protected override void ExecuteTask()


{
Log(Level.Info, "Connecting to CCNet server " +
ServerUrl);
_cruiseManager = (ICruiseManager)
RemotingServices.Connect(typeof (ICruiseManager), ServerUrl);

IntegrationStatus status = LaunchBuild(_cruiseManager,


ProjectName, PollingInterval, TimeOut);
if (status != IntegrationStatus.Success)
throw new BuildException(string.Format("Project
'{0}' failed : {1}", ProjectName, status));
}

#endregion

/// <summary>
/// Return the current status of the project. Return null if
the project does not exist.
/// </summary>
private ProjectStatus GetCurrentProjectStatus(ICruiseManager
cruiseManager, string name)
CRUISE CONTROL.NET

{
ProjectStatus[] allStatus =
cruiseManager.GetProjectStatus();
foreach (ProjectStatus status in allStatus)
{
if (status.Name == name)
return status;
}
return null;
}

public IntegrationStatus LaunchBuild(ICruiseManager


cruiseManager, string projectName, int pollingIntervalInSeconds, int
timeOutInSeconds)
{
ProjectStatus status =
GetCurrentProjectStatus(cruiseManager, projectName);
if (status == null)
throw new BuildException(string.Format("Project
'{0}' not found on the build server.", projectName));

if (status.Activity != ProjectActivity.Sleeping)
throw new BuildException(string.Format("Project
'{0}' activity is '{1}' instead of expected '{2}'", projectName,
status.Activity, ProjectActivity.Sleeping));

Log(Level.Info, "Forcing build for project '{0}'",


projectName);
cruiseManager.ForceBuild(projectName);

DateTime startTime = DateTime.Now;


TimeSpan timeout = new TimeSpan(0, 0,
timeOutInSeconds);
while (true)
{
TimeSpan elapsed = DateTime.Now - startTime;
if (elapsed >= timeout)
throw new
BuildException(string.Format("Project '{0}' build timed-out (lasted more than
{1} seconds)", projectName, timeOutInSeconds));
Thread.Sleep(pollingIntervalInSeconds*1000);
// check current integration status to decide
what to do
status = GetCurrentProjectStatus(cruiseManager,
projectName);
switch (status.Activity)
{
case ProjectActivity.Building:
// fine, keep it rolling
break;
case
ProjectActivity.CheckingModifications:
// fine
break;
case ProjectActivity.Sleeping:
CRUISE CONTROL.NET

// the build is finished (may be


successful or have failed)
return status.BuildStatus;
default:
throw new
Exception(string.Format("Unknown ProjectActivity '{0}'",status.Activity));
}
}
}
}
}

Example:
<launchccnetbuild serverurl="tcp://buildserver:21234/CruiseManager.rem" projectname="myproject" />
The task works synchronously: it polls the server periodically to check a given project status. A build
exception is raised if the build times out or is not successful (although this behavior could easily be
altered).
To build a list of projects sequentially and stop the script whenever one project fails to build, you can use
something like :
<target name="build. all">
<property name="serverurl" value="tcp://buildserver:21234/CruiseManager.rem" />
<launchccnetbuild serverurl="${serverurl}" projectname="myproject" />
<launchccnetbuild serverurl="${serverurl}" projectname="mysecondproject" />
<launchccnetbuild serverurl="${serverurl}" projectname="mythirdproject" />
</target>

Configuration Elements:
Attribute  Description  Type  Required Default 

serverurl  The url of the remote CruiseControl.Net server hosting the  string  true  N/A 


project. 

projectname  The name of the project to build.  string  true  N/A 

timeoutinseconds  After that amount of time, a build exception will be raised.  int false  1800 

pollinginterval  How many seconds between each project status check.  int  false  5 

NUnit Task

The second Task Block that you find in the xml fragment above is an Executable Task used to
instruct CruiseControl.NET to run unit tests with NUnit.
CRUISE CONTROL.NET

At first I tried to use a NUnit Task Block but I soon realized that it was not good for me because
it was not possible to provide arguments to the task that should be used as arguments of the
NUnit command-line executable.

This is a problem because there’s no way to let the NUnit task be aware of NUnit categories.
For those who don’t know, NUnit lets you specify a ‘Category‘attribute in test methods, with the
following syntax:

1.
2. [Test]
3. [Category("Long Running")]
4. public void VeryLongTest()
5. { /* ... */ }

This attribute allows you to instruct NUnit to treat all the methods belonging to the same
category in the same way.
Usually what we want to do is to exclude a cluster of tests from running.
Typically we exclude tests that take too much to run, using the following syntax with the NUnit
command-line tool:

nunit-console.exe /exclude:LongRunning,AnotherCategoryName

You can configure excluded categories in NUnit GUI as well, by clicking the ‘Categories‘ tab in
the top left corner.
A list of available categories will be shown. Just select the categories of interest and click the
Add button.
Then check the Exclude these categories checkbox at the bottom of the page and run the NUnit
project.

It is very useful to be able to exclude some categories of tests from the continuous integration
environment, still being able to run them on developer machines.

This is the reason why I recently submitted a patch to CruiseControl.Net adding support for
NUnit categories.
It’s not included in the official release yet, because I submitted it too late for this purpose.
However you can find it in the current build which is publicly available at: CCNetLive. The
patch is included starting from build: 3591.
So now you have two chances to use categories:

1. If you really want to use the last officially released version, read the paragraph 11.2 about how to
use an Executable Task (the method described can be useful also if you want to use any other
unsupported Nunit command line argument);
2. Instead if you can download the latest build from ccnetlive you will be able to specify categories
inside the Nunit Task block, as explained in paragraph 11.1
CRUISE CONTROL.NET

Nunit Task

If you downloaded the most recent build and followed the installation instructions (see: 3.
Installation) you can go on reading this paragraph.
If you installed the official release or a build older than 1.4.0.3591, you can still modify your
installation with the following instructions:

download the zipped package (here) or source code. Unzip it in a temporary directory and locate
the assembly: ThoughtWorks.CruiseControl.Core.dll (which, for the zip package, is in the
directory: ’server’).
Copy and replace it to the original one in your CCNET installation directory (back up the
original one first) that should be: Program Files\CruiseControl.NET\server.

That’s it! Now you can use the CruiseControl.NET’s Nunit Task Block also for specifying Nunit
categories (see: Nunit categories for reference).

It is possible to specify a list of the categories of tests that we want to be excluded.


It is possible, as well, to specify a list of the only categories that we want to be included as
allowed by the Nunit Command-line or GUI interface.
The configuration syntax for the Nunit task becomes:

view plaincopy to clipboardprint?

1.
2. <nunit>
3. <path>C:\Program Files\NUnit 2.4.7\bin\nunit-console.exe
4. </path>
5. <assemblies>
6. <assembly>Dummy.sln.nunit</assembly>
7. </assemblies>
8. <excludedCategories>
9. <excludedCategory>LongRunning</excludedCategory>
10. <excludedCategory>Category 2</excludedCategory>
11. </excludedCategories>
12. </nunit>

for excluded categories, or:

view plaincopy to clipboardprint?

1.
2. <nunit>
3. <path>C:\Program Files\NUnit 2.4.7\bin\nunit-console.exe
4. </path>
5. <assemblies>
6. <assembly>Dummy.sln.nunit</assembly>
7. </assemblies>
8. <includedCategories>
CRUISE CONTROL.NET

9. <includedCategory>LongRunning</includedCategory>
10. <includedCategory>Category 2</includedCategory>
11. </includedCategories>
12. </nunit>

for included categories. You can find the official reference at this page on the official website.

The Nunit task output log file is automatically integrated in the CCNET build results.
So you don’t need to specify the Merge task (needed if you use the procedure explaine in
paragraph 11.2 instead of this one) in the Publishers block as explained in paragraph 12:

view plaincopy to clipboardprint?

1.
2. <merge>
3. <files>
4. <file>..\project1CCnetArtifacts\nunit-results.xml</file>
5. </files>
6. </merge>

Instead you still need to delete the previous Nunit log file before each build process as explained
in the paragraph 13 - PreBuild Block.

→ top of post
→ top of paragraph

11.2. Executable Task

If you’re working with the official release of CruiseControl.Net (release 1.4) Nunit Task Block
syntax only allows you to specify the target solution and little more. In our example it would be:

view plaincopy to clipboardprint?

1.
2. <nunit>
3. <path>C:\Program Files\NUnit 2.4.7\bin\nunit-console.exe
4. </path>
5. <assemblies>
6. <assembly>Dummy.sln.nunit</assembly>
7. </assemblies>
8. </nunit>

where Dummy.sln.nunit is the Nunit project file for our solution.

The solution I strongly suggest is to replace the Nunit Task with an Executable Task like the one
shown below:

view plaincopy to clipboardprint?


CRUISE CONTROL.NET

1.
2. <exec>
3. <executable>
4. C:\Program Files\NUnit 2.4.7\bin\nunit-console.exe
5. </executable>
6. <buildArgs>/xml:..\project1CCnetArtifacts\nunit-results.xml
7. /nologo Dummy.sln.nunit
8. /exclude:LongRunning,AnotherCategoryName
9. </buildArgs>
10. </exec>

You only need to specify the full path to the Nunit command-line executable file in the
<executable> field and the command-line arguments in the <buildArgs> field.

In the <buildArgs> field you specify arguments as if provided directly to nunit-console.exe:

1. specify the path to the file in which nunit will write its output:
/xml:..\project1CCnetArtifacts\nunit-results.xml.
The file should be produced in the artifactDirectory of the current CCNET project.
By default the executable run by an executable task is run in the Project Working Directory, so
the path to the output file is relative to such directory.
2. You can pass many things as Nunit targets (assemblies, Visual Studio projects or Nunit project
files). I suggest creating an Nunit project and passing it as argument to nunit-console.exe as
shown in the sample above (where the nunit project file is called: Dummy.sln.nunit).
3. you can then add: /exclude:LongRunning,AnotherCategoryName thus excluding unwanted tests.

Specifying the name of the output file is not enough.


In order to make the output written by nunit in the file nunit-results.xml (arbitrary name specified
in the buildArgs tag), available to CruiseControl.NET we need to use a File Merge Task.
If we used Nunit task the output file would have been automatically merged with other output for
CruiseControl.NET.
Using the Executable Task we need to explicitly configure CruiseControl.NET to merge the
Nunit output file in the log file parsed by CruiseControl.NET.
We will tell CruiseControl.NET to do it at the end of the build process, namely in the Publishers
section.

Build Configuration - MSBuild

MsBuild Task

The <msbuild> task is used to execute MsBuild projects, which are the default project format for Visual
Studio 2005 projects and can also be compiled by using the MSBuild application that ships with the .NET
2 Framework.
CRUISE CONTROL.NET

In order to work with the results of MsBuild it is important to use a custom xml logger to format the build
results.

Let’s have a look at the meaning of the xml nodes children of the <msbuild> node:

<executable>: contains the path to the msbuild executable file. You don’t really need to set it
because the default value is the standard installation path:
C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\MSBuild.exe.

<workingDirectory>: is the directory in which MsBuild will be run, so it must be the directory
containing our projects checked out working copy. You can provide a path relative to the current
project’s workingDirectory. Actually, the path to the CCNET checked out working copy is the
same as the <workingDirectory> field of the Source Control Block.

<projectFile>: is the name of the project to build. MsBuild accepts a Visual Studio solution file
as the project file to build. Obviously the MsBuild Task accepts it as well.

<buildArgs> This row provides additional command line arguments to MsBuild. We tell it not to
log events to the console (/noconsolelogger), to build the Debug configuration
(/p:Configuration=Debug) and to provide a reduced output (/v:quiet).
As far as the /p:ReferencePath buildArg is concerned it is worth to talk extensively about a
problem that could arise with Nunit, so have a look at paragraph 10.1.

1.1 MSBuild and ReferencePath - CruiseControl.NET not resolving reference to


Nunit

It could happen that CCNET is not able to locate Nunit (or some other dependency assembly)
depending on how your project file has been created by Visual Studio.
Open your project file (DummyProject.csproj) with a text editor (e.g.: Notepad++). If you find
an entry as follows in it:

view plaincopy to clipboardprint?

1.
2. <Itemgroup>
3. <Reference Include="nunit.framework, Version=2.4.7.0,
4. Culture=neutral, PublicKeyToken=96d09a1eb7f44a77,
5. processorArchitecture=MSIL" />
6. ....
7. </Itemgroup>

with no <HintPath> associated to the Nunit <Reference> it could be that CCNET will not be able
to resolve that reference if you don’t register nunit.framework.dll in the server’s GAC.
CRUISE CONTROL.NET

You can make sure that CCNET is able to resolve the dependency by providing an alternative
search path in which to look for.
Each assembly referenced in the Visual Studio project files needs to be located by MSBUild at
compile time.
The location of the referenced assemblies is resolved by MSBuild by looking in several locations
in a particular search order (as explained here).
We could modify the .csproj file by providing a value as a child node of the node, e.g.:

view plaincopy to clipboardprint?

1.
2. <Reference Include="DummyLibrary, Version=1.0.0.0,
3. Culture=neutral, processorArchitecture=MSIL">
4. <SpecificVersion>False</SpecificVersion>
5. <HintPath>..\..\CommonReferencedDLLs\DummyLibrary.dll
6. </HintPath>
7. </Reference>

This approach has two drawbacks:

1. the hintpath is a relative path, thus making the build success depend on the location of the project
relative to the referenced assembly (this could be a problem if we reference an external
assembly);
2. we need to modify each Visual Studio project file by hand and we don’t want to do it!

Fortunately there’s an easy way out:


We can override all the project specific settings for path resolving by passing a ReferencePath
property from the MSBuild command line.
Such property accepts as value a list of paths (MSBuild DummySolution.sln
/p:”ReferencePath=<Path1;Path2;Path3>”) and it is checked by the build process before
checking other locations (HintPath for example).
So the way to provide an alternative search path from the command line is to pass as argument a
ReferencePath property.
This is the reason why the command line provided in the <buildArgs> field contains the
ReferencePath property pointing to the Nunit install path:
/p:ReferencePath=”C:\Program Files\NUnit 2.4.7\bin”.

Let’s go on with the analysis of the xml nodes children of the <msbuild> node:

<targets> specifies which targets to build in this msbuild project file. It represents the MSBuild
/target command line argument. We set it to Rebuild (clean and build).
CRUISE CONTROL.NET

<timeout> is the number of seconds before assuming that the process has hung. If timeout is
exceeded the process will be killed.

<logger> specifies the path to the assembly containing the logger to use to format the log output
of MSBuild .
If you don’t want to use the alternative logger that I used in the configuration shown above, you
can rely on the default logger as explained here and skip the following

To use the default logger:

• leave out the <logger> field,


• download the assembly containing the default xml logger here (find info here),
• copy the downloaded assembly (ThoughtWorks.CruiseControl.MSBuild.dll) to the folder:
C:\%ProgramFiles%\CruiseControl.NET\server.

I suggest using the alternative logger (by Christian Rodemeyer) as explained in the following
paragraph. The RodeMeyer’s logger provides lighter msbuild output and his modified stylesheets
provide much more readable display of such information.

1.2. An Alternative MSBuild Logger - Christian Rodemeyer’s MsBuildToCCNet

I chose to use a logger alternative to the default one: Christian Rodemeyer’s MsBuildToCCNet.
You can find it at: Improved MSBuild Integration. From there either you can download
separately the assembly and all related stuff needed to correctly display the results from
Rodemeyer’s logger or you can download a zip file with the whole project and source code.

In the page cited above you can find detailed instructions on how the logger works and how it
should be configured.
In the current paragraph I’ll illustrate the installation process and add some useful tips for
making it work.
I suggest downloading the full project that comes in a zip file named: MsBuildToCCNet.zip
(download here).
Unzipping the package you will have a directory named: MsBuildToCCNet. Inside this directory
you will find, among the rest, a directory named Release, containing the assembly:
Rodemeyer.MsBuildToCCnet.dll.
Just copy the assembly to the \CruiseControl.NET\server folder (e.g.: c:\Program
Files\CruiseControl.NET\server\).
There’s another subdirectory of the MsBuildToCCNet folder, named ccnet where you can find
the resources needed to correctly display the logs produced by Rodemeyer’s logger. Those
resources are:
cruisecontrol.css and
msbuild2ccnet.xsl.

You need to use those two files and to configure the Webdashboard:
CRUISE CONTROL.NET

1. Move into your CruiseControl.NET Webdashboard folder, under the path:


C:\%ProgramFiles%\CruiseControl.NET\webdashboard (e.g.: c:\Program
Files\CruiseControl.NET\webdashboard\) and back up the file: cruisecontrol.css.
Then replace it with the cruisecontrol.css file you found in the Rodemeyer’s MsBuildToCCNet
folder (e.g.: copy MsBuildToCCNet\ccnet\cruisecontrol.css to c:\Program
Files\CruiseControl.NET\webdashboard\cruisecontrol.css);
2. There’s a subdirectory of the CruiseControl.NET Webdashboard folder, named: xsl.
You need to copy the other resource (msbuild2ccnet.xsl) you found in the
MsBuildToCCNet\ccnet folder in that directory:
C:\%ProgramFiles%\CruiseControl.NET\webdashboard\xsl\;
3. You need to modify the dashboard. Config file in the CruiseControl.NET Webdashboard folder
in order to correctly show the output of the logger.
Being that we’re talking about the Webdashboard configuration I will show you all the changes
you will need to do to let it work with the following three components (even if we’ll see two of
them only in the following paragraphs):
o MsBuildToCCNet
o Nunit integration
o FxCop integration

First of all choose a 32 x 32 jpg image representing a smiling icon and place it in the
CruiseControl.NET Webdashboard folder:
C:\%ProgramFiles%\CruiseControl.NET\webdashboard.
Rename the image file: your_happy_image.jpg and, when a new build succeeds, you’ll
obtain a smiling icon in the Webdashboard report! (you can find a sample image here).
Then open CruiseControl.NET\webdashboard\xsl\msbuild2ccnet.xsl and go to line 24:

view plaincopy to clipboardprint?

1.
2.<xsl :if test="@error_count = 0 and @warning_count = 0">
3.<tr>
4.<td><img src="/ccnet/your_happy_image.jpg"
5. alt="Happy Image <IMG class=wp-smiley alt=:-) src="http://s.wordpress.com/wp-
includes/images/smilies/icon_smile.gif"> " /> Juchuu !!!</td>
6.</tr>
7.</xsl>

replace the img src attribute: /ccnet/your_happy_image.jpg with /your_happy_image.jpg


if you configured iis with a new website for the webdashboard instead of a virtual
directory. If you’re usign the default virtual directory named ccnet, don’t modify that
row.
Next you need to locate the field: <buildPlugins> in
C:\%ProgramFiles%\CruiseControl.NET\webdashboard\dashboard.config and arrange or
delete its children nodes in order to obtain the following configuration (remember to back
up the file first):

view plaincopy to clipboardprint?


CRUISE CONTROL.NET

8.
9.<buildplugins>
10. <buildreportbuildplugin>
11. <xslfilenames>
12. <xslfile>xsl\header.xsl</xslfile>
13. <xslfile>xsl\modifications.xsl</xslfile>
14. <xslfile>xsl\msbuild2ccnet.xsl</xslfile>
15. <xslfile>xsl\unittests.xsl</xslfile>
16. <xslfile>xsl\compile.xsl</xslfile>
17. <xslfile>xsl\fxcop-summary.xsl</xslfile>
18. </xslfilenames>
19. </buildreportbuildplugin>
20. <buildlogbuildplugin />
21. <xslreportbuildplugin description="NUnit Details"
22. actionName="NUnitDetailsBuildReport"
23. xslFileName="xsl\tests.xsl" />
24. <xslreportbuildplugin description="NUnit Timings"
25. actionName="NUnitTimingsBuildReport"
26. xslFileName="xsl\timing.xsl" />
27. <xslreportbuildplugin description="FxCop Report"
28. actionName="FxCopBuildReport"
29. xslFileName="xsl\FxCopReport.xsl" />
30.</buildplugins>

As you can see, such configuration includes also stylesheet files for nunit and fxcop
integration. We will soon configure the server to integrate those components.

While adding the smiling image in the previous paragraph we had to change the path in the xsl
file.
The same problem could arise with other stylesheet files if you configured the webdashboard to
be a website instead that a virtual directory named ccnet.
Have a look at the next paragraph for details:

1.3. CruiseControl.NET Webdashboard Fails in Finding Images if Not Installed in


Virtual Directory

If you unchecked ‘Create virtual directory in IIS for Web dashboard’ as shown in part 1 of this
tutorial at 3.1. Install CruiseControl.NET and installed the Webdashboard as a new website as
shown in the paragraph: 3.2. Create a CCNet Website in IIS, the webdashboard could have
problems in resolving image paths.
You will realize it as soon as you will configure the server to integrate nunit or fxcop (will see it
in following paragraphs).
To make sure not to have this problems you must modify the following files:
xsl\tests.xsl
xsl\fxcop-summary.xsl
under: C:\%ProgramFiles%\CruiseControl.NET\webdashboard\
CRUISE CONTROL.NET

you have to replace all the paths relative to the root of the website with relative paths, e.g:

in the file: xsl\tests.xsl you should replace all entries like:

view plaincopy to clipboardprint?

1.
2. eImg.src = "<xsl :value-of select="$applicationPath"/>/images/arrow_minus_small.gif";

with:

view plaincopy to clipboardprint?

1.
2. eImg.src = "<xsl :value-of select="$applicationPath"/>images/arrow_minus_small.gif";

and entries like:

view plaincopy to clipboardprint?

1.
2. <img src="{$applicationPath}/images/fxcop-error.gif"/>

with:

view plaincopy to clipboardprint?

1.
2. <img src="{$applicationPath}images/fxcop-error.gif"/>

that is, you simply need to delete the leading ‘forward slash’ at the beginning of the path (just
before the ‘images’ folder name).

you need to accomplish the same task with the file xsl\fxcop-summary.xsl, e.g.:

you should replace entries like:

view plaincopy to clipboardprint?

1.
2. <xsl :attribute name="src"><xsl :value-of select="$applicationPath" />/images/fxcop-critical-
error.gif</xsl>

with:

view plaincopy to clipboardprint?


CRUISE CONTROL.NET

1.
2. <xsl :attribute name="src"><xsl :value-of select="$applicationPath" />images/fxcop-critical-
error.gif</xsl>

Actually, you should find all paths to images in those two files and delete the leading forward
slash.

Back to the MSBuildToCCNET alternative Logger for MsBuild, I will explain now why I
decided to recompile the source code instead of using the assembly provided:
MsBuildToCCNet\Release\Rodemeyer.MsBuildToCCnet.dll

1.4. MSBuildToCCNET Reports Wrong Number of Compiled Projects

I found that MsBuildToCCNet reported the wrong number of projects in the webdashboard in the
page reporting the details of the last build.
There’s a row that sounds like the following, displaied in that page:

‘15 Projects built with 2 warnings’

Looking at the source code (in the file: Logger.cs) I realized that the list of Project type
instances includes the solution file (DummySolution.sln) and a Project object named
“MSBuild“, somehow representing the MsBuild process.
Appearently this is the reason why the reported number of projects is wrong.
I still haven’t tried to contact the author so I don’t know very well how the Logger is supposed to
work as far as this count is concerned.
As a workaround I modified the following row:

1.
2. w.WriteAttributeString("project_count",
3. XmlConvert.ToString(projects.Count));

turning it into:

1.
2. w.WriteAttributeString("project_count",
3. XmlConvert.ToString(projects.Count - 2));

in the ‘WriteLog(XmlWriter w)’ method (file: Logger.cs at row 104).

This seems having fixed the problem with no side effects.

You could have problems running msbuild task if your server machine (the one in which you
installed CruiseControl.NET) is not updated with all the software installed in a developer
workstation. Let’s see which problems could arise:
CRUISE CONTROL.NET

1.5. CruiseControl.NET, MsBuild Task and Resources - Assembly Linker

If you want to provide localization for any of your projects or somehow use resources files
(.resx) you will get an error during the build on the CruiseControl.NET server if MsBuild is not
able to locate the Assembly Linker.
The error should look something like:

C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Microsoft.Common.targets(1950,9):
error MSB3011: “C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\AL.exe” was not
found. Either 1) Install the .NET Framework SDK, which will install AL.exe. Or 2) Pass the
correct location of AL.exe into the “ToolPath” parameter of the AL task.

AL.exe is used to produce the satellite assemblies and the executable file is placed in the .NET
framework directory.
But Al.exe is a .Net Framework SDK tool. It is not included in .Net Framework 2.0 runtime
installation.
You need to install the .NET framework SDK on the server machine if you don’t want to
encounter this problem.
If you want to solve this particular issue in a tricky way without installing the whole SDK, you
can copy al.exe.config e al.exe from a developer workstation and place them in the
C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727 directory on the server machine.
This is how I solved the problem but I suggest you to install the .NET framework SDK on the
server machine.

1.6. CruiseControl.NET, MsBuild Task and Web Application projects

A particular note is due for Web projects.


Updating Visual Studio 2005 you get the SP1. Together with the Service Pack 1 for Visual Studio
you get the WebApplication project template.
Such template lets us add a new kind of project to our solution: a web site project structured
exactly like any other Visual Studio project.
So you can quit creating new websites (File –> New –> Web Site…) and start creating new
WebApplication projects (File –> New –> Project… and then choose ‘ASP.NET Web
Application‘).

In order to use WebApplication projects you need to have Visual Studio installed on your
machine and the WebApplication project plugin (that comes with the Visual Studio 2005 SP1).
If the server in which CruiseControl.NET server is running is not a develpment workstation you
will get an error when trying to build a WebApplication project, beacuse you miss those two
prerequisites.

You can easily fix this problem: you simply need to copy the file:
Microsoft.WebApplication.targets that you can find under:
“C:\Program Files\MSBuild\Microsoft\VisualStudio\v8.0\WebApplications\”
from a development workstation and paste it to the corresponding path on the server machine
(creating the directories in the path if needed).
CRUISE CONTROL.NET

Build Configuration –Visual Studio


Most complex build processes use NAnt or MSBuild to script the build. However, for simple projects that
just need to build a Visual Studio.NET solution, the Visual Studio task <devenv> provides an easier
method.

Examples

Minimalist example:

<devenv>

<solutionfile>src\MyProject.sln</solutionfile>

<configuration>Debug</configuration>

</devenv>

Full example:

<devenv>

<solutionfile>src\MyProject.sln</solutionfile>

<configuration>Debug</configuration>

<buildtype>Build</buildtype>

<project>MyProject</project>

<executable>c:\program files\Microsoft Visual Studio .NET\Common7\IDE\devenv.com</executable>

<buildTimeoutSeconds>600</buildTimeoutSeconds>

<version>VS2002</version>

</devenv>

Configuration Elements:

Node Description Type Required Default

solutionfile The path of the solution filesstring true n/a


to build. If relative, it is
relative to the Project
CRUISE CONTROL.NET

Working Directory.

configuration The solution configuration string true n/a


to use (not case sensitive).

buildtype The type of build. Valid string false rebuild


values are Rebuild, Build
or Clean (not case
sensitive).

project A specific project in the string false The default is to build


solution, if you only want to all projects selected by
build one project (not case the configuration.
sensitive).

executable The path to devenv.com. string false (see below)

buildTimeoutSeconds Number of seconds to wait int false 600 (10 minutes)


before assuming that the
process has hung and should
be killed.

version The version of Visual One of VS2002, false (see below)


Studio. VS2003, VS2005,
VS2008, 7.0, 7.1,
8.0, or 9.0

description If filled in, this will be string false n/a


shown in the buildstage as
the process name

If executable and version are not specified, CC.NET will search the registry for VS.NET 2008, 2005,
2003, and 2002 in that order. If you need to use a specific version when a newer version is installed, you
should specify the version property to identify it, or specify the executable property to point to the
location of correct version of devenv.com.

Note: this task requires you to have Visual Studio .NET installed on your integration server.

Often programmers like to use a centralised project to build an entire software system. They define
specific dependencies and the build order on that specific project to reproduce the behaviours of an
nmake build.

Web Dashboard
CRUISE CONTROL.NET

Simple Installation
The simplest way to install the Web Dashboard is to use the CruiseControl.NET installer, as described in
the Basic Installation section. This should setup everything, resulting in a Dashboard instance being
viewable at the Virtual Directory /ccnet.
If something goes wrong, or you want more control, read the next section

Self-managed installation
Basic Installation:
CruiseControl.NET is distributed in 3 formats:
 Two Installers, one for CruiseControl.NET proper (the Server and Web Dashboard), and a
second for the optional CCTray utility. The Installers are conventional Windows installation
programs, which perform some useful early setup work for you, such as copying files to good
locations, setting up a Virtual Directory for the Dashboard, etc. For most people starting out, this
is the way to go.
 A binary zip file includes the same files as the installers but gives you more control over what
you can do with them.
 A source zip which allows you to read or make your own changes to the CruiseControl.NET
source code.
 The binary zip file will give you several sub-folders:
 /server: holds the assemblies for the CruiseControl.NET Server, including both the The Server
Console Application and The Server Service Application .
 /webdashboard: contains the ASP.NET Web Dashboard application
 /cctray: contains the assemblies for the CCTray application
 /doc: contains HTML documentation for CruiseControl.NET
 With the binary zip file, you will have to manually configure IIS if you want to use the Web
Dashboard, and you will have to manually install the service if you wish to run the Server that
way. This is in addition to the usual, such as adding shortcuts to the Start Menu if you wish.

Then, in your system's IIS Admin tool:


1. Map a virtual directory to the 'webdashboard' subfolder of your CCNet folder (typically called
ccnet)
2.In the configuration for this virtual directory, click the Configuration button of the Virtual
Directory tab
3.Click Add to add a new Application Mapping
4.In Executable, enter the location of the aspnet_isapi.dll file you use (look at the .aspx mapping as
an example. A typical value would c:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\aspnet_isapi.dll
for CruiseControl.NET release 1.2.1 or earlier, or
c:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll for later releases)
5.In Extension, enter .xml
CRUISE CONTROL.NET

6.Make sure Script engine is checked and Check that file exists is not checked
7.Click OK as necessary to save your changes
8.Under the Virtual Directory's Documents tab make sure that default.aspx is added as a default
document

Configuring the web dashboard


The Web Dashboard is configured through the dashboard.config file, a set of XSL Files, and a set of [style
sheets] (CSS files). In most cases this file will be found in the root of the Web Dashboard application. The
only deployment-specific configuration in the web. Config file is an optional appSetting which can
specify an alternative location for the dashboard.config file. If you want to use this behavior, set the
DashboardConfigLocation appSetting value to be the absolute path of your dashboard.config file.

The configuration file forms a tree of constructs, starting at the root element. The documentation for the
rest of this section is reference documentation for each of the types of constructs you can use.

Default Configuration
The dashboard.config file that ships with CruiseControl.NET will work with a default setup, i.e.
one where you are using a build server on the same machine as the Web Dashboard and haven't
changed any of the Remoting settings.

Monitoring Multiple Servers


It's easy to use a single IIS running the Web Dashboard to monitor multiple CruiseControl.Net
build servers. See the Servers Configuration Block.

Configuration elements
 Dashboard Configuration Block
 Plugins Configuration Block
• Build Log Build Plugin
• Build Report Build Plugin
• CCTray Download Plugin
• Custom templates
• Farm Report Farm Plugin
• Latest Build Report Project Plugin
• modificationHistoryProjectPlugin
• Multiple XSL Report Build Plugin
• Project Configurable Build Plugin
• Project Report Project Plugin
• Project Statistics Plugin
• projectConfigurationServerPlugin
• RSSFeedProjectPlugin
• Server Information Server Plugin
• Server Log Project Plugin
CRUISE CONTROL.NET

• Server Log Server Plugin


• Server Report Server Plugin
• View All Builds Project Plugin
• View Configuration Project Plugin
• ViewServerQueue Server Plugin
• XSL Report Build Plugin
• XSL Report Project Plugin
 Remote Services Configuration Block
 Servers Configuration Block

Dashboard Configuration Block :

The root tag in the Dashboard Configuration file is the <dashboard> tag.
The <dashboard> tag contains a <remoteServices> section and a <plugins> section.
Example:
<dashboard>
<remoteServices>
.
.
</remoteServices>

<plugins>
.
.
</plugins>
</dashboard>
Plugins Configuration Block:
The Web Dashboard comes pre-configured to use a default set of plugins. To change what plugins you
want to use for your CruiseControl.NET deployment, use the <plugins> section of the Dashboard
configuration.
The section is split up into 4 parts, representing the Farm, Server, Project and Build views available in the
Dashboard. Each section can be configured with any number of plugins. Most Build Plugins can be
configured just to be used for certain Projects.
Example:
<plugins>
CRUISE CONTROL.NET

<customTemplates>some_folder</customTemplates>
<farmPlugins>
.
.
</farmPlugins>
<serverPlugins>
.
.
</serverPlugins>
<projectPlugins>
.
.
</projectPlugins>
<buildPlugins>
.
.
</buildPlugins>
</plugins>

Build Log Build Plugin:


The Build Log Build Plugin shows you the XML log for a specific build. Initially it is viewed inline in an
HTML view, but there is also an option to download the raw XML form.
This is a Project Configurable Build Plugin.

Example
<buildLogBuildPlugin />

Configuration Elements

There is no configuration for this plugin.

Build Report Build Plugin:
The Build Report Build Plugin shows detailed output for a specific build. This report is generated by
applying a list of XSL transforms to the build's log file.
CRUISE CONTROL.NET

See XSL Files for a list of available XSL transforms.


This is a Project Configurable Build Plugin.

Example
<buildReportBuildPlugin>
<xslFileNames>
<xslFile>xsl\header.xsl</xslFile>
<xslFile>xsl\compile.xsl</xslFile>
<xslFile>xsl\unittests.xsl</xslFile>
<xslFile>xsl\modifications.xsl</xslFile>
<xslFile>xsl\fxcop-summary.xsl</xslFile>
</xslFileNames>
</buildReportBuildPlugin>

Configuration Elements

Node Description Type Required Default

xslFileName A list of <xslFile> tags, each one containing the path of an list of yes n/a
s XSL file relative to the root of the WebDashboard folder. strings

CCTray Download Plugin:

The CCTray Download Plugin adds a link to the dashboard to download the installer for CCTray.

Example
<cctrayDownloadPlugin />

Configuration Elements
There is no configuration for this plugin.

custom templates:
It is possible to change the templates that are used in the dashboard. By default the dashboard looks in the
/templates folder for the template to use. But, it is now possible to set a custom template location by
setting <customtemplates> in <plugins>.
CRUISE CONTROL.NET

When a template is requested it will first look in the location specified by <customtemplates>. If there is a
template in this folder it will use that template, otherwise it will use the template in the default location.

Templates
The following are some of the more commonly modified templates:

Template Description
SiteTemplate.vm The main site template.
This contains the header information (including links to the stylesheet and javascript),
plus the overall layout for each page.
TopMenu.vm The breadcrumbs for each page.
FarmSideBar.vm The side bar for the farm-level views.
ServerSideBar.vm The side bar for server-level views.
ProjectSideBar.vm The side bar for project-level views.
BuildSideBar.vm The side bar for build-level views.
ProjectReport.vm The main project details page - this displays the build history graph.
ProjectGrid.vm The main grid display - this is the list of all the projects, their current status and the
action buttons.

Note: The side bars contain all the actions from the plug-ins.

Themes
It is possible to build themes using the custom templates location. This normally involves adding a new
SiteTemplate.vm and a new stylesheet. SiteTemplate.vm needs to be modified to point to the new
stylesheet, plus any other theme changes.
Additionally, any of the other templates can be modified for a theme.

Farm Report Farm Plugin:

The Farm Report Farm Plugin shows you status information for all projects on all servers. If the
Dashboard cannot connect to any specific server then an errors table is shown detailing the problems.

Example
<farmReportFarmPlugin />

Configuration Elements
There is no configuration for this plugin.
CRUISE CONTROL.NET

Latest Build Report Project Plugin:

The Latest Build Report Project Plugin lists all available builds for a project.

Example
<latestBuildReportProjectPlugin/>

Configuration Elements
There is no configuration for this plugin.

modificationHistoryProjectPlugin:
This plugin shows all the modifications of a project. The newest builds are shown first.
The project must use the ModificationHistory Publisher to get results to show up.

Minimal Configuration
<projectPlugins>
< modificationHistoryProjectPlugin /> ....
</projectPlugins>
This is available from build 1.3.0.2981 onwards

Full Configuration
<projectPlugins>
< modificationHistoryProjectPlugin onlyShowBuildsWithModifications="true" /> ....
</projectPlugins>

Node Description Type Required Default

onlyShowBuildsWithModifications When true, builds without modifications bool false false


will not be shown

Multiple XSL Report Build Plugin:

The Multiple XSL Report Build Plugin shows detailed output for a specific build. This report is generated
by applying a list of XSL transforms to the build's log file. It also allows for end users create build reports
that combine existing XSL stylesheets in order. This was previously only available on the Build Report
CRUISE CONTROL.NET

Build Plugin.
See XSL Files for a list of available XSL transforms.
This is a Project Configurable Build Plugin.

Example
<xslMultiReportBuildPlugin description="Build and Test Details"
actionName="NUnitDetailsBuildReport">
<xslFileNames>
<xslFile>xsl\header.xsl</xslFile>
<xslFile>xsl\compile.xsl</xslFile>
<xslFile>xsl\unittests.xsl</xslFile>
</xslFileNames>
</xslMultiReportBuildPlugin>

Configuration Elements

Node Description Type Required Default

description The description that will appear for the Plugin in the string yes n/a
Dashboard

actionName A name for the action for this instance of the plugin. This string yes n/a
must be strictly alpha-Numerical with no spaces and
unique

xslFileName A list of <xslFile> tags, each one containing the path of an list of yes n/a
s XSL file relative to the root of the WebDashboard folder. strings

Project Configurable Build Plugin:


Most Build Plugins can be configured to be used only for certain projects. If they can be, it will say on
their own documentation page.
A Build Plugin by default will appear on the Build Plugins list for all projects, but you can specify either a
specific inclusion or exclusion list. These are described below. You cannot have both an inclusion and an
exclusion list (if you do, you will get a configuration exception.)

Example
The name of the plugin (myBuildPlugin) is just an example - it will actually be the name of the specific
type of Build Plugin you are using. Also, the other property shown (myBuildPluginsOwnProperty) is just
an example of where the plugin-specific properties would go.
CRUISE CONTROL.NET

By default, you don't have to specify either an <includedProjects /> or <excludedProjects /> section, in
which case your Build Plugin will be shown for all projects.
<myBuildPlugin myBuildPluginsOwnProperty="Something">
<includedProjects>
<projectName>My Project</projectName>
<projectName>My Other Project</projectName>
</includedProjects>
</myBuildPlugin>
OR
<myBuildPlugin myBuildPluginsOwnProperty="Something">
<excludedProjects>
<projectName>My Project</projectName>
<projectName>My Other Project</projectName>
</excludedProjects>
</myBuildPlugin>

Configuration Elements
Node Description Type Required Default
includedProjects A list of project names. If you use an string no empty lists for
OR <includedProjects> section the build plugin will list both sections,
excludedProjects only appear for those projects. If you use an plugin used
<excludedProjects> section the build plugin will for all
appear for all projects apart from the specified ones. projects.
In both cases, the project names must match exactly
to those specified in your build server config files,
including use of spaces and capital letters

Project Report Project Plugin:

The Project Report Project Plugin shows you summary details for a specific project. Part of these details
is any External Links you have specified in the project configuration.

Example
<projectReportProjectPlugin />

Configuration Elements

There is no configuration for this plugin.


CRUISE CONTROL.NET

Project Statistics Plugin:

The Project Statistics Plugin displays the statistics for the project. Since version 1.4 the graphs of Eden
Ridgway are incorporated into CCNet.

Example
<projectStatisticsPlugin xslFileName="xsl\statistics.xsl" /> <!-- the old statistics page of CCNet -->
<projectStatisticsPlugin xslFileName="xsl\StatisticsGraphs.xsl" /> <!-- the new statistics page with the
graphs of Eden, this is the default of CCNet now-->

Configuration Elements
Node Description Type Required Default
xslFileName The file containing the XSL transforms to use. The path is string yes n/a
relative to the root directory of the Web Dashboard

projectConfigurationServerPlugin:
This plugin shows the basic configuration of the projects on this buildserver.
Like project name, category, queue and queue priority, making it easier to spot conflicts in the queue
setup for this buildserver.

Example
<projectConfigurationServerPlugin/>

Configuration Elements
There is no configuration for this plugin.

RSSFeedProjectPlugin:
This publisher generates an RSS feed reporting the builds for a project.
The project must use the RSS Publisher to produce the data for the feed.
This is available from build 1.3.0.3011 onwards. The RSS icon will be displayed on the project page,
whenever a build is done with the Publisher. So there is no configuration to be done in the webdashboard
for this.
Should you want to remove the RSS icon from the project page, remove the RSS publisher from the
project,
and delete the RssData.xml file from the artifact folder.

Server Information Server Plugin:


CRUISE CONTROL.NET

The Server Information Server Plugin gives you information about a build server, for example the version
of CruiseControl.NET the build server is running.

Example
<serverInformationServerPlugin />

Configuration Elements

There is no configuration for this plugin.

Server Log Project Plugin:


The Server Log Project Plugin shows you recent activity that has been output to the server log for a
specific project. Read the Server Application Config File page for more help on build server logging.

Example
<serverLogProjectPlugin />

Configuration Elements

There is no configuration for this plugin.

Server Log Server Plugin:


The Server Log Server Plugin shows you recent activity that has been output to the server log for a
specific build server. Read the Server Application Config File page for more help on build server logging.

Example
<serverLogServerPlugin />

Configuration Elements

There is no configuration for this plugin.

Server Report Server Plugin:


The Server Report Server Plugin shows you status information for all projects on a specific server. If the
Dashboard cannot connect to the server then an errors table is shown detailing the problem.

Example
<serverReportServerPlugin />

Configuration Elements
CRUISE CONTROL.NET

There is no configuration for this plugin.

View All Builds Project Plugin:


The View All Builds Project Plugin lists all available builds for a project.

Example
<viewAllBuildsProjectPlugin />

Configuration Elements
There is no configuration for this plugin.

View Configuration Project Plugin:

The View Configuration Project Plugin shows the configuration for a project.

This plugin shows the entire configuration. From build 1.4.0.3737 onwards, passwords are
masked by default.
Should you want to check the passwords via the dashboard, set hidePasswords to false.

Example
<viewConfigurationProjectPlugin />

Configuration Elements
Element Description Type Required Default
hidePassword Hides(masks) the passwords of all sections that have password bool false true
s attributes.

ViewServerQueue Server Plugin:

This plugin shows the current state of the queues on the build server.

Example
<queueStatusServerPlugin/>

Configuration Elements
There is no configuration for this plugin.
CRUISE CONTROL.NET

Xsl Report Build Plugin:

The Xsl Report Build Plugin shows detailed output for a specific build using a configured XSL
Transform.
See XSL Files for a list of available XSL transforms and how to use your own transforms.
This is a Project Configurable Build Plugin.

Example
<xslReportBuildPlugin description="NUnit Details" actionName="NUnitDetailsBuildReport"
xslFileName="xsl\tests.xsl" />

Configuration Elements
CRUISE CONTROL.NET

Node

Description

Type

Required

Default

description

The
description
that will
appear for
the Plugin in
the
Dashboard

string

yes

n/a

actionName

A name for
the action
for this
instance of
the plugin.
This must
be strictly
alpha-
Numerical
with no
spaces and
unique

string

yes

n/a

xslFileName
CRUISE CONTROL.NET

Remote Services Configuration Block:

At this time the <remoteServices> tag just contains a <servers> section.


This section contains all the build servers that the Dashboard will visualize.
Example:
<remoteServices>
<servers>
.
.
</servers>
</remoteServices>

Servers Configuration Block:

The Dashboard needs to connect over the network to each of Build Servers you want to report on. If you
have changed any of the remoting configuration for your servers, you'll need those details now. (See
Server Application Config File for more details on configuring remoting and management URLs.)
To configure the dashboard, add a <server> tag for each CruiseControl.NET Server you want to monitor
to the <servers> section.

Example
<servers>
<server name="local" url="tcp://localhost:21234/CruiseManager.rem" allowForceBuild="true"
allowStartStopBuild="true" />
</servers>

Configuration Elements

<server> tags have the following syntax:

Node Description Type Required Default

name A referential name for the server - this must be unique string yes n/a
for each server monitored by the Dashboard
CRUISE CONTROL.NET

url The management URL for the Server string yes n/a

allowForceBuild Displays or hides the Force Build button on the Project bool no true
Dashboard page

allowStartStopBuil Displays or hides the Stop Build button on the Project bool no true
d Dashboard page. Stopping a build will stop the project's
triggers so that they will not trigger new builds until the
project is started again; this will not abort a build that is
in progress.

Using Web dashboard

Assuming you've set everything up OK, you should be able to view the default page in the Virtual
Directory you setup for your web application. The default page on CCNetLive is at
http://ccnetlive.thoughtworks.com/ccnet/, and you should see something similar.
CRUISE CONTROL.NET

What you are seeing here is the Farm View. There are 4 different views in the CCNet Web Application,
with increasingly narrower scope. Here's a brief description:
• Farm - shows all projects running on all servers. Drill down into a project by clicking on its name
• Server - shows all projects running on a server. From here you can also view the 'server log' (and later on
add projects to a server)
• Project - Shows a summary of the current state of a project, shows the recent builds, and allows project
configuration (to come later.) Drill down into a specific build by clicking on its name
• Build - This is the equivalent of the old CCNet [Project Report Web Application]. Here you can view the
results of a build in various ways (summary report, full log, FxCop results, etc.)
CRUISE CONTROL.NET

Developing webdashboard plugins:


The Web Dashboard supports custom plugins. This page is documentation for developing your own
Dashboard plugins.
First of all, you need to decide what type of plugin you are developing:
• A Farm Plugin is used when you have not specified any particular project or server to view. Farm plugins
therefore appear in the 'default' view of the Dashboard.
• A Server Plugin is used when you are looking at a specific server, but not any particular project.
• A Project Plugin is used when you are looking at a specific project, but not a particular build.
• A Build Plugin is used when you are viewing a specific build for a specific project.

Actions

About Actions

The CruiseControl.NET Web Dashboard includes its own Web Framework implementation. The
fundamental 'component' in this framework is an Action. An Action represents a specific interaction
between the application and a user. Some features require multiple actions, e.g. one Action to allow a user
to edit some fields, and then another to show the results of this.
Your Dashboard Plugin must include at least 1 Action. It can include more than 1, but only 1 will ever be
linked directly from the Dashboard menus (the others must be linked by your other actions.)

Implementing Actions
The Actions you write should implement ICruiseAction. This has one method on it:
• IResponse Execute(ICruiseRequest cruiseRequest)
The responsibility of an Action's Execute method is 'Given a request, generate a response'. The response
is the 'main panel' part of the Dashboard's UI.

Defining dependencies
The CruiseControl.NET Web Dashboard uses a Constructor Dependency Injection (CDI) pattern to enable
classes to define what types they are dependent on. The Dashboard API has a number of types you can
depend upon which can do things like return you the currently viewed build log. You can also specify
dependencies to your own types. It is recommended that you use interfaces to define responsibilities.
The Dashboard's CDI implementation does not currently allow for runtime configuration. It will use
sensible defaults where available. We plan on adding more configuration later.

How to start
To implement your own actions, it’s probably best to first look at the source code for the Dashboard's own
plugins. These are available in the ThoughtWorks.CruiseControl.WebDashboard.Plugins Namespace.

Support Class
CRUISE CONTROL.NET

Once you've written your action(s), your Plugin is almost complete, but you have one more interface,
IPlugin, to implement. For simple , single-action, plugins you can just implement this interface on the
same class as your action, otherwise it must be implemented on another (single) class.
IPlugin contains the following properties:
• {{LinkDescription { get; }}} – Specifies the text that appears in the Dashboard UI to link to this plugin
• {{INamedAction[] NamedActions { get; }}}
The Actions property returns instances of all the Actions in your plugin. An Action is specified (in a
INamedAction) by giving the action instance itself, and also a (unique) Action Name that will be used by
the Web Framework's controller to route user requests. Action Names should just include alpha-numeric
characters (i.e. only a-z, A-Z, and 0-9).
The Actions property must return an array with at least one INamedAction.
The first named action, i.e. Actions [0] will be the Action linked to through the Dashboard UI.
For this entire look at existing implementations to see how CruiseControl.NET defines its own plugins.

Build Plugins
Build Plugins have a slight complication, in that they must implement the slightly richer interface
IBuildPlugin rather than IPlugin. Most Build Plugins will do this by extending the
ProjectConfigurableBuildPlugin class, which automatically makes them a Project Configurable Build
Plugin - simple!
Apart from that Build Plugins are identical to other plugins.

Deploying your Plugin


To deploy your plugin:
• Compile your plugin to an assembly with the name ccnet.anything-you-like.plugin.dll
• Copy the assembly to the bin folder of the Dashboard
• Configure your plugin in the Plugins Configuration Block as normal

Getting the Web Dashboard working with IIS


Make sure that ASP.NET is installed on server: Go to add/remove programs, add/emove windows
components, select Application Server then click on Details. Make sure that ASP.net is ticked.
CRUISE CONTROL.NET

If you installed IIS after the .Net framework was installed, you need to register ASP.Net with IIS.
You can do this by running the aspnet_regiis.exe -i tool found under
\Windows\Microsoft.NET\Framework\v2.0.50727\

In IIS Admin go to Web Service Extentions and make sure that Asp.net v2.0.* is allowed and any
other version prohibited.

Setup the Dashboard


With the build server all setup, make sure to configure your Dashboard to show MSBuild results.
You will need to make the following modifications to the dashboard.config file:
Make sure your Build Report Build Plugin includes the compile-msbuild.xsl file
CRUISE CONTROL.NET

You'll probably also want to setup an MSBuild Output XSL Report Build Plugin using the
msbuild.xsl file, e.g. :
<xslReportBuildPlugin description="MSBuild Output"
actionName="MSBuildOutputBuildPlugin" xslFileName="xsl\msbuild.xsl" />

You might also like