Tuesday, December 04, 2007

Continous Integration using CruiseControl.Net (part1)

Introduction
A lot of information has been written about the appropriate way to build software releases. Almost everybody have an idea about how to do it, yet almost all the commercial companies I have been working with does not do this. Funny enough almost all of the open source projects that I have participated in are doing it.


Terminology used
Please note that I make a distinction between a "Build" and "Compile".

A "Compile" is when you do the actual compilation from .NET to IL/native image.

A "Build" can be much broader in scope in that it will "Compile" you code and potentially a lot of other steps as well like:
- run some automated tests (NUnit/NUnitForms)
- run coverage analysis
- code metrics
- checking coding guildelines
- building documentation
- creating a deployment package
...

I also distinguish between a "Developer Build" and a "Build".

A "Developer Build" is one that is performed on the same machine the software is developed on. A developer Build is done after changing the source code but before actually checking those changes in to the version control system.

A "Build" is performed on another machine apart from the machine where the software is being developed and is performed after the changes has been checked in to the version control system.



Problems to account for
Setting up the required software to run continuous integration builds is not the hard part. The hard part is all the changes that it brings around. Change the working habits of people can at times (read most of the time) be a challenge.


  • developers will no longer just build using CTRL+SHIFT+B in visual studio (they can compile the solution using this method but no builds please)

    A compile is not enough to actually mark the code "passed" so it can be checked in to the versioning control system

  • you will need to decide on a versioning scheme and how this affect common libraries/assemblies, are you going to build all the libraries all the time or are you going to have a common set of libraries/assemblies which are referenced directly in the binary form?

    If you have a relatively stable/mature common assembly that is used across all projects, it makes sense to reference this assembly in binary format rather than as a project reference. It does not load the build server, if there is no need for the new additions that have been made in the common assembly for project Y but project X does not need them then it is introducing possibilities for bugs. The relation graph between projects and shared assemblies can become very complex.

  • is your version control system directory/repository tree the same as on the developer workstations and the build server?

    Being able to run the same script on the developer workstation as on the build server guaranties that the tests run are the ones needed to pass. You do not need to maintain 2 versions of the same script due to developers saving the source code to a different location. It makes it simpler to locate code, communicate and introduce new developers to the project.

  • are shared assemblies located the same place across these machines
  • introducing unit test, code coverage and code metrics and adherence to coding guidelines will make some developers feel exposed

    Now you are suddenly able to actually measure and have some idea of the quality of work the developer is producing.


Software
The software used in this article are the following.

FxCop 1.35
"FxCop analyzes programming elements in managed assemblies, called targets, using rules that when violated, return informational messages about the targets. A report containing these messages appears in the user interface, or in the output window when using the command-line tool. Messages identify any relevant programming and design issues and, when possible, supply information on how to fix the target. ..." (taken from the FxCop documentation here)

Nant 0.85
"NAnt is a free .NET build tool. In theory it is kind of like make without make's wrinkles. ..."
(see more here)

NCover 1.5.8
"... NCover monitors your code while running under test and reports where your code is being exercised (and more importantly, where it is not being exercised). ..."
(see more here) NUnit 2.4.2-net 2.0
"NUnit is a unit-testing framework for all .Net languages..."
(see more here)

NUnitFormsv2.0alpha5
"NUnitForms is an NUnit extension for unit and acceptance testing of Windows Forms applications. ..."
(see more here)

Source Monitor 2.3.6.1
"The freeware program SourceMonitor lets you see inside your software source code to find out how much code you have and to identify the relative complexity of your modules. ..."
(see more here)

NMock
"NMock is a dynamic mock object library for .NET. Mock objects make it easier to test single components—often single classes—without relying on real implementations of all of the other components. This means we can test just one class, rather than a whole tree of objects, and can pinpoint bugs much more clearly. ..."

Each of the above software/products are my preferences, that does not mean that these are the only ones or the right ones.