You are on page 1of 11

Setting Up a Build Server - Part 1 (Subversion)

By Mgordon11. Thng Ba 2008 07:54


For the past several months, we've been using a build server on our project for continuous
integration. I've been involved with teams, in the past, that used build servers, but this particular setup
has proved to to be a real asset and the experience of using it day-to-day has been a pleasure.
I'd like to share how we built the server. I'll make several posts over the next few days to address the
various parts that work together. Along the way, I'll discuss version control (subversion in our case),
Cruise Control .Net, NAnt and StatSvn.
What We're Trying to Accomplish
Why would you want a build server, anyway? The primary benefits of a build server are continuous
integration and automation. Let's say you have a team of five and all are working on the same
project. Each has a piece of the application that they're working on. As they develop, they test the code
they're responsible for. Who, though, is responsible for making sure that all the pieces work
together? The reality is that at any given time each developer's machine has a unique version of the
application that's different everyone else's. The purpose of the build server is to periodically take the
code that exists in the source repository and process is to verify the code all works together. In other
words, the health of the code (how well all the parts integrate) is always known.
There are many functions the build server can perform. It can do a compile, execute test suites, generate
an installer or even a CD image. Crucial to the whole process is source control, so let's look at getting
started with Subversion.
Subversion
All source code repositories have their own take on how best to solve the problem of keeping up with all
the changes made to to the code base. Some require the developer to lock a file while it's being worked
on, while others allow changes to be made by anyone at any time. Subversion falls into the latter
category. Basically, a developer grabs a snapshot of the current version in the repository, makes his
changes and then pushes them back up. Committing of changes happens in a transaction so the
commits are always stable. Subversion takes the version being committed and merges it into the current
version in the repository. This means that manual merging is greatly reduced. On the occasions when
Subversion can't figure out how to merge the changes, the developer is notified and is give an opportunity
to manually do the merge.
Installation
You can obtain the subversion installer here. I downloaded the installer, svn-1.4.6-setup.exe, and
executed it taking all the defaults. At this point, all the binaries are installed on your system, but
Subversion hasn't been configured to run as a Windows Service. To set it up to run this way, execute the
following from a command line.
C:\>sc create svn binPath= "\"c:\program files\subversion\bin\svnserve.exe\" --service -r c:\repos"
DisplayName= "Subversion Server" depend= Tcpip
This command will create a Windows service named "Subversion Server" that runs svnserve.exe when
it's started.
Subversion Client
Regarding a client that you'll use for interacting with your Subversion server, you'll need to decide
whether you prefer to have the client integrated into Visual Studio or not. If having everything available
within the IDE is you bent, then you'll likely prefer something like AnkhSVN. Personally, I'd rather do
my source repository work outside the IDE and prefer to use TortoiseSVN which installs as a shell
extension. Either way, you'll need to create a repository and then connect to it with your client.
Creating and Configuring a Repository
On the machine on which the Subversion service is running, create a folder in which you'll be storing your
code repository. Then, go to a command line and execute the following.
svnadmin create c:\path-to-repos
This will create a repository for you in the directory you created. Now, we need to configure access to the
repository. Go to the folder you created, before, and you'll find that three files have been created
there. First, open the svnserve file. All the lines in the file are currently commented out. You'll need to
modify at lease three of these lines. Find the line that contains "anon-access". This line controls what
access users connecting to the repository anonymously have. Your options are "read", "write" and
"none". In my case, I set this value to "none". Next, find the line that contains "auth-access" and set its
value to either "read", "write" or "none". this line controls what access authenticated users will have. For
the last change, find the line that contains "password-db" and remove the "#" character and the space
that follows it to un-comment the line. This tell Subversion to look in the passwd file to find a list if valid
users of the repository. Save your changes to this file.
Now, open the passwd file. All lines in this file are commented out, as well. Beneath the line "[users]",
you will need to create a list of valid users for the repository in the form "username = password". Save
your changes.
Accessing the Repository From a Client
Whichever client you choose, you'll need to specify a URL and your credentials. URL's for subversion are
of the form svn://server-name. For credentials, you'll need to use one of the user-name / password
combinations you created in the passwd file, earlier. At this point, you should be able to check out (get a
copy of the current version) and commit (check in) to and from your repository. If, however, you're having
problems reaching the server you'll want to check that the Subversion service is running and you also
may need to configure svnserve.exe as an exception in windows firewall.
That's it for Subversion. Next time, we'll set up CruiseControl.Net.
Setting Up a Build Server - Part 2 (Cruise Control .Net)
By Mgordon24. Thng Ba 2008 06:41
In continuation of the series I started last time, I'll look at the part Cruise Control .Net plays in the creation
of a build server today.
All the individual parts of a build server would be of little use if they were all working alone. There needs
to be some entity responsible for orchestrating the workings of and communication between the individual
parts. The software we've used for this purpose is Cruise Control .Net. It's job will be to initiate a
build. We can tell it we'd like a build every time a configured amount of time passes or whenever a new
version of the code base has been checked into our repository.
First, you'll need to install the product on your build server. You can download the installer, here.
Execute the installer and take the defaults. In particular, on the select components page of the
installation wizard, choose to install the CruiseControl.Net server, the Web Dashboard and the
examples. The server component is what we'll be configuring to do the work of initiating builds, the web
dashboard will allow you to check the results of each build via a web interface and the examples will help
you to learn how to configure the server.

