Use Subversion revision number as version number with MSBuild (and handle revision numbers larger than 65534)

When using a system for continuous integration to automatically deploy your application, it is important to know what version of your code is deployed. This tutorial will show you how to automatically set the version number of the deployed .dll.

Published:

In a .NET project, the version number is defined in AssemblyInfo.cs, on the format 1.0.0.0. The numbers are MajorVersion.MinorVersion.Build.Revision. The two latter, build and revision numbers, should be set automatically by your CI system on each deploy.

Content of this tutorial

  • How to create an MSBuild target to automatically insert the revision number on build

  • What to do when your revision numbers are too large to use as .NET revision numbers

  • How to use Bamboo to get the latest revision number from Subversion and use this as an input parameter to MSBuild

How to create an MSBuild target to automatically insert the revision number on build

When creating the MSBuild target, I use MSBuild.Extension.Pack. In Visual Studio, install the MSBuild.Extension.Pack Nuget package for any projects in your solution where you want to modify the version number.

After installing the Nuget package, edit the project file, project.csproj. Near the end of project.csproj, you will have some lines similar to these, added when you installed the Nuget package:

<import project="..\..\packages\MSBuild.Extension.Pack.1.6.0\build\net40\MSBuild.Extension.Pack.targets" condition="Exists('..\..\packages\MSBuild.Extension.Pack.1.6.0\build\net40\MSBuild.Extension.Pack.targets')">
  <target name="BeforeBuild"></target>
  <target name="AfterBuild"></target>
</import>

We will be using the BeforeBuild target to add some extra data to the project's AssemblyInfo.cs file.

Add the following code to project.csproj (replacing the code shown above):

<import project="..\..\packages\MSBuild.Extension.Pack.1.6.0\build\net40\MSBuild.Extension.Pack.targets" condition="Exists('..\..\packages\MSBuild.Extension.Pack.1.6.0\build\net40\MSBuild.Extension.Pack.targets')">
  <propertygroup>
    <revision condition="$(Revision) == ''">0</revision>
  </propertygroup>
  <target name="BeforeBuild">
    <assemblyinfo assemblyinfofiles="Properties\AssemblyInfo.cs" assemblyrevision="$(Revision)" assemblyfilerevision="$(Revision)">
    </assemblyinfo>
  </target>
</import>

When building your project with MSBuild.exe, you can now add a parameter Revision. The value of the Revision parameter will be added in AssemblyInfo.cs in the last part of the version number for both AssemblyVersion and AssemblyFileVersion.

To try it out, add MSBuild.exe to path. Then run this command from the command line:

msbuild project.csproj /p:Revision=123

Have a look at your project's AssemblyInfo.cs. It should now have been modified to have AssemblyVersion and AssemblyFileVersion 1.0.0.123.

What to do when your revision numbers are too large to use as .NET revision numbers

Run the following command:

msbuild project.csproj /p:Revision=66000

The build now crashes, because .NET does not allow any part of the version number to be larger than 65534.

What I ended up doing to solve this, was to split the revision number in two. For example when deploying revision 66123, I convert this to version number 1.0.66.123 (instead of 1.0.0.66123).

To achieve this, you have to modify project.csproj. Here is the modified target that splits the incoming Revision parameter into two parts:

<import project="..\..\packages\MSBuild.Extension.Pack.1.6.0\build\net40\MSBuild.Extension.Pack.targets" condition="Exists('..\..\packages\MSBuild.Extension.Pack.1.6.0\build\net40\MSBuild.Extension.Pack.targets')">
	<propertygroup>
		<revision condition="$(Revision) == ''">0</revision>
	</propertygroup>
	<propertygroup>
		<revisionlastthreedigits>
			$(Revision)
		</revisionlastthreedigits>
		<revisionlastthreedigits condition="$(Revision.Length) > 3">
			$(Revision.Substring($([MSBuild]::Add($(Revision.Length), -3)), 3))
		</revisionlastthreedigits>
		<revisionbeforelastthreedigits>
			0
		</revisionbeforelastthreedigits>
		<revisionbeforelastthreedigits condition="$(Revision.Length) > 3">
			$(Revision.Substring(0, $([MSBuild]::Add($(Revision.Length), -3))))
		</revisionbeforelastthreedigits>
	</propertygroup>
	<target name="BeforeBuild">
		<assemblyinfo assemblyinfofiles="Properties\AssemblyInfo.cs" assemblyrevision="$(RevisionLastThreeDigits)" assemblyfilerevision="$(RevisionLastThreeDigits)" assemblybuildnumber="$(RevisionBeforeLastThreeDigits)" assemblyfilebuildnumber="$(RevisionBeforeLastThreeDigits)">
		</assemblyinfo>
	</target>
</import>

To test this, run msbuild from the command line again:

msbuild project.csproj /p:Revision=66000

Have a look at AssemblyInfo.cs. I should now contain AssemblyVersion and AssemblyFileVersion 1.0.66.000.

How to use Bamboo to get the latest revision number from Subversion and use this as an input parameter to MSBuild

In Bamboo there is a special MSBuild task used to build .NET applications and deploy them. Use the input field "Options" for all your MSBuild parameters.

Here I have added the "Revision" parameter to my MSBuild task in Bamboo:

/p:Revision="789" /p:Configuration="Test1" /p:DeployOnBuild=True

Try running the plan, and go have a look at the deployed dll. Right-click the dll, select Properties, select the Details tab, and you will see the version number 1.0.0.789.

The next step is to get Bamboo to fetch the Subversion revision number associated with this deploy. This is done by using one of Bamboo's many global variables.

I am using Bamboo version 4.4, and here the variable name is bamboo.custom.svn.revision.number. However this changes slightly from version to version, so have a look at Bamboos documentation to see what applies to your version of Bamboo.

In the latest version of Bamboo (5.8), I think the correct variable is bamboo.planRepository.revision.number, but I have not been able to test that.

Change the MSBuild task options in Bamboo to this:

/p:Revision=${bamboo.custom.svn.revision.number} /p:Configuration="Test1" /p:DeployOnBuild=True

Try running the plan again, and have a look at the deployed dll and check that the version number contains the correct revision number.

Categories: Bootstrap Subversion

Comments