Automatic assembly versioning with TeamCity
Although there are a number of good continuous integration servers out there, TeamCity is one of my favorites. It has great support for .NET — supporting MSBuild, NAnt, Solution builds, NUnit, MSTest, and FxCop. The price is right if you have less than 20 users and 20 build configurations – free. I was also able to a plugin to integrate with our issue tracking systems in a couple of hours timespan (my Spring MVC experience definately helped though).
One of thing that you want to do with a release build is automatically increment your version numbers. Most approaches to this problem recommend using MSBuild to autogenerate the AssemblyInfo.cs file. Although that certainly works, I prefer not to have to do that for every project. Instead, each of our projects references a single CommonAssemblyInfo.cs file.
When TeamCity builds a release build, it is configured to the IncrementVersion task:
1: <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
2: ...
3: <Target Name="UnrestrictedExecutionPolicy">
4: <Exec Command="powershell set-executionPolicy unrestricted"" />
5: </Target>
6: <Target Name="IncrementVersion" DependsOnTargets="UnrestrictedExecutionPolicy">
7: <Exec Command="PowerShell .\incrementVersion.ps1 $(build_vcs_number_1)" />
8: </Target>
9: ...
10: </Project>
The $(build_vcs_number_1) property tells TeamCity to the current revision number from the first source repository attached – in my case SVN — to the project (most projects will only have one repository attached). Then, we execute a simple Powershell script to replace the file version number:
1: $buildNumber = $args[0]
2: (Get-Content ..\src\CommonAssemblyInfo.cs) | Foreach-Object {$_ -replace "(\d\.\d\.\d)\.\d*", "`$1.$buildNumber"} | Set-Content ..\src\CommonAssemblyInfo.cs
If you are more comfortable using a MSBuild task for regex replacement, there is a RegexReplace task that is part of the MSBuild Community Tasks. For my build, we do not need any other custom tasks, so it was preferable to just use a simple PS script.