Building your own Continuous Integration Server

The benefits of setting up a CIS are just too obvious

Setting up a Continuous Integration Server This is more of a personal Note to myself than a tutorial. You will not leave this post feeling that you know all the tools. You will have to spend time with their docs and get a little frustrated at times, but hey you live you learn.. You will need the following things.

Step 1. This is easy. Ensure that you have a working build by opening the workspace/solution file in the IDE and doing a complete build. Now we use this as a base for Step 2.
Step 2:Making an NAnt build file. Please unzip and READ THE DOCS folder in the nant zip. I found the docs really cool - nothing that makes you read and read and read and zzz. You can keep skimming thru the docs when you hit a dead end. Find the solution and forge ahead. The core concept is simple. The build file has tasks like a batch file has commands. But the tasks are inherently more powerful and configurable or else they wouldn't exist. Take a print of the NAnt tasks list - quick reference at a glance. So here's what I came up with..

GC.build

G TIP

<?xml version="1.0"?>
<!-- NAnt build script for a VS.NET solution
Gishu Sep 14, 2005.
Email: gishu<dot>pillai<at>gmail<dot>com -->
<project name="GC" default="debugBuild">
<property name="ReleaseOutputDir" value="bin\release" />
<property name="SolutionFilePath" value="source\GC.sln" />
<target name="clean" description="Cleans binaries folder">
<delete dir="${OutputDir}" verbose="true" failonerror="false"/>
<mkdir dir="${OutputDir}" failonerror="false" />
</target>
<target name="debugBuild">
<property name="OutputDir" value="bin\debug" />
<property name="BuildConfig" value="Debug" />
<call target="clean" failonError="false"/>
<call target="build"/>
</target>
<target name="build">
<exec program="..\GC_CheckOut.bat" />
<echo message="Source Checkout complete" />
<solution configuration="${BuildConfig}" solutionfile="${SolutionFilePath}" verbose="true" > <assemblyfolders>
<includes name="C:\Windows\Microsoft.NET\Framework\v1.1.4322\**" fromPath="true" /> </assemblyfolders>
</solution> </target> </project>

  • The .NET solution has a pesky hintpath property for framework DLLs. Running the solution task looks up the hardcoded HintPath value and fails. To go around this, you need to add an AssemblyFolders element to the solution task, with the path to the Framework installation on the current machine. This can be a property/constant defined at the top of the build file.
  • Next, another thing that I overlooked in my exuberance is that NAnt.exe.config take framework 1.0 as the default. Change this is you are using Framework 1.1 or else meet Mr. Build Failure. When I found this, I felt specially stupid since I had done the same thing on my last attempt at home. This time I'm gonna DOCUMENT IT HERE!!!.
  • Use the new (and uber cool) solution task. It does not require the IDE and blah blah to be installed. What it does is that it parses the solution file and invokes csc ( long live the command line ) after resolving references. Now ain't that sweet ? It doesn't use devenv - less resources required and faster. I read this from DevX.

Step 3: Meet Cruise Control.NET CruiseControl is another Rad tool which will help complete our Continuous Integration Server. Configure your CruiseControl.NET Server: You need to make a ccnet.config file to make your server do something useful. Start with the \Doc\CCNET\CruiseControl.NET Server.html under the CC installed directory. You will need to write your specific sourcecontrol block, based on what you actually use. G TIP This tool will only detect an update to the SourceControl Server and then give you a callback. You have to write a script to check out the changes. CC won't do it for you. This was something I learned the hard way. So you need to write a script that will checkout the latest source. This will depend on exactly what you use - I have tried Subversion and StarTeam. Both would be different scripts - see their command line documentation for details. I have built myself a batch file. There I go putting my foot in my mouth. The Subversion block did not have this option but I now see that Starteam sourcecontrol block has a [autoGetSource]true[/autoGetSource] entry. I'll try that out later and update this post. For now I'll stick to my batch file (which I have verified works from the prompt).

Listing: Sample CC config file

<cruisecontrol>
<!-- My Second CruiseControl Config File
Gishu Sep 14, 2005.
Email: gishu<dot>pillai<at>gmail<dot>com -->
<project name="GC">
<sourcecontrol type="starteam">
<executable>c:\Program Files\Starbase\StarTeam 5.4\stcmd.exe</executable>
<project>GC.net/GC.net</project>