On the additional configuration page, select both to install the server as a windows service and to create
a virtual directory for the web interface.

When the installer has finished, we need to configure our server. To do so, navigate to C:\Program
Files\CruiseControl.NET\server and open the file ccnet.config. The file will contain this text:
<cruisecontrol>
<!-- This is your CruiseControl.NET Server Configuration file. Add your projects below! -->
<!--
<project name="MyFirstProject" />
-->
</cruisecontrol>
Our task, now, is to replace the contents of this file with XML that will tell CruiseControl when and how to
perform a build. As a start, replace the file contents with this text.
<cruisecontrol>
<project name="MyProject" >
<webURL>http://servername/ccnet/</webURL>
<triggers>
<intervalTrigger seconds="60" />
</triggers>
<modificationDelaySeconds>60</modificationDelaySeconds>
<sourcecontrol type="svn">
<executable>c:\program files\subversion\bin\svn.exe</executable>
<workingDirectory>c:\build\source\ProjectName</workingDirectory>
<trunkUrl>svn://localhost/repository/path/to/project</trunkUrl>
<username>uname</username>
<password>password</password>
</sourcecontrol>
<tasks>
<nant>
<executable>c:\nant\bin\nant.exe</executable>
<baseDirectory>c:\build\source\ProjectName</baseDirectory>
<buildFile>c:\build files\Project.build</buildFile>
<targetList>
<target>TargetName</target>
</targetList>
<buildTimeoutSeconds>600</buildTimeoutSeconds>
</nant>
</tasks>
<publishers>
<xmllogger />
<statistics/>
</publishers>
</project>
</cruiseControl>
All the values in red will need to be modified to suit your specific needs and setup. Beginning at the top,
you'll need to specify your own project name. Next, specify the name of your build server in the
webURL. The intervalTrigger is the amount of time that CruiseControl will allow to elapse between each
check for changes and indicates that you want CruiseControl to initiate a build when the code base
changes (after a check in). There are other trigger types you can specify. Check the documentation for
these other types.
Next, the modificationDelaySeconds is the amount of time to wait between detecting a code base change
and initiating a build. This allows time for subsequent check ins to be completed before a build starts. As
you can see, we have specified SVN as out source control type (CruiseControl works with several other
repositories, as well). We need to tell CruiseControl where to find the svn.exe executable. Also, we need
to specify a folder into which the code base can be checked out. To detect changes in the code base,
CruiseControl uses a Subversion command to check for updates. This command effectively compares
the local copy of the code base with the version on the Subversion server. I suggest you determine
where you'd like this local version to reside, create the folder if necessary and then check the code base
out into that folder. Then specify the path to that folder as the baseDirectory. trunkUrl is the path, in the
repository, where the code base can be found. Next is the username and password to use when
accessing the repository.
We'll skip the nant section, for now, and cover it next time. The publishers section is important because if
no publishers are specified, you won't be able to see any of the results of the build in the web
dashboard. The function of a publisher is to take the raw output from the various tools we'll use, capture
it and format it into a format that can be viewed in the dashboard. Here we have specified the xmllogger
and statistics. There are other options available. See the documentation for CruiseControl to check them
out.
So, at this point, we have our source control repository and a server that detects when the source has
changed. We have yet to specify what the actual build process is, however. We'll discuss that, next time,
where we look at nant.
Setting Up a Build Server - Part 3 (NAnt)
By Mgordon1. Thng Tu 2008 13:21
So far, in this series, we've installed and configured Subversion for source control and installed and
partially configured CruiseControl.Net as a continuous integration server. This time, we'll look at a utility
called NAnt which provides a declarative way of specifying tasks that are to be performed - specifically,
tasks to be completed during a build.
A NAnt script is an XML document containing nodes that the NAnt engine understands. By carefully
creating a NAnt script, we can have the tool automate many tasks for us at build time. NAnt can be
downloaded from the site, hereand the documentation is here. NAnt is powerful, out of the box, but its
functionality can be extended by also obtaining the NAnt Contrib library which contains additional tags
you can use in your script file.
To install NAnt, Download the zip file containing the binary files and unzip the archive to a folder on your
hard drive. You'll probably want to make this folder as shallow as possible (c:\nant) since you'll be
specifying this path in CruiseControl.Net setup and possibly on the command line for testing you
scripts. As an alternative, you can place the code anywhere and add the path to the bin folder beneath
the root folder to the path variable.
Next, download the NAntContrib library and unzip the contents of the downloaded archive to a different
folder. Now, copy the contents of the bin folder beneath where you unzipped NAntContrib into the bin
folder beneath where you placed NAnt. You should now be ready to start building scripts.
NAnt looks for its instructions in a file with a .build extension. As I said before, this file contains XML. I
won't try to teach you all there is to know about NAnt (I don't know it all, anyway), but I'll try to give you
enough of the basics to get you stared on a firm foundation. The root node of a build file looks like this.
<?xml version="1.0" encoding="utf-8" ?>
<project name="Rtc.Fx" default="CopyFiles" basedir="."
xmlns="http://nant.sf.net/release/0.85/nant.xsd">
</project>
The root node is a <project> node and specifies the project name and a default task. The build file is
broken up into separate tasks and the default attribute indicates which task to begin with. There may be
certain values we'll want to use over and over in our build file or that we'll want to calculate. We can work
with these as properties.
<property name="month" value="${datetime::get-month(datetime::now())}"/>
<property name="day" value="${datetime::get-day(datetime::now())}"/>
<property name="year" value="${datetime::get-year(datetime::now())}"/>
<property name="hour" value="${datetime::get-hour(datetime::now())}"/>
<property name="minute" value="${datetime::get-minute(datetime::now())}"/>
<property name="second" value="${datetime::get-second(datetime::now())}"/>
<property name="buildDirName" value="build_${month}-${day}-${year}_${hour}-${minute}-
${second}"/>
<property name="sourceDirName" value="source_${month}-${day}-${year}_${hour}-${minute}-
${second}"/>
Insert these inside the root node. As you can see, we're calling available functions to obtain values for
parts of the current date and time. These are stored in parameters have the name specified in the name
attribute. We've calculated names, here, for our source and destination folders. Often, you'll want to
save versions of code on your build server for a while and creating new folders with the date and time in
the name is an easy way to identify when the snapshot was pulled down for a build. Now let's actually do
something. Let's start by pulling the current version of our source code down for a compile.
<?xml version="1.0" encoding="utf-8" ?>
<project name="Rtc.Fx" default="CreateTags" basedir="."
xmlns="http://nant.sf.net/release/0.85/nant.xsd">
<property name="month" value="${datetime::get-month(datetime::now())}"/>
<property name="day" value="${datetime::get-day(datetime::now())}"/>
<property name="year" value="${datetime::get-year(datetime::now())}"/>
<property name="hour" value="${datetime::get-hour(datetime::now())}"/>
<property name="minute" value="${datetime::get-minute(datetime::now())}"/>
<property name="second" value="${datetime::get-second(datetime::now())}"/>
<property name="buildDirName" value="build_${month}-${day}-${year}_${hour}-${minute}-
${second}"/>
<property name="sourceDirName" value="source_${month}-${day}-${year}_${hour}-${minute}-
${second}"/>
<target name="GetSolution" description="Get Solution Files from Subversion">
<mkdir dir="c:\build\source\Rtc.Crm\${sourceDirName}"/>
<svn-checkout
destination="C:\Build\source\Rtc.Crm\${sourceDirName}"
uri="svn://localhost/rtc_repository/RTC/Rtc.Crm"
quiet="true"
username="uname"
password="pword"
/>
</target>
</project>
Tasks, in NAnt, are called targets. More on why they maybe called this and how to control the flow of
execution in a minute, but for now look at the target we added. It has a name of GetSolution and an
optional description. Inside each target, we can specify zero or more actual action that need to take
place. In this example, a new directory is being created to place the source code into by using the mkdir
tag. It will have the name we calculated in the parameter, above. In NAnt, a property(Variable, Function
all, anything that returns a value) is accessed by surrounding it with ${}. Once the directory is prepared
for our source code, we'll ask Subversion to check our code out into the new folder by using the svn-
checkout tag. We specify a destination for the source code, the uri path inside the repository where the
source code is located, a user name and a password for an account having access to the
repository. When this tag is encountered, the code will be checked out for us. Now, let's specify another
target that will build our code.
<?xml version="1.0" encoding="utf-8" ?>
<project name="Rtc.Fx" default="CreateTags" basedir="."
xmlns="http://nant.sf.net/release/0.85/nant.xsd">
<property name="month" value="${datetime::get-month(datetime::now())}"/>
<property name="day" value="${datetime::get-day(datetime::now())}"/>
<property name="year" value="${datetime::get-year(datetime::now())}"/>
<property name="hour" value="${datetime::get-hour(datetime::now())}"/>
<property name="minute" value="${datetime::get-minute(datetime::now())}"/>
<property name="second" value="${datetime::get-second(datetime::now())}"/>
<property name="buildDirName" value="build_${month}-${day}-${year}_${hour}-${minute}-
${second}"/>
<property name="sourceDirName" value="source_${month}-${day}-${year}_${hour}-${minute}-
${second}"/>
<target name="GetSolution" description="Get Solution Files from Subversion">
<mkdir dir="c:\build\source\Rtc.Crm\${sourceDirName}"/>
<svn-checkout
destination="C:\Build\source\Rtc.Crm\${sourceDirName}"
uri="svn://localhost/rtc_repository/RTC/Rtc.Crm"
quiet="true"
username="build"
password="build"
/>
</target>
<target name="build" description="Build Core Solution" depends="GetSolution">
<exec program="c:\program files\Microsoft Visual Studio 8\Common7\IDE\devenv.com"
commandline="c:\build\source\Rtc.Crm\${sourceDirName}\Rtc.Crm.Sln /build Release"></exec>
</target>
</project>
We've added a new target, now, called build. Notice the depends attribute. This attribute, in effect, says
don't run this target until the GetSolution target has finished. This is how you can control the flow of your
targets. If we make the build target the default (on the root node), NAnt will come to the build task and
see that it can't execute it until GetSolution has run, so it puts build on hold and goes to execute
GetSolution. Once it's finished, the build target is executed. In the build target, we're using the exec tag
to build our code. You could use compile tags in the NAnt libraries to compile your code, as an
alternative (or MSBuild, the C# compiler or whatever), but I have found that it's hard, sometimes, to keep
the .Net version and the NAnt version in sync. For this reason...stability...I prefer to use the exec task
and specify a command line to execute.
From here, you can use any of the provided tags to round out all the tasks you want to automate in your
build. You could copy the binaries just compiled to a deployment location, run NUnit tests, create a cd
image file or whatever is needed.
Integrating NAnt into CruiseControl.Net
Last time, we left our CruiseControl config file looking like this...
<cruisecontrol>
<project name="MyProject" >
<webURL>http://servername/ccnet/</webURL>
<triggers>
<intervalTrigger seconds="60" />
</triggers>
<modificationDelaySeconds>60</modificationDelaySeconds>
<sourcecontrol type="svn">
<executable>c:\program files\subversion\bin\svn.exe</executable>
<workingDirectory>c:\build\source\ProjectName</workingDirectory>
<trunkUrl>svn://localhost/repository/path/to/project</trunkUrl>
<username>uname</username>
<password>password</password>
</sourcecontrol>
<tasks>
<nant>
<executable>c:\nant\bin\nant.exe</executable>
<baseDirectory>c:\build\source\ProjectName</baseDirectory>
<buildFile>c:\build files\Project.build</buildFile>
<targetList>
<target>TargetName</target>
</targetList>
<buildTimeoutSeconds>600</buildTimeoutSeconds>
</nant>
</tasks>
<publishers>
<xmllogger />
<statistics/>
</publishers>
</project>
</cruiseControl>
We can, now, complete the section in red. The executable tag contains the path to the NAnt executable
and the buildFile tag the path to the build file we just created. The baseDirectory is where NAnt will do its
work and the targetName is the name of the target within the build file to execute first. You can also
specify a timeout for the build.
So, the config file as it stand now will check Subversion every 60 seconds to see if there have been any
changes checked into the repository. If so, CCNet will pause for 60 seconds to give the developer
enough time to complete checking in all their code and then initiate a build. Now CruiseControl will look
at all the tasks in the tasks section of the config file. Here, there is one and that is to execute our NAnt
script.
If you code the defaults when you installed CC.Net, you should be able to browse
to http://buildServerName/ccnetand take a peak at the CCNet portal. Make sure the Cruise Control
service is started! The portal looks like this.

From here, you can look at the progress for all your projects and builds. Notice the link in the upper right
to the documentation. There is also a link on the far left to download CCTray, which is a utility that runs in
the system tray and lets you know, at a glance, the health of your builds and double-clicking on the icon
will open a utility that offers more functionality.
Next time, we'll look at how to get metrics from your subversion database as part of your build process.

Setting Up a Build Server - Part 4 (StatSvn)
By Mgordon2. Thng Tu 2008 05:52
So, now we have a build server including source control, a mechanism to monitor our source code and
trigger builds and a utility in place to allow us to automate actions like compiling, running unit tests,
deploying files. We can also look at the Cruise Control web application to track our builds, their progress,
success, failure.
This time, we'll take a look at a package called StatSvn which tracks the changes made to your code
base and generates informative reports from what it sees. Let's dig right in to setting it up.
First, you'll need to download the software from here. You'll be downloading a zip file which needs to be
expanded into a directory on your build server. In that directory, you'll find a jar file, so you know right
away you need to install the Java runtime on the build server. You can find the runtime here. After
insuring the runtime is installed, you'll need to create a new directory on the server to contain a running
current version of your code base. StatSvn will be using the code in this directory to generate its reports
from. After creating the directory, check the current version of the code base into it.
We'll be calling StatSvn from our build script. Since there are several steps to working with StatSvn, I
create a bat file containing all the steps and then call it from the build script. So, create a new bat file
(Stats.bat) on the root of a drive on the build server. It should contain something like the following.
c:
cd c:\stats
del *.html
del *.png
cd "c:\StatCode"
svn up
svn log --xml -v > svn.log
cd c:\stats\
java -jar statsvn.jar "c:\StatCode\svn.log" "c:\StatCode"
Here, I'm changing the current drive to c: and then changing the current path to where I unzipped the
StatSvn jar file. When the jar is executed, it creates several html and ping files in its current directory. I
start, then, by deleting all these from the last run. Next, I change the current path to point to the directory
into which I checked out the current version of my code base. I then call the Subversion command line
utility, svn, and pass it a parameter or "up". This tells subversion to update the local copy of my code with
what's on the server. Now, I call the Subversion command line, again, and ask it to create a log file for
me, called svn.log, in XML format. This file will be created in the same folder my source code is in. Last,
I change the local path back to where I unzipped the StatSvn archive and execute the jar file telling it
where my log file and code base is. The result of this is the creation of html and image files in the
StatSvn folder containing reports about my source code. Let's tie this process into the build script.
Last time, we looked at using the <exec> element in our NAnt script to execute command line
statements. To add the batch file to our build, therefore, all we need to do to add a call to our batch file is
to either create a new target or use an existing target and add this task inside it.
<exec program="C:\stats.bat"></exec>
Now, how do we view the generated reports? Generally, you'll want to make sure IIS is installed on your
build server and create a virtual directory that points to the StatSvn folder. Be sure to set the default page
to index.html. Once you do this, you'll be able to navigate all the generated content with your
browser. There are examples of the generated reports on the StatSvn web site for you to check out.

You might also like