Why version your assemblies?
Having version information on your assemblies that are deployed with your application can be useful for determining what code was actually used to create a compiled asset. Unfortunately the default versioning msbuild provides during a compilation is not extremely useful. You can enable auto-increment on the version numbers, but unless you track them in some way it can be difficult to trace the exact code used to build the assembly.
It would be great if there was some way to version your assemblies as part of your continuous integration / deployment process. Note: If you don’t have a continuous integration process for your builds, you should! This way the artifacts that are created by a build for each push to your version control repository are versioned and tied to the source control assets. If you come across your assembly in the wild (on your server or a customer’s), it would be possible to tell exactly which build and source code commit were used to create the assembly.
Team City
We’re using Team City as our build and deployment environment. JetBrains has made it extremely easy to add this type of information to the file version properties for an assembly. With only a small change to your normal build process you can add assembly versioning.
Additional Build Feature – AssemblyInfo Patcher
I wasn’t aware that the Additional Build Feature functionality existed until I researched assembly versioning with Team City. I came across the AssemblyInfo Patcher feature in the Team City documentation. If you have created your application using standard Visual Studio solutions and projects then all your projects contain an AssemblyInfo.cs class in the Properties folder. This file contains information about your assembly that is used to define its file properties during compilation. It also holds information about paths to embedded resources as well as other compilation options for your assembly.
The AssemblyInfo Patcher in Team City scans your entire working directory looking for files named AssemblyInfo.cs. When it finds these files it updates three of the properties: AssemblyVersion, AssemblyFileVersion, and AssemblyInformationalVersion. The first two (version and file version) need to be in the standard version format for assemblies (1.0.0.0) while the information version is free text. We will set all of these with the patcher and specifically use this free text field to store information about the git repository used to retrieve the source code for the build.
It actually took me a minute to find the build features in the Team City UI, because I was looking for it under the build step itself. Instead it is actually at the bottom of the Build Steps form (the third step of a build configuration):
From here you would click Add build feature and choose AssembyInfo patcher:
Once this is selected you can see where the three assembly information properties may be set.
Setting the Version Number to Team City Build Number
If the version number of an assembly contained the build number on Team City that was used to create the assembly, it would make it very easy to look up the build history and results. As luck would have it, the Team City build number is numeric which makes it a good fit for the standard assembly version number. In Team City the environment variable which contains the current build number is %system.build.number%. So for the first two fields we set the properties to:
1.0.%system.build.number%.0
This conforms to the normal .NET assembly versioning standard which is the following:
<major version>.<minor version>.<build number>.<revision>
In this case we’re setting the <build number> portion to the team city build number. If you would like to update the major, minor, or revision portions of your version you could obviously change these as well. You could even create custom environment variables in Team City that to set on build for these values (still leaving the build number up to team city).
Providing Git Details
It is also possible to provide some details about the exact source code used to build the assembly. In order to unambiguously identify the source, we need three key pieces of information: repo url, branch name, and commit SHA. I know in theory the SHA uniquely identifies the commit, but the other pieces of information give some really useful context when you’re tracing the history of an assembly.
In order to set this up, we just need to know the Team City environment variables that provide this information in the context of a build. Fortunately you’re in luck! I’ve done this for you…. :-)
Url => %vcsroot.url%
Branch => %vcsroot.branch%
SHA => %build.vcs.number%
Final Assembly information version format:
url:%vcsroot.url% branch: %vcsroot.branch% commit:%build.vcs.number%
What does this look like when it builds?
When Team City builds your project it is going to search through all of your assemblyinfo.cs files and update them with this information. You will see this in your Team City Build log immediately proceeding your build log entries.
When your assemblies are generated you will see these three properties on the file properties of the assembly. Of course, if you want to be able to easily read them you could use powershell to get the properties with a command like the following:
Get-ItemProperty -Path Example.dll | Format-list -Property * -Force | more
Yielding:
Note: Repo location is an example only, it does not exist.
That’s it. Now you have some very useful version information on every set of assembly artifacts you build and deploy!
Nice article. TeamCIty V9.1 includes a new File Content Replacer which allows replacement of some other parameters too. See their documentation at https://confluence.jetbrains.com/display/TCD9/File+Content+Replacer for more details.