<username>buildGuy</username> <password>buildPwd</password>
<host>XX.XX.XX.XXX</host> <port>50000</port>
<path>/GC/Source</path>
<autoGetSource>false</autoGetSource>
</sourcecontrol>
<tasks>
<nant>
<baseDirectory>E:\GC\RootBuild</baseDirectory>
<buildFile>GC.build</buildFile>
<buildTimeoutSeconds>1200</buildTimeoutSeconds>
</nant> </tasks>
<triggers> <intervalTrigger seconds="1800" buildCondition="ForceBuild"/> </triggers> <publishers> <xmllogger><logDir>E:\Program Files\CruiseControl.NET\server\GCLogs</logDir></xmllogger> </publishers>
</project> </cruisecontrol>

Copy the ccnet.config file to your CruiseControl.Net\Server directory. Ensure that Nant is on your PATH EnvVar so that CC can find it. Now pray to your favourite God and double-click the ccnet.exe file in the server directory. This should start the CC Server. (SP2 might try to throw a spanner in the works. Click on Unblock).

G TIP

  • In case of people like me, this generally blows up. So what you do is start a command prompt and start the exe from within the command window. This gives you a chance to look at what blew up. Common things - incorrect paths, locked log files (Stop any running servers first), etc.Ok looks like I got my StarTeam folder project and view names wrong. Backspace Backspace Type Type. That’s it !

Now I can open my web dashboard http://localhost/ccnet to view a whole lot of things on a web page, totally FREE. Not an iota of effort put in. That’s the kinda of thing I like. I had a lotta fun doing this and this will help me have a lot of fun in the future rather than sit here verifying builds. I have got better things to do.. If you have any issues/suggestions or things that you feel I should know, post a comment here. I’ll try my best to get back.. Ciao!

KILLJOY FootNote

Source control servers across WANs rob you of most of the joy with a CIS. E.g. My experiment showed that a project which takes around 17 secs to build from the command prompt with an NAnt script, will take ~11 mins! What the @#%^!!! Allmost all the time is spent in network operations for the SourceControl app (Starteam here), even when checking out only the changes. Still I feel that the benefits justify the time spent even though you have to wait for some time to see the green light. Another excuse for a break :)

Update
Starteam is absolutely horrendous. If you have ST as the source control and it is also across a WAN, please stick with doing all this manually. Take this from me..


2 comments:

  1. UPDATE
    ------

    Found another cool thing with CruiseControl.
    I found that someone who needed the binaries always found that he came in at the exact moment that a build was in progress (I clear the output folders before each build and so should you.). As a result he had to wait till the build completed and pray that no one issues a devious "Force Build" again.
    So what I needed was a way to copy the binaries to a separate folder each time I had a successful build. A little bit of looking and once again CruiseControl inherently supports this via a build publisher (It's a beautiful world!).
    See below code snippet. The thing of importance here is the SourceDir (build output dir) and the publishDir (GoodBuilds folder) elements. CruiseControl will create a folder with the latest build label (e.g. 12) and copy the contents of the output dir there. So you just need to share the publishDir to everyone who requires the binaries. Simple and sweet!

    <publishers>
    <buildpublisher>
    <sourceDir>E:\GC\RootBuild\bin</sourceDir>
    <publishDir>E:\GC\LastGoodBuild</publishDir>
    </buildpublisher>
    <xmllogger><logDir>E:\Program Files\CruiseControl.NET\server\GCLogs</logDir></xmllogger>
    </publishers>


    Ditto with NAnt. NAnt has a very nice mailing list. With the latest version, I found that there is no need to tweak the runtime version in the nant.exe.config file as I mentioned in the above post.
    NAnt now automatically looks for v2.0, 1.1 and 1.0 in that order. I kept forgetting the .config file modification each time I setup Nant on a new machine. Good one guys!

    ReplyDelete
  2. On my personal machine, I found that CruiseControl dashboard never worked without a wrestling bout with me. The error page asked me to "add an application extension mapping". However on my machine, I always found OK disabled on that particular dialog ( My Computer > Manage > Services > IIS > Virtual Folder properties ).
    The answer is here at
    href="http://forums.devarticles.com/web-server-configuration-51/iis-problem-unable-to-add-application-extension-mapping-2527.html
    and http://www.west-wind.com/wiki/kb.wiki?wc~XPGotchas
    Answer: you need to click in the application textbox once to enable the OK Button. This was pretty frustrating for some time.

    After that I was able to see the dashboard page. However it kept saying 'unable to connect to server' the 'actively refused connection' bit. This after CCTray was working perfectly!! I got another tip at the comment by Malcolm Anderson at http://joefield.mysite4now.com/blogs/blog/articles/146.aspx
    I haven't tried it yet but the problem is an exact match. The suggested solution is to ensure that the CCNet service is running. I would have never thought of that one.

    ReplyDelete