Cruise Control is a continues integration software for build and deploy operations. It will check your source control server in defined intervals and will download & compile the projects if there is a modification on them. It will also inform stakeholders about the outcome of the compile. Cruise Control can use other open source projects like NUnit, NAnt, NCover, FXCop and will work with most of the source control servers available.
I will explain the part "how the Cruise Control will work with Subversion". You need to install Subversion first, create a database and some users, use Margus's service wrapper to run Subversion as a Windows server. First, necessary applications you need to instal:
- Subversion version 1.1.3
- NAnt version 0.85 rc2
- NAntContribute version 0.85 rc2
- NUnit version 2.2.0
- Visual Studio .NET 2003
- Notepad2 (to edit XML config files)
- TortiseSVN (no need to struggle with command prompt)
NUnit has an easy to use installation. NAnt and NAntContrib is distributed as zip files. Unzip them and copy the NAntContrib/bin folder content into NAnt/bin folder. This way NAnt can use the tasks in NAntContrib. Also add the NAnt/bin folder to Environment Variables/Path so the nant.exe can be called from any directory.
You will be needing IIS as well to check the log records. Make sure that default.aspx is defined as the default document when you create a virtual directory.
I have used .NET Framework 1.1 and build scripts are created based on 1.1 framework. NAntContrib and NAnt versions are important. If they are not the same version, you may not be able to call NAntContrib tasks. NUnit version is also important. It should be 2.2.0 otherwise you need to fiddle with "binding redirections" in test config files.
First of all we will create a C# file that is compilable with NAnt. Once this is working we will hand over everything to Cruise Control. Copy paste the below code into Notepad2 and save it as BestCode.cs into CCExample folder.
using System;
//\CCExample\BestCode.cs
namespace KruyzKontrol {
public class Gurkan
{
static void Main(String[] args)
{
Console.Write("CC Example is working");
}
}
}
Try with csc if it is compiling successfully. Now, we will create an NAnt build script to compile. Again, copy & paste the below xml script to Notepad2 and save it as cruise.build into the same folder where your BestCode.cs is.
<?xml version="1.0"?>
<project name="CCExample" default="build" basedir=".">
<description>any description</description>
<property name="debug" value="true" />
<property name="defaultframework" value="net-1.1" />
<target name="build" description="Compiles the code">
<csc target="exe" output="BestCode.exe" debug="${debug}">
<sources>
<include name="BestCode.cs" />
</sources>
</csc>
</target>
</project>
\CCExample\cruise.build
Open a command prompt to the folder where your BestCode.cs is and enter the NAnt command below. We will test if the NAnt is actually compiling our code.
D:\Workbench\CSharp\Deneme\>nant -t:net-1.1
You should see an output telling you that the compile is successful. If there are errors, check the messages and try to correct them.
NAnt will search for a .build file in the folder and when it found, will compile the source based on the data in the .build file. -t parameter is superseding the old parameter -defaultframework and used to indicate that we want to use Framework version 1.1. Check the outputs and make sure the compile has done. There must be one executable and a debug file (.pdb) in the folder.
Now use TortoiseSVN and send the project to Subversion. I have Subversion working with svn: protocol so I can access to my Subversion server with svn://Yoda or I can use IP address of the machine YODA which is svn://192.168.0.1 . Do not forget to create a folder for the project like svn://Yoda/DotNet/CCExample/
Now this is where the pinatas' tail has dropped. We need to get the Cruise Control to do this for us. After you extract the zip of Cruise Control go into the "server" directory. You need to create a file called ccnet.config in this folder containing the xml below. This file will tell the ccnet.exe, what to do.
<cruisecontrol>
<project>
<name>CCDeneme</name>
<webURL>http://Yoda/ccnet</webURL>
<triggers>
<!--<intervalTrigger seconds="30" buildCondition="ForceBuild"/> -->
<intervalTrigger seconds="30" />
</triggers>
<sourcecontrol type="svn">
<!--<executable>c:\program files\subversion\bin\svn.exe</executable>-->
<executable>svn.exe</executable>
<trunkUrl>svn://Yoda/DotNet/CCDeneme</trunkUrl>
<workingDirectory>D:\Workbench\CCDeneme</workingDirectory>
<username>gurkan</username>
<password>gurkanpass</password>
<autoGetSource>true</autoGetSource>
</sourcecontrol>
<build type="nant">
<executable>D:\OpenSource\NAnt\bin\nant.exe</executable>
<baseDirectory>D:\Workbench\CCDeneme</baseDirectory>
<buildArgs>"-D:svn.executable=c:\program files\subversion\bin\svn.exe" -t:net-1.1 </buildArgs>
<buildFile>cruise.build</buildFile>
<targetList>
<target>build</target>
</targetList>
<buildTimeoutSeconds>300</buildTimeoutSeconds>
</build>
<publishers>
<xmllogger>
<logDir>D:\OpenSource\CruiseControl\web\log</logDir>
</xmllogger>
</publishers>
</project>
</cruisecontrol>
Please refer to the Cruise Control documentation for further explanation. Basically, we have a project that is on Subversion and we want to compile with our NAnt script. We also want all the outputs to be recorded in a log folder.
Create a folder under CruiseControl\Web directory and name it as "log". Find the file web.config under CruiseControl\Web and open with Notepad2. Locate the line below:
<add key="logDir" value="log" />
And change it with this one:
<add key="logDir" value="D:\OpenSource\CruiseControl\web\log\" />
Next step is to create a virtual directory in IIS for the CruiseControl\web folder. You may leave all the default settings but make sure the default.aspx is in the default documents.
Now looks like everything is ready to run the ccnet.exe for our first automated compile\integration. Open a DOS prompt to CruiseControl\server directory and run the ccnet.exe. It will use the ccnet.config file and will check the Subversion to see if there is any change on the project. If there is, it will download the project and compile. Every 30 seconds it will check the Subversion again. To trigger the compile, download the project from Subversion with TortoiseSVN to a different directory and make a change. Send the project back to Subversion with TortoiseSVN and keep an eye on the DOS window that the ccnet.exe running.
It is time to see the outcomes on Internet Explorer. Browse to http://localhost/ccnet/default.aspx.
Another way to be notified about the compiles is CCTray application. It is under CruiseControl/CCTray directory. You may copy this folder to another computer on the network to get notifications about the compiles. Run the CCTray.exe and enter your Cruise Control server URL. You should be able to select your project from the drop down list. My settings are:
Server : tcp://YODA:21234/CruiseManager.rem
Project Name: CCExample
If you are accessing the Cruise Control server from another computer on the network, use the IP address or machine name instead of localhost.
What we have accomplished so far:
- Created a project which can be compiled with NAnt.
- We have written ccnet.config to get the connection between Cruise Control and Subversion.
- CCNet.exe is now controlling the Subversion source control.
- When there is a modification on the Subversion, it has been picked up and compiled.
- We can see the results from web.
- CCTray.exe notifications are working.
What about NUnit Tests
It would be good if we can run the NUnit tests on this project and see the results on Cruise Control web page. You may give a break to ccnet.exe. We will first integrate NAnt and NUnit. When we get a successful test, we will try to see the test results on Cruise Control.
This time create a Visual Studio class project and add a reference to NUnit.Framework assembly. Modify the class1.cs to look like the below code.
using System;
using NUnit.Framework;
namespace KruyzKontrol{
/// <summary>
/// Summary description for Class1.
/// </summary>
[TestFixture]
public class Class1{
public Class1(){
//
// TODO: Add constructor logic here
//
}
[Test]
public void FailTest(){
Assert.Fail("This test will fail and CC will show the message to me");
}
}
}
Save the project somewhere else (other than CCExample folder) with the name Test and send it to Subversion with TortoiseSVN under CCExample\Test.
We will have some modifications on the cruise.build file to integrate with NUnit tests. We need to clean up the test folder if exist, download NUnit test project from Subversion, compile both test project and BestCode.cs and execute the tests. When we get everything up and running, we will handover the process to Cruise Control and sit back & relax. Below is the modified version of the cruise.build file.
<?xml version="1.0"?>
<project name="CCExample" default="build" basedir=".">
<record name="Buildlog.txt" level="Info" action="Start"/>
<description>any description</description>
<property name="debug" value="true" />
<property name="defaultframework" value="net-1.1" />
<target name="build" depends="get">
<csc target="exe" output="BestCode.exe" debug="${debug}">
<sources>
<include name="BestCode.cs" />
</sources>
</csc>
<solution configuration="debug" solutionfile="Test\CCTest.sln" />
<nunit2>
<formatter type="Xml" />
<test assemblyname="Test\bin\debug\CCTest.dll" />
</nunit2>
</target>
<target name="get" depends="clean">
<svn command="checkout"
uri="svn://Yoda/DotNet/CCExample/Test"
destination="D:\Workbench\CCExample"
username="gurkan"
password="gurkanpass"
verbose="true"/>
</target>
<target name="clean" >
<delete dir="Test" failonerror="false" />
<mkdir dir="Test" />
<delete file="BestCode.exe" failonerror="false" />
<delete file="BestCode.pdb" failonerror="false" />
</target>
<record name="Buildlog.txt" action="Close"/>
</project>
<URI> is the Subversion folder where your test project resides.
<DESTINATION> is the working directory for the test project.
There are multiple targets in this one and they are dependant to each other. First the "clean" target will clean up the existing folders, "get" target will download the test project from Subversion, "build" target will compile the projects and execute the NUnit tests. Open a command prompt to the project folder and enter the below command.
D:\Workbench\CSharp\Deneme\>nant -t:net-1.1
If you are seeing an error message saying that build failed, then everything is okay. This is what we want. Now we may handover the process to Cruise Control. Run the ccnet.exe and browse to http://localhost/ccnet/default.aspx. Check the builds and see the error message that we have setted in the code.