I recently had to implement a continuous integration framework on one of my projects. Naturally, CruiseControl.NET was the first choice because of it’s extensive feature list and good community support.

If you are not sure what continuous integration is, then here a couple of good places to get you started:

http://en.wikipedia.org/wiki/Continuous_integration
http://martinfowler.com/articles/continuousIntegration.html

More specifically, CruiseControl.NET offers the following features (source):

  • 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

As you can see it can be configured to do a vast array of things, but for the purpose of this post, I’m interested in achieving the following:

  • Setup a CI server
  • Setup the config file required for building my projects (I’m going to use MSBuild rather than Nant) & monitor build results by setting email notifications

Step 1 – Setup a CI server

This step couldn’t have been easier. A dedicated build & integration server is always recommended. I’m huge fan of virtualisation and for this particular example I’ve setup a Windows 2008 virtual machine. The software that you’ll need to install on the server are:

  1. Prerequisites: .NET Framework (latest version), IIS
  2. CruiseControl.NET

You can download the latest version of CruiseControl.NET from here. At the time of writing of this post, the latest version was 1.5 RC1 and that’s the one I’ve used for my setup. I ran into one issue with this release, which I’ll discuss in the notes section at the end of this post, but I guess that’s acceptable for a RC release.

Download the setup file and go through the installation and choose all of the default options. At the end of a successful installation, you’ll have two main things on the server:

  1. Web dashboard: This can be accessed by going the following URL: http://localhost/ccnet/
  2. Windows service: This gets installed with a name of “CruiseControl.NET Server”. This is the main service which is responsible for building your projects.

A quick gotcha over here – if you get an error on the dashboard page just after the installation which says something like “No connection could be made because the target machine actively refused it“, then make sure that the windows service is running. By default, it gets installed with a “Startup type” of “Manual”. If this is the case with you as well, then go to the Services management console and start the service manually.

That’s pretty much what’s required for setting up your server. All that’s required now is to setup your config file with details about the projects that you want to build.

Step 2 – Setup the config file

The config file is located at: C:\Program Files\CruiseControl.NET\server\ccnet.config. Open this is file in your favourite text/XML editor and start entering details about your project. As an example, below is what I ended up with:

<cruisecontrol xmlns:cb="urn:ccnet.config.builder">
	<!-- This is your CruiseControl.NET Server Configuration file. Add your projects below! -->

	<project name="Build Framework">
		<triggers>
            <intervalTrigger seconds="3000" buildCondition="ForceBuild" />
        </triggers>

        <sourcecontrol type="vsts" autoGetSource="true" applyLabel="false">
            <server>http://virtual-charon:8080</server>
            <project>$/Reach.GlobalConnect/Reach/Reach.Laptop/Main</project>
            <workingDirectory>C:\Temp\CCNet_Test\Laptop</workingDirectory>
        </sourcecontrol>
        <tasks>
           <msbuild>
                <executable>C:\WINDOWS\Microsoft.NET\Framework\v3.5\MSBuild.exe</executable>
                <workingDirectory>C:\Temp\CCNet_Test\Laptop</workingDirectory>
                <projectFile>Laptop.Framework\Laptop.Framework.csproj</projectFile>
                <buildArgs>/noconsolelogger /p:Configuration=Debug /v:diag</buildArgs>
                <targets>Build</targets>
                <timeout>600</timeout>
                <logger>ThoughtWorks.CruiseControl.MsBuild.XmlLogger,C:\Program Files\CruiseControl.NET\server\ThoughtWorks.CruiseControl.MsBuild.dll</logger>
            </msbuild>
			<msbuild>
                <executable>C:\WINDOWS\Microsoft.NET\Framework\v3.5\MSBuild.exe</executable>
                <workingDirectory>C:\Temp\CCNet_Test\Laptop</workingDirectory>
                <projectFile>Laptop.Common\Laptop.Common.csproj</projectFile>
                <buildArgs>/noconsolelogger /p:Configuration=Debug /v:diag</buildArgs>
                <targets>Build</targets>
                <timeout>600</timeout>
                <logger>ThoughtWorks.CruiseControl.MsBuild.XmlLogger,C:\Program Files\CruiseControl.NET\server\ThoughtWorks.CruiseControl.MsBuild.dll</logger>
            </msbuild>
            <msbuild>
                <executable>C:\WINDOWS\Microsoft.NET\Framework\v3.5\MSBuild.exe</executable>
                <workingDirectory>C:\Temp\CCNet_Test\Laptop\Reach.Laptop.Framework</workingDirectory>
                <projectFile>Laptop.BusinessObject.csproj</projectFile>
                <buildArgs>/noconsolelogger /p:Configuration=Debug /v:diag</buildArgs>
                <targets>Build</targets>
                <timeout>600</timeout>
                <logger>ThoughtWorks.CruiseControl.MsBuild.XmlLogger,C:\Program Files\CruiseControl.NET\server\ThoughtWorks.CruiseControl.MsBuild.dll</logger>
            </msbuild>
            <msbuild>
                <executable>C:\WINDOWS\Microsoft.NET\Framework\v3.5\MSBuild.exe</executable>
                <workingDirectory>C:\Temp\CCNet_Test\Laptop\ResourceProvider</workingDirectory>
                <projectFile>Laptop.ResourceProvider.csproj</projectFile>
                <buildArgs>/noconsolelogger /p:Configuration=Debug /v:diag</buildArgs>
                <targets>Build</targets>
                <timeout>600</timeout>
                <logger>ThoughtWorks.CruiseControl.MsBuild.XmlLogger,C:\Program Files\CruiseControl.NET\server\ThoughtWorks.CruiseControl.MsBuild.dll</logger>
            </msbuild>
            <msbuild>
                <executable>C:\WINDOWS\Microsoft.NET\Framework\v3.5\MSBuild.exe</executable>
                <workingDirectory>C:\Temp\CCNet_Test\Laptop\Reach.Laptop</workingDirectory>
                <projectFile>Reach.Laptop.csproj</projectFile>
                <buildArgs>/noconsolelogger /p:Configuration=Debug /v:diag</buildArgs>
                <targets>Build</targets>
                <timeout>600</timeout>
                <logger>ThoughtWorks.CruiseControl.MsBuild.XmlLogger,C:\Program Files\CruiseControl.NET\server\ThoughtWorks.CruiseControl.MsBuild.dll</logger>
            </msbuild>

        </tasks>

		<publishers>
			<statistics />
			<xmllogger />
			<email from="test@test.co.uk" mailhost="mail.test.co.uk" includeDetails="true"
				mailhostUsername="test" mailhostPassword="test">
				  <users>
					  <user name="Test" address="developer@test.co.uk"
						 group="NotifyGroup" />
				 </users>
				<groups>
				  <group name="NotifyGroup">
					<notifications>
					  <NotificationType>Always</NotificationType>
					</notifications>
				  </group>
				</groups>
			 </email>
		</publishers>
    </project>
</cruisecontrol>

Most of the XML is self-explanatory but here are a few things to point out:

  • The buildCondition attribute defaults to a value of “IfModificationExists” which will only initiate the build process if there have been changes to the code repository since the last build. I’ve set it to “ForceBuild” – which will initiate the build process irrespective of whether there’s new code checked-in or not.
    <triggers>
        <intervalTrigger seconds="6000" buildCondition="ForceBuild" />
    </triggers>
    
  • The type attribute is set to “vsts” – this is because I’m using TFS as my source control provider but you could quite easily use any of the other supported source controls including SVN & CVS.
    <sourcecontrol type="vsts" autoGetSource="true" applyLabel="false">
    
  • I wanted to get email notifications every time the build was processed. To accomplish this, the following piece of code was added to the config file:
    <publishers>
    	<statistics />
    	<xmllogger />
    	<email from="test@test.co.uk" mailhost="mail.test.co.uk" includeDetails="true"
    		mailhostUsername="test" mailhostPassword="test">
    		  <users>
    			  <user name="Test" address="developer@test.co.uk"
    				 group="NotifyGroup" />
    		 </users>
    		<groups>
    		  <group name="NotifyGroup">
    			<notifications>
    			  <NotificationType>Always</NotificationType>
    			</notifications>
    		  </group>
    		</groups>
    	 </email>
    </publishers>
    

    Most of it is self-explanatory – the only setting worth pointing out is: NotificationType. I’ve set it to “Always” but it can also be set to “Failed” or “Changed”. Other values are explained over here.

