Continuous Integration with CruiseControll.NET

Continuous Integration with CruiseControll.NET

Today I will try to bite quite a big topic which is continuous integration setup for .NET application build using Visual Studio 2008, Vistual Studio Unit Tests and Cruise Control.NET.
Continuous integration, in a few simple words works the following way: there are a number of developers working on a project, developers use subversion or other code versioning system to manage their source code. When they work on the project they commit changes to the subversion repo and from the other side another part of the process called ‘continuous integration server’ checks this code out every few minutes, and tries to build it and run unit tests on it, to see if it is so far all ok.
That was probably the shortest description of continuous integration process you would ever be able to find on the internet ;).

So, how do you set up your own? Well, actually its not that difficult but looks scary at the frist sight. First of all of course, you would have to download and install all software needed, and this is:

That should be it on the server side! While installing just follow the defaults and you should be fine. I do install Cruise Control directly on the C: drive which ends up as C:CruiseControl.NET but you can install it wherever you want, I do it this way as its easier for me to write scripts if neccessary (short pathes instead of long ones).

Once CC.NET is installed you should be able to run it. You have two options, first one run it as a console app or run it as a service. For the setup, I would recommend running it as a console, make sure that CC.NET service is not running and double click ccnet.exe file inside C:CruiseControl.NETserver directory or any other ‘server’ directory depending on your installation path.
If all went fine you can see the CC.NET dashboard in your browser. Just browse to the url ‘http://localhost/ccnet’ where ‘ccnet’ is a virtual directory created by Cruise Control application setup.
capture1

Ok then, once all is runnning and installed we can start configuring our CC server. To do that you would need to open ccnet.config file in your favourite text editor. Inside ccnet.config you will be able to set your project which should be build and tested by Cruise Control. The ccnet.config file consist of a number of project sections. You can have as many ‘project sections as you wish, all contained inside the root element of the document.

<cruisecontrol xmlns:cb="urn:ccnet.config.builder">

  <project name="Project One">
  </project>

  <project name="Project Two">
  </project>

</cruisecontrol>

Lets configure one of the projects, all elements described above would be a subnodes of the project element. First of all we need to specify a working directory for our project. Simply create a dir on your drive somewhere and add a path to it between ‘workingDirectory’ elements. This directory will be used to download the subversion sources.

    <workingDirectory>c:projectone</workingDirectory>

After we specify ‘workingDirectory’ we have to specify a trigger which will call updates on our source code, checked out form the subversion. Right here we specify that CC.NET should check the subversion repo every 60 seconds and if it finds any modifications it should run the whole continuous integration process.

     <triggers>
         <intervalTrigger seconds="60"/>
     </triggers>

To allow cruise controll download/update your sources, we need to specify the adress of the subversion repository as well as username and password

    <!--set the sourcecontrol type to subversion and point to the subversion exe-->
    <sourcecontrol type="svn">
      <executable>C:Program FilesSubversionbinsvn.exe</executable>
      <workingDirectory>C:projectone</workingDirectory>
      <trunkUrl>http://svn_server.com/projectone</trunkUrl>
      <autoGetSource>true</autoGetSource>
      <username>your_username</username>
      <password>your_password</password>
    </sourcecontrol>

This section was pretty easy, after we specify working directory, trigger and subversion settings we are ready to add sections responsible for building, testing and publishing our results.
All of the mentioned should happen inside the ‘tasks’ section so, just after the ‘sourcecontrol’ element add the following:

      <tasks>
      </tasks>

Inside the ‘tasks’ we will add the elements for building the project/solution (msbuild element), unit testing (2 times ‘exec’ element), publishing our work to a separate directory (‘buildpublisher’ element) as well as publish our test results to CC.NET dashboard (‘publishers’ element).

To do all that, we need to first build our project. We are going to use MSBuild.exe which you should be able to find in C:WINDOWSMicrosoft.NETFrameworkv3.5 if you are using .NET 3.5 version. Instead of building single project we are going to build a whole solution. To build a solution you need to specify the place where the solution file exists as well as the name of the solution file itself. Depending on the project size and characteristics you have to set the timeout option to suit your needs and to prevent CC.NET to timeout before the project have a chance to actually build.

      <!-- Configure MSBuild to compile the updated files -->c:
      <msbuild>
        <executable>C:WINDOWSMicrosoft.NETFrameworkv3.5MSBuild.exe</executable>
        <workingDirectory>C:projectonetrunk</workingDirectory>
        <projectFile>projectOne.sln</projectFile>
        <buildArgs>/noconsolelogger /p:Configuration=Debug</buildArgs>
        <targets></targets>
        <timeout>300</timeout>
        <logger>C:CruiseControl.NETwebdashboardbinThoughtWorks.CruiseControl.MsBuild.dll</logger>
      </msbuild>

