VSO Build vNext – versioning assemblies with MSBuild


In this blog post I will show you how to version assemblies during the Visual Studio Online vNext build.

Why to version assemblies?

Versioning assemblies will help you to detect, which library version has been deployed to your environment. You can obviously do it manually for each of your projects, but it can be a mundane and error prone task. Instead, I’ll show you how to easily automate the process.

In result, each project library will be automatically versioned. The version number format will follow the recommended standard:

[Major version[.Minor version[.Build Number[.Revision]]]]

How to version assemblies?

By default the assembly version is defined in the AssemblyInfo.cs class, which can be found in the Properties folder.

[assembly: AssemblyVersion("1.0.0.0")]

If you have many projects it’s much easier to have a single file with all common assembly information shared by all projects. This way you will only need to update the property once and it will be picked up by all projects.

To do that create a separate file called CommonAssemblyInfo.cs and place it the solution’s root folder. Move the AssemblyVersion definition to that file. Then, link the file from all projects:

1. Right click project

2. Add Existing…

3. Select the created CommonAssemblyInfo.cs

4. Click small arrow next to the Add button

5. Select Add as Link

6. Drag the linked file to the Properties folder.

alm_link

The result should look like this:

alm_linked

Obviously you can move more common properties to the CommoAssemblyInfo file e.g. AssemblyCompany, AssemblyCopyright etc.

Automate versioning

Now that we store the assembly version in a single file we can easily automate the versioning process. The idea is that before executing the actual build we will run another MSBuild script that updates the version in the Common file. The script will be using the AssemblyInfo target task from the MSBuild Community tasks. The script takes 2 parameteres: BuildId & Revision:

<?xml version="1.0" encoding="utf-8" ?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <MSBuildCommunityTasksPath>.</MSBuildCommunityTasksPath>
  </PropertyGroup>
  <Import Project=".\tasks\MSBuild.Community.Tasks.Targets"/>
  <Target Name="UpdateAssemblyInfo">
    <Message Text="Updating Assembly versions with Build Id $(BuildId) and Revision $(Revision)"></Message>
    <AssemblyInfo OutputFile="..\CommonAssemblyInfo.cs"
                  CodeLanguage="CS"
                  AssemblyVersion="1.0.$(BuildId).$(Revision.Replace('C',''))"
                  AssemblyFileVersion="1.0.$(BuildId).$(Revision.Replace('C',''))"
                  >
    </AssemblyInfo>
  </Target>
</Project>

The script must be added to your source together with community tasks files, so you can reference it in your VSO build definition.

VSO Build definition

Now that we have all components it’s time to define the VSO build. The first step would be execution of our custom build task:

alm_build

As you can see we use 2 environment variables here:

  • $(Build.BuildId) – id of the build
  • $(Build.SourceVersion) - The latest version control change that is included in this build .If you are using TFS it will have the format “C1234”, so you need to remove the “C” prefix (see our build script above)

Then, we can use the regular MSBuild step to build the solution. All assemblies that have the CommonassemblyInfo.cs file linked should have the correct version number set.

Now you can add more steps to the build definition: running unit tests, publishing artifacts, etc.

Alternative approach

You can also achieve the same functionality using PowerShell instead of MSBuild. There is a good example here.  Which one you choose is up to your personal preference – I prefer my solution, as it requires less code.

Approach with moving all common assembly properties to a single file I found here.

This post has also been published on my technical blog.

Comments (4)

  1. Tim Norris says:

    Hi Filip,

    Thanks for this – very useful and just what I’m working on right now!

    One question I have: what is your strategy for updating source control with the new version info?

    Or do you take the approach that these values are at a level higher than source control i.e. fed from the build? In which case, how do you associate the built version with a particular commit? Do you add a source control tag or something?

    Many thanks,
    Tim

  2. Filip Czaja says:

    Hi Tim
    It’s the second case – the version number doesn’t get updated in source. The TFS revision (commit) is the last part of the assembly version e.g. 1.0..
    You can also find out about build-commit association in VSO online portal by looking at the builds list.
    I hope this answers your question.

  3. Gary Howlett says:

    Why not just include the MSBuild targets fine inside a NuGet package? Then any project you wish to version you just add the NuGet package. Then you pass the arguments into the task conducting the build.

    Cheers Gary

  4. Filip Czaja says:

    Hi Gary
    I didn’t understand how your approach with NuGet packages would be better in this case? Can you provide more details?

    The approach described by me works well if you have a solution with multiple projects referencing each other directly, not as NuGet packages (no need for a private package store, easy debugging across all projects).

Skip to main content