    <rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:admin="http://webns.net/mvcb/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:content="http://purl.org/rss/1.0/modules/content/">
     <channel>
        <title>ACCU  :: Continuous Integration with CruiseControl.Net</title>
        <link>https://members.accu.org/index.php/articles/1371</link>
        <description>Professionalism in Programming</description>
        <dc:language>en-us</dc:language> 
        <dc:creator>Administrator</dc:creator> 
        <admin:generatorAgent rdf:resource="http://www.xaraya.org" /> 
        <admin:errorReportsTo rdf:resource="mailto:webeditor@accu.org" />
       <sy:updatePeriod>hourly</sy:updatePeriod>
       <sy:updateFrequency>1</sy:updateFrequency>
       <docs>http://backend.userland.com/rss</docs>




<div class="xar-mod-head"><span class="xar-mod-title">Programming Topics + Process Topics + Overload Journal #79 - Jun 2007</span></div>

<table border="0" cellpadding="1" cellspacing="0">
    <tbody>
    <tr>
        <td valign="top">
            Browse in :
       </td>
       <td valign="top">

                                            <a href="https://members.accu.org/index.php/articles/">All</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c13/">Topics</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c65/">Programming</a>
<br />

                                            <a href="https://members.accu.org/index.php/articles/">All</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c13/">Topics</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c221/">Process</a>
<br />

                                            <a href="https://members.accu.org/index.php/articles/">All</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c76/">Journals</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c78/">Overload</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c224/">79</a>
<br />

                                            <a href="https://members.accu.org/index.php/articles/c65-221-224/">Any of these categories</a>

                    -                        <a href="https://members.accu.org/index.php/articles/c65+221+224/">All of these categories</a>
<br />
</td>
   </tr>
   </tbody>
</table>




<div class="xar-error">
   <p>
 <strong>Note:</strong> when you create a new publication type,
the articles module will automatically use the templates
<em>user-display-[publicationtype].xt</em>
and <em>user-summary-[publicationtype].xt</em>.
If those templates do not exist when you try to preview or display a new article,
you'll get this warning :-)  Please place your own templates in themes/<em>yourtheme</em>/modules/articles . The templates will get the extension .xt there. </p>
</div>
<div class="xar-norm xar-standard-box-padding">
   <h1><strong>Title:</strong>&nbsp;Continuous Integration with CruiseControl.Net</h1>
<p><strong>Author:</strong>&nbsp;</p>
<p>
<strong>Date:</strong> 04 June 2007 11:57:00 +01:00 or Mon, 04 June 2007 11:57:00 +01:00</p>
<p><strong>Summary:</strong>&nbsp;Is CC any good? How could it be better? Did it make a real difference where it was installed? Should we all give it a go?</p>
<p><strong>Body:</strong>&nbsp;<h2> What is continuous integration? </h2>
<p>
Continuous integration is vital to the software development process if
you have multiple build configurations and/or multiple people working
on the same code base. WikiPedia [<a href="#WikiPedia">WikiPedia</a>] describes continuous
integration as '...a software engineering term describing a process
that completely rebuilds and tests an application frequently.'
Generally speaking, continuous integration is the act of automatically
building a project or projects and running associated tests; typically
after a checkin or multiple checkins to a source control system. </p>
<h2> Why should you use continuous integration? </h2>
<p> My Dad takes a huge interest in my career and always wants to know
what I'm doing. He knows almost nothing about software engineering, but
he does know &lt;sup class=&quot;footnoteref&quot;&gt;a lot</sup> about cars, so I
often use the production of a car as an analogy to software
engineering. </p>
<p> Imagine a car production factory where one department designs and
builds the engine, another department designs and builds the gear box
and a third department designs and builds the transmission (prop shaft,
differential, etc.). The engine has to connect to the gearbox and the
gearbox to the transmission. These departments work to a greater or
lesser degree in isolation, just like teams or individuals working on
different libraries or areas of a common code base on some projects. </p>
<p> A deadline has been set in the factory for all the parts of the car
to be ready and the car will be assembled and shipped the next day.
During the time to the deadline the gearbox is modified to have four
engine mountings, as a flaw in the original design is identified,
instead of the three the specification dictates and the ratio of the
differential is changed as the sales department has promised the
customer the car will have a higher top speed. </p>
<p> The deadline has arrived and the first attempt to assemble the
engine, gearbox and transmission is made. The first problem is that the
gearbox cannot be bolted onto the engine correctly as there are
insufficient mountings on the engine. However this can be fixed, but
will take an extra two weeks while the engine block is recast and the
necessary mountings added. </p>
<p> Two weeks later the engine, gearbox and transmission are all
assembled, bolted into the car and it's out on the test track. The car
is flat out down the straight and it is 10 miles per hour slower than
sales department promised it would be as the engine designers did not
know about the change in differential ratio and the maximum torque
occurs at the wrong number of revs. So the car goes back to the factory
have the valve timings adjusted which takes another two weeks. </p>
<p> When presented like this it is clear that there is a problem with
the way development has been managed. But all too often this the way
that software development is done - specs are written and software
developed only to be put together under the pressure of the final
deadline. Not surprisingly the software is delivered late, over budget
and spoils reputations. We've all been there. </p>
<p> The problems could have been avoided or at least identified in time
to be addressed, by scheduling regular integrations between the
commencement of production and the deadline. Exactly the same applies
to software engineering. All elements of the system should be built
together and tested regularly to make sure that it builds and that it
performs as expected. The ideal time is every time a checkin is made.
Integration problems are then picked up as soon as they are created and
not the day before the release and the ideal way to do this is using an
automated system such as CruiseControl. </p>
<h2> CruiseControl.Net </h2>
<p> CruiseControl, written in Java, is one of the better known
continuous integration systems it is designed to monitor a source
control system, wait for checkins, do builds and run tests.
CruiseControl.Net [<a href="#CruiseControl.Net">CruiseControl.Net</a>] is, obviously, a .Net
implementation of CruiseControl, designed to run on Windows although it
can be used with Mono[<a href="#Mono">Mono</a>]. </p>
<p> I found the simple start-up documentation for CruiseControl.Net
sadly lacking, so in this article I am going to go through a simple
CruiseControl.Net configuration step-by-step using my Aeryn [<a href="#Aeryn">Aeryn</a>] C++
testing framework. Aeryn is an ideal example as it has both Makefiles
for building in Unix-like environments and a set of Microsoft Visual
C++ build files. It also has a complete test suite which is run as part
of the build.<br>
</p>
<h3>Download and Install<br>
</h3>
<p> You can download CruiseControl.Net from the CruiseControl.Net
website. It comes in several different formats including source and a
Windows MSI installer. Download and install the Windows MSI and select
the defaults. This will install CruiseControl.Net as a service and
setup a virtual directory that so it can be used with Microsoft's
Internet Information Service [<a href="#IIS">IIS</a>] to give detailed information about
the builds (I'll cover this in Part 2). Also download and install the
CCTray Windows MSI. CCTray is a handy utility for monitoring builds
I'll discuss later. </p>
<p> CruiseControl.Net can run as both a command line program and a
Windows service. It is useful to start off with the command line
version and then move to the Windows service once all the configuration
bugs have been ironed out. </p>
<h2> Project block </h2>
<p> CruiseControl.Net uses an XML configuration file called
ccnet.config, which is located in the CruiseControl.Net server
directory (the default CruiseControl.Net install directory is:
C:\Program Files\CruiseControl.NET). The configuration must be wrapped
in a <tt class="code">&lt;cruisecontrol&gt;</tt> block and contain at
least one <tt class="code">&lt;project&gt;</tt> block: </p>
<pre class="programlisting">&lt;cruisecontrol&gt;<br>  &lt;project name=&quot;Aeryn&quot; &gt;&lt;/project&gt;<br>&lt;/cruisecontrol&gt; </pre>
<p> The above is the minimal project block. In the above example the
project is simply given the name Aeryn. It will be added as we step
through the configuration. To run CruiseControl.Net from the command
line, open a command prompt and change to the &lt;sup class=&quot;footnoteref&quot;&gt;server</sup>
directory, type &lt;sup class=&quot;footnoteref&quot;&gt;ccnet</sup> and hit return.
The output is similar to that shown in Figure 1. </p>
<table class="sidebartable">
    <tr>
      <td>
      <pre class="programlisting"> Microsoft Windows XP [Version 5.1.2600]<br>  (C) Copyright 1985-2001 Microsoft Corp.<br><br> C:\&gt;cd C:\Program Files\CruiseControl.NET\server<br><br> C:\Program Files\CruiseControl.NET\server&gt;ccnet<br> CruiseControl.NET Server 1.2.1.7 -- .NET Continuous Integration Server<br> Copyright (C) 2003-2006 ThoughtWorks Inc.  All Rights Reserved.<br> .NET Runtime Version: 2.0.50727.42      Image Runtime Version: v1.1.4322<br> OS Version: Microsoft Windows NT 5.1.2600 Service Pack 2        Server locale: en-GB<br> [CCNet Server:DEBUG] The trace level is currently set to debug.  This will cause CCNet to log at the most<br> verbose level, which is useful for setting up or debugging the server.  Once your server is running<br> smoothly, we recommend changing this setting in C:\Program<br> Files\CruiseControl.NET\server\ccnet.exe.config to a lower level.<br> [CCNet Server:INFO] Reading configuration file &quot;C:\Program Files\CruiseControl.NET\server\ccnet.config&quot;<br> [CCNet Server:INFO] Registered channel: tcp<br> [CCNet Server:INFO] CruiseManager: Listening on url: tcp://192.168.0.100:21234/CruiseManager.rem<br> [CCNet Server:INFO] Starting CruiseControl.NET Server<br> [Aeryn:INFO] Starting integrator for project: Aeryn<br> [Aeryn:INFO] No modifications detected.<br>  </pre>
      </td>
    </tr>
    <tr>
      <td class="title">Figure 1</td>
    </tr>
</table>
<p> This starts CruiseControl.Net, but it has nothing to do so it just
sits and waits. Now is a good point at which to configure CCTray. Bring
up the CCTray window by double clicking on the CCTray icon (usually a
green, red or orange circle with CC in the centre) in the system tray.
First register the CruiseControl.Net server:<br>
</p>
<ol>
  <li>Select the file menu and settings.</li>
  <li>Then select the Add button from the Build Projects tab.</li>
  <li>Click the Add Server button from the project dialog.</li>
  <li>Select the Ã¢â‚¬ËœConnect directly using .Net remotingÃ¢â‚¬â„¢ radio button.</li>
  <li>Enter &lt;tt&gt;localhost&lt;/tt&gt; to connect to a server on
the local machine or the&nbsp; IP address or host name for a server on
a remote machine and click Ok.</li>
  <li>Select the project (in this case Aeryn) from the projects list
box and click Ok.</li>
  <li>Click Ok on the CruiseControl.Net Tray Settings dialog.<br>
  </li>
</ol>
<p> </p>
<p> CCTray will connect to the CruiseControl.Net server and you should
see the CCTray main window, looking something like Figure 2.<br>
</p>
<table class="sidebartable">
    <tr>
      <td> <img alt="CCTray User Interface"
 src="/content/images/journals/ol79/image001.png"><br>
      </td>
    </tr>
    <tr>
      <td class="title">Figure 2<br>
      </td>
    </tr>
</table>
<p> </p>
<p> CCTray is designed not only to run on the same machine as
CruiseControl.Net, but on any number of client machines as well. </p>
<h2> Source control block </h2>
<p> CruiseControl.Net can be configured to monitor a number of source
control systems for changes. Theses include subversion, CVS, Perforce,
ClearCase and Visual Source Safe. The CruiseControl.Net documentation
includes a complete list. One of the strengths of CruiseControl.Net is
that it is easy to add support, via a plugin, for other source control
systems. I plan to write about creating CruiseControl.Net plugins in
future articles. </p>
<p> Aeryn uses Subversion [<a href="#SVN">SVN</a>] and CruiseControl.Net. A subversion
client must be installed to use it (TortoiseSVN doesn't appear to have
the right executable). The minimum parameters needed are the (trunk)
URL of the repository and the working directory (a path to check the
code out to). However, this assumes that svn.exe (subversion client
executable) is also in the working directory, so it is necessary to
specify the path to it. The full working directory must also exist. </p>
<pre class="programlisting">&lt;project name=&quot;Aeryn&quot;&gt;<br>  &lt;sourcecontrol type=&quot;svn&quot;&gt;<br>    &lt;trunkUrl&gt;http://aeryn.tigris.org/svn/aeryn/<br>              trunk/&lt;/trunkUrl&gt;<br>    &lt;workingDirectory&gt;c:\temp\ccnet\aeryn<br>    &lt;/workingDirectory&gt;<br>    &lt;executable&gt;C:\Program Files\Subversion\bin\<br>                svn.exe&lt;/executable&gt;<br>  &lt;/sourcecontrol&gt;<br>&lt;/project&gt;  </pre>
<p> CruiseControl.Net monitors ccnet.config, so simply making the above
changes and saving the file should be all that needs to be done.
Alternatively the server can be started again from the command line,
giving an output similar to Figure 3.<br>
</p>
<table class="sidebartable"><tr><td>
<pre class="programlisting">[CCNet Server:DEBUG] The trace level is currently set to debug. This will cause CCNet to log at the most <br>verbose level, which is useful for setting up or debugging the server. Once your server is running<br>smoothly, we recommend changing this setting in C:\Program Files\CruiseControl.NET\server\ccnet.exe. <br>config to a lower level.<br>[CCNet Server:INFO] Reading configuration file &quot;C:\Program Files\CruiseControl.NET\server\ccnet.config&quot; <br>[CCNet Server:INFO] Registered channel: tcp <br>[CCNet Server:INFO] CruiseManager: Listening on url: tcp://192.168.0.100:21234/CruiseManager.rem <br>[CCNet Server:INFO] Starting CruiseControl.NET Server <br>[Aeryn:INFO] Starting integrator for project: Aeryn <br>[Aeryn:INFO] No modifications detected.</pre>
</td></tr><tr><td class="title">Figure 3</td></tr></table>
<p> There is some extra debug information, such as the last checkin
message, omitted from Figure 3. The final message is <tt class="code">No
modifications detected</tt>. This means that CruiseControl.Net has
identified that there have been no recent changes to the repository.
Therefore it has not checked anything out and it has not attempted to
build anything. </p>
<p> One way to test that it checks code out correctly would be to
commit a change to the repository, however this is unnecessary. CCTray
can be used to force the checkout. Select the project from the CCTray
list box and click <tt class="code">Force Build</tt>. You will get an
output similar to Figure 4.<br>
</p>
<table class="sidebartable"><tr><td>
<pre class="programlisting">[Aeryn:DEBUG] Starting process [C:\Program Files\Subversion\bin\svn.exe] in working directory <br>[c:\temp\ccnet\aeryn] with arguments [log http://aeryn.tigris.org/svn/aeryn/trunk/ -r &quot;{2007-05-<br>04T16:06:42Z}:{2007-05-04T17:26:17Z}&quot; --verbose --xml --non-interactive --no-auth-cache] <br>... <br>[Aeryn:INFO] No modifications detected. <br>[Aeryn:INFO] Building: Paul Grenyer triggered a build (ForceBuild) <br>[Aeryn:DEBUG] Starting process [C:\Program Files\Subversion\bin\svn.exe] in working directory<br>[c:\temp\ccnet\aeryn] with arguments [checkout http://aeryn.tigris.org/svn/aeryn/trunk/ <br>c:\temp\ccnet\aeryn --non-interactive --no-auth-cache&lt;] <br>[Aeryn:DEBUG] A   C:\temp\ccnet\aeryn\corelib <br>[Aeryn:DEBUG] A   C:\temp\ccnet\aeryn\corelib\corelib.vcproj <br>[Aeryn:DEBUG] A   C:\temp\ccnet\aeryn\corelib\Makefile <br>[Aeryn:DEBUG] A   C:\temp\ccnet\aeryn\Doxyfile <br>[Aeryn:DEBUG] A   C:\temp\ccnet\aeryn\include <br>... <br>[Aeryn:DEBUG] A   C:\temp\ccnet\aeryn\examples\lift\TestClient\main.cpp <br>[Aeryn:DEBUG] U   C:\temp\ccnet\aeryn <br>[Aeryn:DEBUG] Checked out revision 157.<br>[Aeryn:INFO] Integration complete: Success - 04/05/2007 18:26:50<br></pre>
</td></tr><tr><td class="title">
Figure 4</td></tr></table>
<p> The SVN source control block, unlike some of the other source
control blocks, supports username and password parameters. This allows
code to be checked out on machines where the current user, such as the
system account if CruiseControl.Net is running as a service, does not
have the necessary permissions. </p>
<pre class="programlisting">&lt;sourcecontrol type=&quot;svn&quot;&gt;<br>  &lt;trunkUrl&gt;http://aeryn.tigris.org/svn/aeryn/trunk/&lt;/trunkUrl&gt;<br>  &lt;workingDirectory&gt;c:\temp\ccnet\aeryn<br>  &lt;/workingDirectory&gt;<br>  &lt;executable&gt;C:\Program Files\Subversion\bin\svn.exe&lt;/executable&gt;<br>  &lt;username&gt;fprefect&lt;username&gt;<br>  &lt;password&gt;towel&lt;password&gt;<br>&lt;/sourcecontrol&gt;  </pre>
<p> The drawback is that the username and password are stored in
ccnet.config in unencrypted human readable format. However,
CruiseControl.Net only needs to be able to check code out, it doesn't
need to check it back in, so if the repository you are using supports
anonymous checkouts this is less of a disadvantage. </p>
<h2> Devenv task block (Visual Studio 7.x Task) </h2>
<p> One of the two basic build systems supported by Aeryn is Microsoft
Visual Studio solutions. CruiseControl.Net has two special task blocks
for visual studio solutions: <tt class="code">&lt;devenv&gt;</tt> and <tt
 class="code">&lt;msbuild&gt;</tt>. <tt class="code">&lt;devenv&gt;</tt>
is used to build version 7.x solutions and <tt class="code">&lt;msbuild&gt;</tt>
to build version 8 solutions using Microsoft's MSBuild [<a href="#MSBuild">MSBuild</a>]. Aeryn
uses visual studio 7.1 solutions and therefore requires <tt
 class="code">&lt;devenv&gt;</tt>. </p>
<p> The minimum parameters needed are the solution file to build and
the configuration to build (e.g. <tt class="code">debug</tt> or <tt
 class="code">release</tt>). However this assumes that Visual Studio
7.x is installed at a specific location, but Visual Studio 7.x can be
installed to any path and the default path varies across versions, so
it is best to specify the path to the devenv.com executable for the
version being used. </p>
<pre class="programlisting">&lt;sourcecontrol type=&quot;svn&quot;&gt;<br>  ...<br>&lt;/sourcecontrol&gt;<br>&lt;tasks&gt;<br>  &lt;devenv&gt;<br>    &lt;solutionfile&gt;C:\temp\ccnet\aeryn\aeryn2.sln<br>    &lt;/solutionfile&gt;<br>    &lt;configuration&gt;Debug&lt;/configuration&gt;<br>    &lt;executable&gt;C:\Program Files\Microsoft Visual Studio .NET 2003\Common7\IDE\devenv.com<br>    &lt;/executable&gt;<br>  &lt;/devenv&gt;<br>&lt;/tasks&gt;<br>    </pre>
<p> There are a number of other useful <tt class="code">&lt;devenv&gt;</tt>
parameters, two of which are:&lt;sup class=&quot;footnoteref&quot;&gt; </sup><tt
 class="code">&lt;buildtype&gt;</tt> and <tt class="code">&lt;buildTimeoutSeconds&gt;</tt>.
The build types are <tt class="code">Build</tt>, <tt class="code">Clean</tt>
and <tt class="code">Rebuild</tt> and have their normal visual studio
meanings. The default is <tt class="code">Rebuild</tt>. Build timeout
is the number of seconds that CruiseControl.Net will wait before
assuming the build has hung and should be killed. The default is 600
(10mins): </p>
<pre class="programlisting">&lt;devenv&gt;<br>  &lt;solutionfile&gt;C:\temp\ccnet\aeryn\aeryn2.sln<br>  &lt;/solutionfile&gt;<br>  &lt;configuration&gt;Debug&lt;/configuration&gt;<br>  &lt;executable&gt;C:\Program Files\Microsoft Visual Studio .NET 2003\Common7\IDE\devenv.com<br>  &lt;/executable&gt;<br>  &lt;buildtype&gt;Rebuild&lt;/buildtype&gt;<br>  &lt;buildTimeoutSeconds&gt;300&lt;/buildTimeoutSeconds&gt;<br>&lt;/devenv&gt;    </pre>
<p> Aeryn has both a debug and a release configuration and the building
of both should be tested. That requires two <tt class="code">&lt;devenv&gt;</tt>
blocks and two fully hard coded solution paths. This introduces a
possible maintenance headache if the working directory is moved.
Solution paths can be relative if a working directory is specified in
the project block, as shown in Listing 1.<br>
</p>
<table class="sidebartable"><tr><td>
<pre class="programlisting">&lt;cruisecontrol&gt; <br>  &lt;project name=&quot;Aeryn&quot;&gt;<br>    &lt;workingDirectory&gt;c:\temp\ccnet\aeryn <br>       &lt;/workingDirectory&gt;<br>    ... <br>    &lt;tasks&gt;<br>     &nbsp;&lt;devenv&gt;<br>        &lt;solutionfile&gt;aeryn2.sln&lt;/solutionfile&gt;<br>        &lt;configuration&gt;Debug&lt;/configuration&gt;<br>        &lt;executable&gt;C:\Program Files\Microsoft <br>            Visual Studio ... .NET 2003\Common7\IDE\ <br>            devenv.com&lt;/executable&gt;<br>        &lt;buildtype&gt;Rebuild&lt;/buildtype&gt;<br>        &lt;buildTimeoutSeconds&gt;300 <br>           &lt;/buildTimeoutSeconds&gt;<br>      &lt;/devenv&gt; <br>      &lt;devenv&gt;<br>        &lt;solutionfile&gt;aeryn2.sln&lt;/solutionfile&gt;<br>        &lt;configuration&gt;Release&lt;/configuration&gt;<br>        &lt;executable&gt;C:\Program Files\Microsoft<br>           &nbsp;Visual Studio ... .NET 2003\Common7\IDE\ <br>            devenv.com&lt;/executable&gt;<br>        &lt;buildtype&gt;Rebuild&lt;/buildtype&gt;<br>        &lt;buildTimeoutSeconds&gt;300<br>          &nbsp;&lt;/buildTimeoutSeconds&gt;<br>      &lt;/devenv&gt; <br>    &lt;/tasks&gt; <br>    ... <br>  &lt;/project&gt;<br>&lt;/cruisecontrol&gt; </pre>
</td></tr><tr><td class="title">
Listing 1
</td></tr></table>
<p> Again, the changes to ccnet.config should be automatically picked
up by the server when it is saved or the server can be restarted from
the command line. Using CCTray to force the build will cause both
configurations to build. </p>
<p> The other build system supported by Aeryn is make on both Windows
and Linux. Obviously CruiseControl.Net can only run the Windows
version. CruiseControl.Net doesn't have a specific make task block, so
a generic executable block must be used instead. </p>
<p> I think that a task block supporting make is a fundamental omission
from CruiseControl.Net. As creating new task blocks is very easy; I
have written a <tt class="code">make</tt> task block and am currently
trying to get it incorporated into CruiseControl.Net. If I am
unsuccessful I will be making it available as a plugin. </p>
<p> The parameters are the path to the executable, the arguments to
pass to the executable, the number of seconds to wait before assuming
that the process has hung and should be killed, and the working
directory. The working directory is only needed if it is different from
the working directory specified by the project block. </p>
<pre class="programlisting">&lt;exec&gt;<br>  &lt;executable&gt;C:\MinGW\bin\mingw32-make.exe&quot;<br>  &lt;/executable&gt;<br>  &lt;buildArgs&gt;-f Makefile rebuild&lt;/buildArgs&gt;<br>  &lt;buildTimeoutSeconds&gt;300&lt;/buildTimeoutSeconds&gt;<br>&lt;/exec&gt;    </pre>
<p> This disadvantage of using an <tt class="code">&lt;exec&gt;</tt>
block to run make is that it does not give any <tt class="code">INFO</tt>
level log output indicating that the task is running or whether it was
successful, as the <tt class="code">&lt;devenv&gt;</tt> and <tt
 class="code">&lt;msbuild&gt;</tt> blocks do. CruiseControl.Net also
generates a <tt class="code">DEBUG</tt> level error as the output from
calling make is not in XML format. This is not a serious problem as
when CruiseControl.Net is running in production debug logging should be
turned off. The make task block I have written solves both these
issues. </p>
<p> Saving the changes to <tt class="code">ccnet.config</tt> and using
CCTray to force the build should cause the make configurations to build
along with the visual studio configurations. </p>
<h2> Publisher block - email </h2>
<p> CruiseControl.Net uses publisher blocks to notify developers of the
status of the build. The most useful publisher block is email. The
email block can be used to send status emails to groups of email
addresses. </p>
<p> For example the developer responsible for maintaining the
CruiseControl.Net server may want an email every time a build takes
place. However, the rest of the developers on the team probably only
want to receive an email when the status of the build changes (e.g.
from fixed to broken or vice-versa) or while the build is broken. To
achieve this, two groups can be setup, a &quot;developers&quot; group and a
&quot;buildmaster&quot; group, each group is configured individually. </p>
<p> Emails can be triggered by three different notification events: </p>
<ul>
  <li> Always An email is sent every time a build takes place. </li>
  <li> Change An email is sent when the status of the build changes,
either from fixed to broken or from broken to fixed. </li>
  <li> Failed Sends an email whenever a build fails. </li>
</ul>
<p> An SMTP server must also be specified along with the relevant
username and password when needed. The <tt class="code">&lt;email&gt;</tt>
block has the same security issues as the source control block in terms
of the username and password being in human readable format. However,
most of the time a build server will be fixed within a particular
network and access to the SMTP server on a corporate network or through
the ISP will not require a username or password. </p>
<p> If CruiseControl.Net is being run on a roaming computer such as a
laptop then this becomes more of an issue. I use Google mail for my
every day email and the Google SMTP server uses a non-standard port and
requires a secure connection. This is not supported by the email block
or, it appears, the underlying .Net <tt class="code">SMTP</tt> class.
I am sure that both the username and password issue and the port and
security issue could be overcome by writing a custom email block based
on the existing one, however that is outside the scope of this article.
</p>
<p> See Listing 2. Assuming the SMTP details and email addresses are
correct, emails will be sent at the end of each build.<br>
</p>
<table class="sidebartable"><tr><td>
<pre class="programlisting">&lt;project name=&quot;Aeryn&quot;&gt; ...<br>  &lt;publishers&gt; <br>    &lt;email from=paul.grenyer@gmail.com mailhost=&quot;mailhost.zen.co.uk&quot; <br>        includeDetails=&quot;TRUE&quot;&gt; <br>      &lt;users&gt;<br>        &lt;user name=&quot;Paul Grenyer&quot; group=&quot;buildmaster&quot;...<br>           ...address=&quot;paul.grenyer@gmail.com&quot;/&gt; <br>        &lt;user name=&quot;Aeryn Developers&quot; group=&quot;developers&quot;...<br>           ...address=&quot;continuousintegration@aeryn.tigris.org&quot;/&gt; <br>      &lt;/users&gt;<br>      &lt;groups&gt; <br>        &lt;group name=&quot;developers&quot; notification=&quot;change&quot;/&gt;<br>        &lt;group name=&quot;buildmaster&quot; notification=&quot;always&quot;/&gt; <br>      &lt;/groups&gt;<br>    &lt;/email&gt; <br>  &lt;/publishers&gt; <br>&lt;/project&gt;<br></pre>
</td></tr><tr><td class="title">
Listing 2
</td></tr></table>
<p> When setting up email notifications from continuous integration on
multi-developer projects it is important to be aware of how the members
of the team feel about potentially receiving a lot of extra email and
having the fact that their code changes have broken the build
highlighted to the team. </p>
<p> During the setting up of the server it is sensible to restrict
emails to the person doing the setup. I found that people became
irritated with only a small increase in email to begin with. However as
the builds became more successful and the appropriate email rules
implemented (see above), this became less of an issue. </p>
<p> To get people to accept that they have broken the build and agree
to fix it, I found that it was important to get buy-in for continuous
integration. This is an ongoing task. The management, however, is on
side and pushing quite hard. I am sure that as soon as the next release
is built smoothly everyone will be more enthusiastic about continuous
integration and maintaining working builds. </p>
<h2> Running CruiseControl.Net as a Service </h2>
<p> CruiseControl.Net can be run as a Windows Service. This has the
advantage that whenever the dedicated build server is rebooted or
someone logs in or logs out, the CruiseControl.Net server keeps
running. Running CruiseControl.Net as a service uses exactly the same
ccnet.config file. </p>
<p> During the development of the configuration it useful to have lots
of debug information. Once the configuration is complete and working;
this extra debug information is no longer useful and should be turned
off. To adjust the logging level, edit the <tt class="code">&lt;level
value&gt;</tt> tag in the ccservice.exe.config file in the
CruiseControl.Net server directory. The available levels are <tt
 class="code">DEBUG</tt>, <tt class="code">INFO</tt>, <tt class="code">WARN</tt>,
<tt class="code">ERROR</tt>, <tt class="code">OFF</tt>. The default is
<tt class="code">Debug</tt>. Changing the setting to <tt class="code">INFO</tt>
reduces a lot of unnecessary noise: </p>
<pre class="programlisting">&lt;level value=&quot;INFO&quot; /&gt;</pre>
<p> Changes to ccservice.exe.config are not picked up by
CruiseControl.Net until it is restarted. </p>
<p> CruiseControl.Net is installed as a Windows service as part of the
standard setup. Before it can be started it must be configured to run
as a user that has access to the source control system (unless the
username and password have been put into source control block) and the
compilers and applications that are used in the configuration. </p>
<p> CruiseControl.Net writes a log file called ccnet.log to the Service
directory. It can be useful to monitor this with a tool such as tail
[<a href="#Tail">Tail</a>]. When CruiseControl.Net is running as a service a build can be
forced from CCTray in the same way as when it was running from the
command line. The complete ccnet.config file is shown in Listing 3.<br>
</p>
<table class="sidebartable"><tr><td>
<pre class="programlisting">&lt;cruisecontrol&gt; <br>  &lt;project name=&quot;Aeryn&quot;&gt;<br>    &lt;workingDirectory&gt;c:\temp\ccnet\aeryn&lt;/workingDirectory&gt;<br>      &lt;sourcecontrol type=&quot;svn&quot;&gt;<br>        &lt;trunkUrl&gt;http://aeryn.tigris.org/svn/aeryn/trunk/&lt;/trunkUrl&gt;<br>        &lt;workingDirectory&gt;c:\temp\ccnet\aeryn&lt;/workingDirectory&gt;<br>        &lt;executable&gt;C:\Program Files\Subversion\bin\svn.exe<br>          &lt;/executable&gt; <br>      &lt;/sourcecontrol&gt; <br>      &lt;tasks&gt; <br>        &lt;devenv&gt;<br>          &lt;solutionfile&gt;aeryn2.sln&lt;/solutionfile&gt;<br>          &lt;configuration&gt;Debug&lt;/configuration&gt;<br>          &lt;executable&gt;C:\Program Files\Microsoft Visual Studio... <br>             ....NET 2003\Common7\IDE\devenv.com&lt;/executable&gt;<br>          &lt;buildtype&gt;Rebuild&lt;/buildtype&gt;<br>          &lt;buildTimeoutSeconds&gt;300&lt;/buildTimeoutSeconds&gt;<br>        &lt;/devenv&gt; <br>        &lt;devenv&gt;<br>          &lt;solutionfile&gt;aeryn2.sln&lt;/solutionfile&gt;<br>          &lt;configuration&gt;Release&lt;/configuration&gt;<br>          &lt;executable&gt;C:\Program Files\Microsoft Visual Studio... <br>             ....NET 2003\Common7\IDE\devenv.com&lt;/executable&gt;<br>          &lt;buildtype&gt;Rebuild&lt;/buildtype&gt;<br>          &lt;buildTimeoutSeconds&gt;300&lt;/buildTimeoutSeconds&gt;<br>        &lt;/devenv&gt;<br>       &nbsp;&lt;exec&gt;<br>          &lt;executable&gt;C:\MinGW\bin\mingw32-make.exe&lt;/executable&gt;<br>          &lt;buildArgs&gt;-f Makefile rebuild&lt;/buildArgs&gt;<br>          &lt;buildTimeoutSeconds&gt;300&lt;/buildTimeoutSeconds&gt;<br>        &lt;/exec&gt;<br>     &nbsp;&lt;/tasks&gt;<br>     &nbsp;&lt;publishers&gt;<br>       &nbsp;&lt;email from=paul.grenyer@gmail.com... <br>           ...mailhost=&quot;mailhost.zen.co.uk&quot; includeDetails=&quot;TRUE&quot;&gt; <br>          &lt;users&gt; <br>            &lt;user name=&quot;Paul Grenyer&quot; group=&quot;buildmaster&quot;... <br>               ...address=&quot;paul.grenyer@gmail.com&quot;/&gt;<br>            &lt;user name=&quot;Aeryn Developers&quot; group=&quot;developers&quot;...<br>               ...address=&quot;continuousintegration@aeryn.tigris.org&quot;/&gt; <br>          &lt;/users&gt;<br>          &lt;groups&gt; <br>            &lt;group name=&quot;developers&quot; notification=&quot;change&quot;/&gt;<br>            &lt;group name=&quot;buildmaster&quot; notification=&quot;always&quot;/&gt; <br>          &lt;/groups&gt;<br>        &lt;/email&gt;<br>     &nbsp;&lt;/publishers&gt; <br>    &lt;/project&gt;<br>&lt;/cruisecontrol&gt;</pre>
</td></tr><tr><td class="title">
Listing 3
</td></tr></table>
<h2> Final test </h2>
<p> As a final test modify a source file in such a way as to break the
build. Commit the file to the source control system and see that it
triggers the CruiseControl.Net build and that the build fails. Then
undo the modification, commit it again and see that the build succeeds.
ccnet.config should also be committed to the source control system and
checking it in will also trigger a build. </p>
<h2> Part 2 </h2>
<p> In this article I have demonstrated how easy it is to setup
continuous integration with CruiseControl.Net. I found the
documentation lacking and I hope this article has started to rectify
that situation. I have highlighted some of CruiseControl.Net's
shortcomings, not only its lack of documentation, but that it is
missing at least one fundamentally important task block and that the
source control and email blocks need to have additional features. I
intend to address these issues with plugins in future articles. </p>
<p> I think it is clear that, because continuous integration highlights
integration issues early, it is something we should all be doing on
multi-developer projects or projects with multiple build systems. This
is what I have found in the relatively short period of time I have been
using continuous integration. </p>
<p> In part two, I am going to look at setting up a webserver to allow
more detailed information to be obtained about the status of the
CruiseControl.Net server and its projects and builds. <br>
</p>
<h2> Acknowledgments </h2>
<p> Thank you to Jez Higgins, Peter Hammond, Roger Orr, Paul Thomas and
Alan Griffiths for reviews and suggestions. </p>
<h2> References </h2>
<p class="reference"> [<a name="WikiPedia">WikiPedia</a>]
<a href="http://en.wikipedia.org/wiki/Continuous_Integration">http://en.wikipedia.org/wiki/Continuous_Integration </a></p>
<p class="reference"> [<a name="CruiseControl.Net">CruiseControl.Net</a>]
<a href="http://ccnet.thoughtworks.com/">http://ccnet.thoughtworks.com/ </a></p>
<p class="reference"> [<a name="Aeryn">Aeryn</a>] <a href="http://www.aeryn.co.uk">http://www.aeryn.co.uk </a></p>
<p class="reference"> [<a name="Mono">Mono</a>] <a href="http://www.mono-project.com">http://www.mono-project.com </a></p>
<p class="reference"> [<a name="IIS">IIS</a>]
<a href="http://www.microsoft.com/windowsserver2003/iis/default.mspx">http://www.microsoft.com/windowsserver2003/iis/default.mspx </a></p>
<p class="reference"> [<a name="SVN">SVN</a>] <a href="http://subversion.tigris.org/">http://subversion.tigris.org/ </a></p>
<p class="reference"> [<a name="MSBuild">MSBuild</a>]
<a href="http://msdn2.microsoft.com/en-us/library/wea2sca5(VS.80).aspx">http://msdn2.microsoft.com/en-us/library/wea2sca5(VS.80).aspx </a></p>
<p class="reference"> [<a name="Tail">Tail</a>] <a href="http://tailforwin32.sourceforge.net/">http://tailforwin32.sourceforge.net/ </a></p>

</p>
<p><strong>Notes:</strong>&nbsp;</p>
<p><em>More fields may be available via dynamicdata ..</em></p>
</div>
</channel>
</rss>