Ok, so we are already able to automatically build our project and this is really cool but what would be continuous integration without executing unit tests :). As it makes development easier, for my projects, wherever possible I use built in Unit Test functionality in Visual Studio 2008.In my opinion, VS Unit Tests are a bit more tricky to set up than NUnit on CC.NET, especially publishing results part of it) but the developmnet on the other hand is easier and I will stick to it.
We need to do the following three things to properly execute tests. First of all we need to run tests using MSTest.exe, this part is pretty easy but before doing that we need to delete previous test results or otherwise our MSTest would complain. Therefore you have to add into your tasks the two following ‘exec’ sections.
First one to delete any previouse test results using bat file (deleteTestLog.bat) with single command:

    DEL C:projectoneresults.trx
        <exec>
            <executable>deleteTestLog.bat</executable>
            <baseDirectory>C:CruiseControl.NETserver</baseDirectory>
            <buildArgs></buildArgs>
            <buildTimeoutSeconds>30</buildTimeoutSeconds>
        </exec>

Second ‘exec’ section running the actual unit tests:

        <exec>
            <!--Call mstest to run the tests contained in the TestProject -->
            <executable>mstest.exe</executable>
            <baseDirectory>C:projectonetrunkprojectOneTests</baseDirectory>
            <!--testcontainer: points to the DLL that contains the tests -->
            <!--runconfig: points to solutions testrunconfig that is created by vs.net, list what test to run -->
            <!--resultsfile: normally the test run log is written to the uniquely named testresults directory  -->
            <!--                   this option causes a fixed name copy of the file to be written as well -->
            <buildArgs>/testcontainer:C:projectonetrunkprojectOneTestsBinDebugprojectOneTests.dll /resultsfile:C:projectoneresults.trx</buildArgs>
            <buildTimeoutSeconds>90</buildTimeoutSeconds>
         </exec>

Right now our server builds and tests our solution automatically. If we want to publish the build results somewhere else, lets say to another virtual directory or web site we can copy the files using ‘buildPublisher’. This way, if its a web application, after each build you can browse to the web site url and see the latest changes in place, all freshly build and tested.

      <buildpublisher>
        <sourceDir>C:projectonetrunkprojectOne</sourceDir>
        <publishDir>D:projectOnePublished</publishDir>
        <useLabelSubDirectory>false</useLabelSubDirectory>
      </buildpublisher>

At this point we have a continuous integration server running which automatically update our solution if it detects any changes on subversion server, builds the sources, runs unit tests and publish the build results. This is great, one problem though, MSTest is not well integrated into CC.NET so we won’t be able to see our tests results, if any fails for e.g. on our CC dashboard.
To publish your test results into cruise control dashboard you would need to add the following section inside your ‘project’, just after ‘exec’ or ‘buildPublisher’ sections:

    <!--Publishers will be done after the build has completed-->
    <publishers>
         <merge>
               <files>
                     <file>results.trx</file>
               </files>
         </merge>
         <xmllogger logDir="C:CruiseControl.NETserverProjectOneArtifactsbuildlogs" />
    </publishers>

This will merge your test results into the dashboard.

I hope you will enjoy having continuous integration as part of your project building flow. Have fun.

4 responses on “Continuous Integration with CruiseControll.NET

  1. Brandon May 28, 2009 at 11:41 pm

    Excellent article! Just what we were looking for. I have everything working based on your example, but my unit test results are not showing up in the CC dashboard. The unit test results are included in the log file, just not showing up in the dashboard.

    Any ideas?

  2. Matt Palmerlee November 14, 2009 at 2:50 am

    Thanks for the nice article, I’ve noticed one mistake though: the mstest.exe base directory should be something like:
    C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE

    really helpful post though,
    -Matt

  3. Naresh July 24, 2010 at 7:25 am

    Thank you very much for explaining baby steps in continuous integration.

  4. Rodrigo March 2, 2011 at 8:58 pm

    Excellent. Thanks!

    Additionally:

    *Add user permissions to write to CC.NET installation folder.

    *Open firewall port 21234.

Leave a Reply