Rants, rambles, news and notes from another geek

NAnt Build Files for Continuous Integration BoF

I have a few minutes tonight, so in case anyone asks, I wanted to share my barebones build files that I put together for my CI BoF tomorrow night. These are two very simple NAnt scripts that you can use with a Cruise Control .NET (CCNET) setup. One of my biggest goals when putting these together was to make them as reusable as possible. I wanted to be able to take these from one project to the next and not have to make tons of edits to get them to work. Since my demo uses Subversion for source control, these files reference the SVN.EXE command line tool. If should be a simple matter to switch to a different provider.

The first one is the CCNET Bootstrapper file. The basic purpose of this file is to be the one that CCNET can use to clean, checkout and then build the project. I don’t include this file in the actual project source tree. Rather it is part of the CCNET setup. It is completely parameterized so that the same file can be used for multiple CCNET projects on the same server.

 _place_holder;  _place_holder;  _place_holder;  _place_holder;  _place_holder; _place_holder; _place_holder;  _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder;  _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder;  _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder;  _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder;  _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder;  _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder;  _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder;  _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder;  _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder;  _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder;  _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder;  _place_holder; _place_holder; _place_holder;  _place_holder;  _place_holder; _place_holder; _place_holder;  _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder;  _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder;  _place_holder; _place_holder; _place_holder;  _place_holder;  _place_holder; _place_holder;  _place_holder;

That is the file that is responsible for getting a fresh, clean checkout of the source tree and then lanching the master build file for that project. Here is the starting build file for my demo project.

 _place_holder;  _place_holder; _place_holder; _place_holder;  _place_holder; _place_holder;  _place_holder;  _place_holder;  _place_holder; _place_holder;  _place_holder;  _place_holder;  _place_holder;  _place_holder;  _place_holder;  _place_holder;  _place_holder;  _place_holder;  _place_holder; _place_holder; _place_holder;  _place_holder; _place_holder; _place_holder;  _place_holder;  _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder;  _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder;  _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder;  _place_holder; _place_holder;  _place_holder; _place_holder; _place_holder;  _place_holder;  _place_holder; _place_holder; _place_holder;  _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder;  _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder;  _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder;  _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder;  _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder;  _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder;  _place_holder; _place_holder; _place_holder;  _place_holder;  _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder;  _place_holder;  _place_holder; _place_holder; _place_holder;  _place_holder; _place_holder;  _place_holder; _place_holder; _place_holder;  _place_holder; _place_holder; _place_holder;  _place_holder; _place_holder;  _place_holder; _place_holder; _place_holder;  _place_holder; _place_holder; _place_holder;  _place_holder; _place_holder; _place_holder; _place_holder;  _place_holder; _place_holder; _place_holder; _place_holder; _place_holder;  _place_holder; _place_holder; _place_holder; _place_holder;  _place_holder; _place_holder; _place_holder;  _place_holder; _place_holder;  _place_holder; _place_holder; _place_holder;  _place_holder; _place_holder; _place_holder;  _place_holder; _place_holder; _place_holder;  _place_holder;  _place_holder; _place_holder; _place_holder;  _place_holder; _place_holder;  _place_holder; _place_holder; _place_holder;  _place_holder; _place_holder; _place_holder;  _place_holder; _place_holder; _place_holder; _place_holder; _place_holder;  _place_holder; _place_holder; _place_holder; _place_holder;  _place_holder; _place_holder; _place_holder;  _place_holder; _place_holder;  _place_holder; _place_holder; _place_holder;  _place_holder; _place_holder;  _place_holder; _place_holder; _place_holder;  _place_holder; _place_holder; _place_holder;  _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; <exec program="${fxcop.executable}"  _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder;commandline="/o:${results.dir}/${file}-fxcop.xml /c /f:${assembly.name} /s"  _place_holder; _place_holder; _place_holder; _place_holder; _place_holder; _place_holder;failonerror="false"/>  _place_holder; _place_holder; _place_holder;  _place_holder; _place_holder;  _place_holder; _place_holder; _place_holder;  _place_holder;  _place_holder; _place_holder; _place_holder;

(This is all in one build file, which works for a simple setup like this, but if your build system gets more complicated you might want to consider splitting it into multiple build files and either launching them with the task or including them and calling them with the task.)

Like I said, I’m trying to make this as reusable as possible, and I may not have succeeded completely. I haven’t actually used this script on a large project yet, so some of my “tricks” may not work at all. The main trick is that I am trying to get NUnit and FxCop to automatically figure out which assemblies to scan based on their assembly names. This works for my projects because we say in our coding standards that all test assemblies will be named XXX.Tests.dll. So I can run NUnit on those and FxCop on the others.

I would be very interested to hear what any of you think about these scripts.