fredag, december 29, 2006

Continuous Build using CruiseControl & Visual Studio 2005

In order to make sure that my projects are always up-to-date I spend a couple of days this month to figure out how to set up a Continuous Build system.

Since this is just a hobby project of mine I had to use open source software, so MS Team System was not a option ( I am not even sure whether Team System is up to the challange ).

In the past I used Team Coherence as my Source Control system of choise, but resently I changed to Subversion which is a great tool. I have used NUnit on most of my projects the last year so the question was how to set up a system that would:
1) Check out the tip/head revision from Subversion
2) Build the thing
3) Run the unit test
4) Report back

I soon realized that CruiseControl.NET was the tool that should control the flow. Below is the XML file (ccnet.config) that specifies the steps that CruiseControl controls:

- "<cruisecontrol>
- <project name="Persolit Kalkulation udvikling">
- <triggers>
<intervalTrigger name="continuous" seconds="600" buildCondition="ForceBuild" />
<scheduleTrigger time="23:05" buildCondition="ForceBuild" />
triggers>
- <sourcecontrol type="svn">
<executable>C:\Programmer\Subversion\bin\svn.exeexecutable>
<trunkUrl>file:///C:/Subversion/PersolitKalkulationtrunkUrl>
<workingDirectory>C:\System udvikling\C#\Persolit KalkulationworkingDirectory>
sourcecontrol>
- <tasks>
- <exec>
<executable>C:\Programmer\Subversion\bin\svn.exeexecutable>
<buildArgs>checkout file:///C:/Subversion/PersolitKalkulation d:/build2buildArgs>
<buildTimeoutSeconds>100buildTimeoutSeconds>
exec>
- <nant>
<executable>C:\Programmer\Nant\bin\nant.exeexecutable>
<baseDirectory>d:/build2/Persolit KalkulationbaseDirectory>
nant>
tasks>
- <publishers>
- <email from="an email adress" mailhost="smtp">
- <users>
<user name="BuildGuru" group="buildmaster" address="kasperbolarsen@gmail.com" />
users>
- <groups>
<group name="buildmaster" notification="change" />
groups>
email>
<xmllogger />
publishers>
project>
- <project name="ContainerCheckCipher">
- <triggers>
<intervalTrigger name="continuous" seconds="600" buildCondition="ForceBuild" />
<scheduleTrigger time="23:05" buildCondition="ForceBuild" />
triggers>
- <sourcecontrol type="svn">
<executable>C:\Programmer\Subversion\bin\svn.exeexecutable>
<trunkUrl>file:///C:/Subversion/ContainerCheckTooltrunkUrl>
<workingDirectory>C:\System udvikling\C#\ContainerCheckToolworkingDirectory>
sourcecontrol>
- <tasks>
- <exec>
<executable>C:\Programmer\Subversion\bin\svn.exeexecutable>
<buildArgs>checkout file:///C:/Subversion/ContainerCheckTool d:/ContainerCheckToolbuildArgs>
<buildTimeoutSeconds>100buildTimeoutSeconds>
exec>
- <nant>
<executable>C:\Programmer\Nant\bin\nant.exeexecutable>
<baseDirectory>d:/ContainerCheckTool/ContainerCheckCipherbaseDirectory>
nant>
tasks>
- <publishers>
- <email from="an email adress" mailhost="smtp">
- <users>
<user name="BuildGuru" group="buildmaster" address="kasperbolarsen@gmail.com" />
users>
- <groups>
<group name="buildmaster" notification="change" />
groups>
email>
<xmllogger />
publishers>
project>
cruisecontrol>"




Every 300 seconds CC.net will do a ForceBuild
In the Task - Exec section I have specified the path to the Subversion executable which will use the buildArgs "checkout file:///C:/Subversion/PersolitKalkulation d:/build"
(Note: spaces in the project name made it very difficult for me to get the syntax right, none of my future Subversion project will contain any spaces that is for sure)
This will check out the Head revision of the PersolitKalkulation project to the folder D:\build
Then I ask the NAnt executable to "do its magic" in the specified folder. NAnt will look for any file named *.build in that folder and use that file as arguments ( the *.build file is off cause saved as part of the solution in Subversion.




The NAnt build file contains the instructions needed to run MSbuild against the solution file (sln) in the project, then I copy the app.config file to the build folder, in this case both the Debug and Release folders.

Most blogs suggests that the build and running the Unit Tests should be carried out in the Nant process rather than the CruiseControl process, and I have to agree. I tried to make it work from the CC process but had to give in after spending some 6 hours on that issue.

Now that the build is complete I call the NUnit2 section in order to run the unit test in the exe file. In bigger project I would prefer to place the unit tests in a separate project within the same solution, but since this is just a small project I have chosen to place the tests in the main assembly.

Whenever the build status changes I get an email but I usual starts CCTray (included in the package from CruiseControl) which will notify me each time a build have been completed (or failed).

I have not yet been able to get a full report in the CruiseControl dashboard about the unit tests but I guess I'll update this post once the build configuration has been put to the test.