Notes: A few quick things to point out which I learnt by experience while setting this up and could save you some time:

  1. Service security credentials: When your build process is run, you might get an error which says “System.Exception: TF30063: You are not authorized to access TFSServer“. There could be better ways of fixing it but I fixed it by changing the logon credentials of the “CruiseControl.NET Server” windows service to a login which has got access to the TFS server.
  2. Error if you are using VSTS: If you are using the RC version that I used, you might also run into an error which says “System.Exception: TF30076: The server name {0}MyTFSServer provided does not correspond to a server URI that can be found. Confirm that the server name is correct.“. In order to fix this I had to make a change to the source code and then re-deploy “ThoughtWorks.CruiseControl.Core.dll” to the “C:\Program Files\CruiseControl.NET\server” folder and re-start the windows service. More details here.
  3. Checking for errors: If you make any changes to the config file and don’t see those changes take affect, then try stopping and then re-starting service. The service will fail to start if there are any errors in the config file. If you get any errors while starting your service or when your build process runs, then you can check for the error logs in either the server’s Application log or in CCNET’s log file located over here: C:\Program Files\CruiseControl.NET\server\ccnet.log

Hope this will help someone out there who is just starting off with CruiseControl.NET. Get in touch via comments or email me if you run into any issues or have any queries regarding this post.

{ 3 comments }

I recently upgraded to Windows 7 Ultimate N and installation went very smoothly and I got up and running within minutes.  After playing around around with it for a few minutes, I noticed that the Aero features were not working – so I headed straight to the Control Panel to get my Windows Experience Index computed.   But everytime I clicked on the compute button, I kept getting this error message:

The windows experience index for your system could not be computed.
Cannot complete the requested assesment. This system does not have the necessary multi-media support to run the requested assessment.

After spending sometime Googling, I found out that Windows 7 Ultimate N doesn’t come with Windows Media Player pre-installed.  I headed straight to the link below, downloaded and installed Windows Media Player and computed Windows Experience Index again and now I have a rather impressive score of 4.7!

http://www.microsoft.com/downloads/details.aspx?FamilyID=31017ed3-166a-4c75-b90c-a6cef9b414c4&displaylang=en

Windows Experience Index

{ 0 comments }

Vista & SD card woes

by ambuj on October 15, 2009

in Fixes

I was struggling this evening to get my new SanDisk 2GB SD card working on my Sony Vaio VGN-FZ31S running Vista Ultimate 64 bit.

After spending a lot of time Googling, I found the link below.  A quick download & install and everything seems to be working OK now!

http://h20000.www2.hp.com/bizsupport/TechSupport/SoftwareDescription.jsp?swItem=ob-70996-1

{ 0 comments }

If you’ve ever tried to use a FileUpload control inside an ASP.NET UpdatePanel, you probably already know that you can’t do that. Using the FileUpload control allows you to use the UpdateProgress control to show some sort of indicator that the page is busy. But since we can’t use an UpdatePanel with a FileUpload control, here’s an alternative solution using jQuery and jQuery’s BlockUI extension to display a message while the file is being uploaded. In fact you can use this solution on any page which involves a long running process.

Download: Click here to download the code
Demo: Click here to view the demo

{ 1 comment }