Easy Release Versioning for .Net Projects using VSTS and TFS

Versioning. Here we are. Again.

Over the years I have always worked hard to make versioning a foundational piece of every CI / CD solution I’ve setup. Reliable, logical versioning becomes key to long-term maintenance and troubleshooting efforts, and whatever you can do to make it a “no-brainer” is worth it (your future self will thank you).

The move to .Net Core changed the way a few items work in the .Net world, including versioning, and besides, I am always looking for ways to make versioning easier.

So here’s my cheat-sheet for versioning your solutions. It won’t suit all application types, but for my use case (.Net Web Apps) it works just fine. It will work with VSTS and newer TFS versions too.

I haven’t tested on VB projects, but this should work for them just as easily as C#.

NET Core: Setup Your Project File

Versioning has been simplified in the .Net Core world. Edit your csproj and modify it as follows:

<PropertyGroup>
  <Version Condition=" '$(BUILD_BUILDNUMBER)' == '' ">1.0.0.0</Version>
  <Version Condition=" '$(BUILD_BUILDNUMBER)' != '' ">$(BUILD_BUILDNUMBER)</Version>
</PropertyGroup>

If your file doesn’t have a version node, add the above. This tip comes from Stack Overflow, but I’ve modified it slightly.

The above setup will mean debugging locally will give you a version of 1.0.0.0, and in the event you build in a non-VSTS / TFS environment you will also end up with a 1.0.0.0 version. $(BUILD_BUILDNUMBER) is an environment variable set by Team Build and which will be updated at build time by VSTS or TFS.

NET Framework: Add Custom Task

In the “old” .Net world we have to update the properties of the AssemblyInfo file that is a part of the project, specifically targeting File Version and Assembly Version.

There isn’t an in-built build Task to do this for you, and rather than hack together a script, why not use a great custom task from the marketplace (which also supports TFS)?

I’m using the “Assembly Info” task from Bleddyn Richards, primarily because it has the most recent updated date out of the similar tasks available, which means it’s hopefully getting plenty of love and care from the owner 🙂

Add the above Task to your build definition (make sure to do it before you build the Solution / project) and then set the version numbering as shown below.

VSTS Task Config - versioning

Setup Build Versioning

The above steps are great, but they will count for nothing (or cause a compile fail) if we don’t have a valid versioning number.

The default VSTS build version number format takes this format:

$(date:yyyyMMdd)$(rev:.r)

This results in a build number that looks like this:

20180201.1 (for the first build on February 1 2018).

This isn’t a valid .Net Version number, so we need to change it.

First, let’s add two Variables to our build definition: MajorVersion and MinorVersion.

You can set these to any valid integer value. These can be manually controlled over time as you determine the need to increment Major and Minor version numbers. Note you can make them whatever you like, keeping in mind the size restriction I mention below.

Build Variables

Now let’s change the Build Numbering scheme to use these variables, a specific date format, and the revision:

Number Format

$(MajorVersion).$(MinorVersion).$(date:yy)$(DayOfYear)$(rev:.r)

Which produces a build number that looks like this:

2.0.18037.1 (for first build on February 6 2018 for Major Version 2, Minor Version 0).

You can choose a format that works for you, with one proviso that each version segment must be less than 65,000, which sounds like a lot, until you consider that 20180201 (Feb 1, 2018) is, as an integer (20,180,201) larger than 65,000. Hence my decision to drop to using YY (if you’re reading this in the year 2065 I apologise for my shortsightedness).

The result of these changes will mean that you’ll have a lovely version number automatically written into your solution at build time. An example from a .Net Framework solution is shown below.

Properties Dialog

Happy Days 😎

Tagged ,

5 thoughts on “Easy Release Versioning for .Net Projects using VSTS and TFS

  1. SvenL says:

    Why is it a good thing to let the build determine the version number?

    When I trigger a build of an older commit I get that brand-new version number; should this not be a code-thing. The code is either version 1 or 2 or 3…

    • Simon says:

      Sven – that’s a good point and one you could certainly implement by pulling the commit hash (I assume from Git) at build time and appending it to the Product Version or Assembly Informational Version (File Version has specific restrictions on format). Here’s an example of how you can achieve this outside of VSTS: https://github.com/jeromerg/NGitVersion, or this marketplace add-in (GitVersion): https://marketplace.visualstudio.com/items?itemName=gittools.gitversion

      I’m not saying that my approach is the only way to achieve a result, but it’s worked for me and allowed me to consistently version across .Net Framework and Core builds. If I am interested in what constituted the build I can go and review the VSTS / TFS Release Management and / or Build History which will give the commit at which the Build was run – one benefit of operating end-to-end on the VSTS ecosystem.

      Hope this helps – Simon.

    • advanium says:

      I agree with SvenL. It doesn’t make sense to me to version builds beforehand when in the end I end up discarding them, wasting the version number. If I’d ship, version numbers would leave gaps. I have yet to find a guide on how to properly set this up.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: