I remember reading a book about 4 years ago on how to determine the maturity of software development companies. The thing that stood out at the time was the fact that mature development shops have a well managed and efficient automated build system with a sliding scale from that to companies that are starting and do not even have a source control system.
The reason why it stood out is that at the time we only had a very rudimentary build system and it was bugging me that we could not go from source to installers (including build # and documentation) without someone getting involved to hand crank it. Doing it that always ended up with inconsistency and we would end up testing software builds that had the wrong DLLs in it and simply just waste some testing time.
The decision was made to create a new build system and efforts started on getting it implemented. Unfortunately, along with the decision to implement a build system also came the decision to implement all of the functionality ourselves rather than use 3rd party OR open source tools. Due to this, the build system got half built before we realized that it was not maintainable and the project suspended.
I mention this in the hope that others do not suffer this growing pain as we did. It is also the case that at the time the tools we know use did not exist or certainly were not ready for reliable use so perhaps we just tried to it before the most optimum time.
Ok. So about a year later I started looking at this problem again and found some interesting tools out there that people were recommending.
Nant
Nant is a open source .NET build system which finds it’s home on sourceforge. At the time of looking we had started to move all of our code from VB/C++ over to C# so standardizing on a build system that is .NET based is fairly good one.
We still have to this day a set of components that are VB so it was important that it would support VB. Thankfully we are not the only company in the world that still have VB code and there is a vb6 task as part of the Nant Contrib project. This allowed us to have our VB6 projects compiled in the same build environment as our C# projects.
Nant allows for a great level of control on what is built and what is used to build it.
CruiseControl.NET
CruiseControl.NET (CC.NET) is a continuous integration server that watches your source control system and recognizes when changes have been made on a configured sub folder triggers a process to begin. In our case this process is a nant build task on the piece of functionality that has changed.
The great thing about this is that you get immediate feedback on all code checked in that it did not break anything. This can be anything from a new source file missing to breaking a build on a different version of ArcGIS (more on this later).
There are web-based and windows notification area (system tray) tools that allow anyone to see the current state of the build system.
To make the ‘test builds’ quick and painless we have separated the build files into product/project and even component level. This means that if we change component Y in project X then only that project will be built and not the whole source tree (which takes about 20 minutes and would be over the top for every check-in!). Due to this we have about 30 projects in each build server (up to 3 at any time — more later).
In the early hours of the morning we also have a batch build script triggered within CC.NET that builds all of the software in order, creates the installers and server folder structures for testing. This process takes anywhere up to about 30 minutes and again as it is within the build system we know whether it as built successfully when we log in every morning.
Build Servers
I mentioned that we have up to 3 build servers. Why on earth would we even contemplate having more than one you say? The simple and only reason that we have up to 3 is to support each version of ArcGIS. When using .NET the libraries referenced are version encoded so we made the decision to build the same source code in all of the versions that we currently support. There are ways of work within versioned assemblies (use of policy files for example) but we felt that it would be good to build on the actual version the user will be running the software on so the build servers were born.
What is the result of the build?
Well, that depends on what build we are talking about.
For a build that is triggered by a Subversion check-in just the component of software that has been changed is built. There *should* be a subsequent build of all components that depend on that particular assembly (or set of assemblies) but this is not supported in CC.NET and we have not encoded that logic in Nant as yet.
For a ‘batch build’ that has been triggered in the evening the Nant script:
- Increments the build number is all of the AssemblyInfo.cs files
- Builds all of the projects we want built
- Reverts the AssemblyInfo.cs files so that they do not show up in SVN as edited.
- Generates Installers for all of the products we have
- Copies the installers to a well defined location
All of this is very important to a software team as it means that all of the tedious tasks that are prone to error are automated. This means we cannot get it wrong (well kind of) and we can be sleeping when it is being done (batch build is triggered at 12:30 AM).