TFS Build 2015 … and versioning!

Lately I got some time to play a bit more with the new build system which was released with TFS 2015 and which is also available for Visual Studio Online. The new build system was in the beginning announced as build vNext, but now with the release of TFS 2015, it’s safe to call it Team Foundation Build 2015 (TFBuild 2015) while the “old” build system can be referred to as the xaml (workflow) build system. Colin Dembovsky has a great post why you should switch to the new build sytem.

In the last years, I had to implement a lot of customizations into the xaml build system and I became very productive with the workflow activities. Along the way I developed a number of generic activities which I could reuse for other assignments and I really knew my way around in the build workflow. In many cases, the TFS Build Extensions were used to not reinvent the wheel. So, in the first phase I was a bit sceptic about the rise of yet another build system, but I clearly saw some interesting advantages which are explained in the post by Colin. One disadvantage of the xaml build system is the steep learning curve to master the customization process and also the deployment mechanism to refresh the TFS build controller(s). But like I experienced, once you got there, you were able to integrate very powerful customizations into the build process. Anyway, the “old” build system won’t disappear and you can still rely on this functionality for quite some time in the future, but I recommend to have a good look at the new build system and use it for your new/future build definitions.

In this post I want to share how I integrated a common activity in the build process: Versioning. With the available build steps it has become extremely simple to hook your own scripts into the build process. In your scripts you will have access to some predefined build variables.

In my previous blogpost I wrote about adopting a Global .NET Versioning Strategy and the existence of a third (optional) version attribute: AssemblyInformationalVersion. Let’s use this strategy to add versioning to a sample Fabrikam software application.

My build definition:


In the screenshot above you will see that I launch a powershell script (PreBuild.ps1) before building the solution and I pass one argument productVersion to the script. The powershell script will do the magic in the background to replace all versioning values for AssemblyVersion, AssemblyFileVersion and AssemblyInformationalVersion in the Assembly Info files, based on this product version. The product version will be passed as a whole to the AssemblyVersion and the AssemblyInformationalVersion attributes. The AssemblyFileVersion will be replaced with a full version number which will consist of the major and minor version number of the product version, a Julian based date and an incremental build number.


Assembly File Version = 1.0.15236.3

  • 1 => taken from “Major” product version
  • 0 => taken from “Minor” product version
  • 15236 => generated by build process: “15” = year 2015, “236” = day of year 2015
  • 3 => third build, run on day 236 in year 2015

Looking at the assembly details of a custom built Fabrikam assembly now reveals correct meta data:


I also modified the build number format to have some more version information displayed in the build run.



I added a gist at GitHub to share the powershell script. Note that the script has been used for experimentation and may not be ready to be used for production. it certainly lacks some proper validation and error-handling. Use at your own risk.

Also have a look at some similar inspiring blog posts about versioning TFS Builds which helped me to develop the powershell script that works for my scenario.

15 Responses to TFS Build 2015 … and versioning!

  1. […] a next post I will talk about how you can achieve this global .NET versioning strategy with the new build […]

  2. You’re using the term Julian Day Number incorrectly. The value you’re referring to is correctly called the Ordinal Date.

  3. lionzhang says:

    I’ve upgraded from TFS 2013 to 2015, but have issue with the new build system, the new agent is not taking the latest from TFVC, old XAML builds and all of them work as expected. Even repairing the TFS the problem is not solved. It seems to be a bug with the agent that is not working properly.

    If I manually do a get to the agent build folder before running the build, set the clean options to false and call the agent eveything goes fine.

    Besides that, if the folder is empty the build fails. So what’s happening is that the agent is not being able to properly get the latest version from TFS, even if it shows a successful message on the log it’s not downloading anything to the destination map folder.

    Any ideas? Really appreciate your time!

  4. Looks promising but why is this still something shops have to roll their own for…surely most ISVs would want this? I’m fascinated what MS use in-house.

  5. […] TFS Build 2015 … and versioning! […]

  6. mkokabi says:

    Could you please share your postbuils.ps1. I want to know how did you check-in your changes. Fyi, I’m using TFS version control.

  7. No check-in of modifications. It’s the Build Process that’s always in charge to set the versioning. No need to commit this to version control.

  8. mkokabi says:

    I put your PS in a solution folder and set the Script filename field in powershell build step to point at it but it didn’t execute. It does say Starting task… but still doesn’t write anything else on the console and it doesn’t update the version either. I moved that PS to the project and changed its ‘Copy to output directoy’ to ‘Copy if newer’ and changed the ‘Script filename’ but still no difference.

  9. mkokabi says:

    I followed the MSDN post ( and it’s working but I prefer the PS you have put here as it’s accepting the version as a parameter. I guess the problem is in how I am calling yours. Could you please share PreBuild.ps1.

  10. The powershell script I added in the gist on github is wrapped in a function. Remove the function and it will work fine …

  11. Brad says:

    Check out this script that I wrote: it applies the version from the assembly info files, but also increments the build number and checks the assembly info files back into source control:

  12. moparthi says:

    Do you have a solution for the Missing build Quality indicator in 2015 Builds ? Its a moajor issue in case of life cycle management . how do we deal with this in 2015 builds ?

  13. ThinkBigger says:

    Note that using yyDOY introduces two long-term problems:
    – The Century Bug (aka, Y2K), where a build in 2100 will look like it comes before a build in 2099. But we won’t get that far, because…
    – Builds will start failing in 2066, since 66001 is beyond the UInt16.Max-1 limit for the components in the Assembly Version et cetera numbers.

  14. ThinkBigger says:

    The Major and Minor portions of the Assembly Version et cetera numbers is really a _design_ decision which should be implemented in the source code, not at deployment time. It seems to make more sense to implement that design in the source code instead of in the build process.

    We would still update the 3rd* & 4th portions during the build process, since those require a centralized control of the increment. But the Major & Minor portions would be taken from the source code instead.

    *Unless you move towards semantic version, which uses the 3rd portion as “Patch” number. The choice of “Patch” number to use would also be a _design_ decision to be implemented in the source code.

    A major advantage to this approach is that you don’t have to update the parameter to the PowerShell script in your Build Definition over time or provide a correct value to a variable with each build request. The portions are either defined in code or by the build process itself.

    This also allows you to have different Major.Minor numbers in the different projects within your solution. For instance, if you didn’t make source code changes in your DLL, you may be recompiling it with a new Revision number, but there is no definitional change and therefore no need to change Major.Minor.

  15. Steve says:

    Thank you for sharing your script. It works well. I was having trouble with it until I realized that I needed to adjust the AssemblyInfo.cs to AssemblyInfo.vb for a project. It always pays to understand what the script file is doing.

Leave a Reply

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

You are commenting using your 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: