The Problem

The company I work for have used the assembly version for keeping track of deployments and we wanted to continue this practice when moving to use VSTS build and release management. You can set the build name in the Options tab of the build definition.

Screen-Shot-2018-05-12-at-12.40.04

You can see under the Build number format that the $(date:yyyyMMdd)$(rev:.r) which will have the date as the build number followed by a '.' and the revision number. The revision number will prevent the builds from having the same build number if more than 1 is run on the same day. The build numbers will be 20180512.1, 20180512.2, 20180512.3, etc.

We wanted to change this to use the assembly number coming from the code and appending the date and time that the build was created.

The problem was that the build number is created using the pattern from the Options tab first and then downloading the code to build. We don't have access to the AssemblyInfo until the code is downloaded so how do you update the build number while the build is running?

My Solution

There were a couple of steps required to complete this task.

  1. Get the AssemblyInfo from the code
  2. Update a build variable to hold the assembly version
  3. Update the build number using the assembly version number

Get the AssemblyInfo from the code

There are a couple of ways to do this.

You can write your own script

$path = "PATH_TO_ASSEMBLYINFO\AssemblyInfo.cs"
$pattern = '\[assembly: AssemblyVersion\("(.*)"\)\]'
(Get-Content $path) | ForEach-Object{
    if($_ -match $pattern){
        # We have found the matching line
        # Edit the version number and put back.
        $fileVersion = [version]$matches[1]
        $AssemblyVersion = "{0}.{1}.{2}.{3}" -f $fileVersion.Major, $fileVersion.Minor, $fileVersion.Build, $fileVersion.Revision
    } else {
        # Output line as is
        $_
    }
}

and use $fileVersion to return the seembly version information in whatever format you would like. In the example, I used it to set $AssemblyVersion to something like 1.2.3.4 depending on what the AssemblyInfo has been set to.

Alternatively, you can use one of the scripts already available in VSTS. I've found Assembly Info Reader very simple to use. You simply provide a path to where your AssemblyInfo file is contained and it will return a build variable called AssemblyInfo that you can use in your script. $(AssemblyInfo.AssemblyVersion) will return the same value as $AssemblyVersion in the sample code above.

Personally, I just went with Assembly Info Reader so I have already covered steps 1 and 2 of the solution.

Update the build number using the assembly version number

This took some experimentation to get working. The solution itself was easy but for some reason it took a while to get working.

In VSTS, there are pre-defined variables that exist for every build that is run. One of them is Build.BuildNumber. This is the label that will be displayed in the list of builds produced by a build definition.

I wrote a short PowerShell script to update this variable once Assembly Info Reader had completed and the AssemblyInfo variable was available.

param (
	[parameter(Mandatory=$True)]
    [string] $AssemblyVersion
)

$datetime = Get-Date
$date = $datetime.ToString("yyyy-MM-dd")
$hour = $datetime.ToString("HH")
$minute = $datetime.ToString("mm")
$DateString = $date + " " + $hour + "h" + $minute

$BuildNumber = $AssemblyVersion + " - " + $DateString
Write-Host "##vso[build.updatebuildnumber]$BuildNumber"

All this does is accept the $AssemblyVersion parameter and then appends the date and time to create $BuildNumber and then update the build number using build.updatebuildnumber. There is documentation here on changing build and release variables when using scripts.

I saved this script as Update_Build_Number.ps1, added it to my project's source code and added a new task to run this during the build. I passed in $(AssemblyInfo.AssemblyVersion) into the $AssemblyVersion parameter

Screen-Shot-2018-05-12-at-13.35.30

The result was now we have the correct build number that is also timestamped.

Screen-Shot-2018-05-12-at-13.39.20

The previous builds had been using a variable value that needed to be changed each time a build was run in order to be accurate but that is no longer the case. This is going to save us time and make our lives easier in the long run.