Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Automatic Versioning with Team Foundation Server 2012; Increment Only on Changed Assembly

I've been tasked with setting up a new Team Foundation/Build server at my company, with which we'll be starting a new project. Nobody here currently has experience with TFS, so I'm learning all of this on my own. Everything is working so far; The server's been set up, the Repository and Team Project has been created, the Build Server has been created, and I've created a simple hello world application to verify the source control and Continuous Integration builds (on the build server) run properly.

However, I'm having a problem setting up the automatic versioning. I've installed the TfsVersioning project, and it's working fine; I'm able to define a format for my assembly versions. I haven't yet decided what format I'll use; probably something like Major.Minor.Changeset.Revision (I'm aware of the potential problem regarding using the changeset number in the assembly version, so I may decide to switch to Major.Minor.Julian.Revision before we begin development).

The problem: I don't want assemblies to have new file versions if their source code has NOT changed since the last build. With a continuous Integration build this isn't a problem, as the build server will only grab the source files that have changed, causing an incremental build which produces only updated modules; the existing unchanged modules won't be built, so their version will remain unchanged. If I set up a nightly build, I'll want to clean the workspace and perform a Build-All. However, this means that ALL assemblies will have new version (assuming the Assembly File Version includes the build number).

A solution? This has prompted me to consider using the latest changeset number in the Assembly File Version. This way, if nothing has been committed between two successive Build-Alls, the versions won't be incremented. However, this would mean that a change and commit to a single file would force a version increment on ALL assemblies.

I'm looking for one of two things:

  • A way to only increment Assembly Version Numbers if their source/dependencies have changed since the last build. Successive Build-Alls should not cause changes in version numbers.

OR

  • A way for testers and non-developers to be able to tell version W.X.Y.Z and version W.X.Y.Z+1 of assembly 'Foo' are identical, even though they have differing file versions.

I've probably read about 20 articles on the subject, and nobody (except this guy) seem to address the issue. If what I'm asking for isn't common practice in the Team Foundation ALM, how do I address the second bullet point above?

Thanks for your time!

like image 780
Tsherr Avatar asked Jun 25 '13 18:06

Tsherr


1 Answers

This is something I did in the past. The solution has two critical points:

  1. You must use an incremental build, i.e. Clean Workspace = None
  2. The change to AssemblyInfo.cs must be computed at each project

This latter is the most complex and I will just draft the solution here.

In the custom MSBuild properties use CustomAfterMicrosoftCommonTargets to inject an hook in normal Visual Studio compile

/property:CustomAfterMicrosoftCommonTargets=custom.proj

Also forward a value for the version

/property:BuildNumber=1.2.3.4

In custom.proj redefine the target BeforeCompile to something similar

<Target Name="BeforeCompile"
Inputs="$(MSBuildAllProjects);
        @(Compile);                               
        @(_CoreCompileResourceInputs);
        $(ApplicationIcon);
        $(AssemblyOriginatorKeyFile);
        @(ReferencePath);
        @(CompiledLicenseFile);
        @(EmbeddedDocumentation); 
        $(Win32Resource);
        $(Win32Manifest);
        @(CustomAdditionalCompileInputs)"
Outputs="@(DocFileItem);
         @(IntermediateAssembly);
         @(_DebugSymbolsIntermediatePath);                 
         $(NonExistentFile);
         @(CustomAdditionalCompileOutputs)" 
Condition="'$(BuildNumber)'!=''">

<Message Text="*TRACE* BuildNumber: $(BuildNumber)"/>

<MyTasksThatReplaceAssemblyVersion
    BuildNumber="$(BuildNumber)"
    File="$(MSBuildProjectDirectory)\Properties\AssemblyInfo.cs"/>
</Target>

You need to have a task for replacing the AssemblyFileVersion in the AssemblyInfo.cs source. MSBuild Extension Pack has an AssemblyInfo task for this purpose.

I posted the full details at my blog here, here and here.

like image 51
Giulio Vian Avatar answered Oct 19 '22 23:10

Giulio Vian