I have got a Team Foundation Server Build running cleanly. It produces several assemblies and I would like the assemblies versions to have the last number to be the changset number. That is, if I commit with a changeset11667 for example the assembly version number should be "x.y.z.11667". I've checked the availible macros, but none is the changeset number.
I would still like to be able to build the solution file on my dev machine as normal, just using the checked in version number.
How would I go about getting this in place?
Realize that this will stop working once you exceed 65,535 changesets. Perhaps you want to update some other field. BTW, yes, build engineering is engineering. Pointing at a solution and telling it to build is only the beginning of the journey.
Have a look at the Community TFS Build Extension project on CodePlex. It contains an AssemblyInfo activity and the TfsVersion activity that are capable of changing the assembly info during the build process using a custom format.
To have it build on your dev machine you have to implement those build extensions on your own using batch files and the TFS command line utilities.
I am working on a tool to automate the build process it is still on development and it's open source here is the link (I am planning a release in about one week):
https://github.com/jupaol/NCastor
Now I would recommend you to check the Semantic versioning:
http://semver.org/
To get the latest changeset from TFS, you have several options:
I built a custom routine to do this
https://github.com/jupaol/NCastor/blob/develop/Solutions/NCastor.AutoBuilder/NCastor.AutoBuilder.Runner/Targets/Build/Versioning/VersionControlServers/TFS/GetTFSRevisionVersion.target
I had to build that routine because the Community tasks and the MSBuild Extenssions tasks were not working on a 64bits machine, if you are using a 32bits machine to build then you can use the following tasks:
Using http://msbuildextensionpack.codeplex.com/
<UsingTask AssemblyFile="$(ExtensionTasksPath)MSBuild.ExtensionPack.dll" TaskName="MSBuild.ExtensionPack.VisualStudio.TfsVersion"/>
Using http://msbuildtasks.tigris.org/
<UsingTask AssemblyFile="$(MSBuildCommunityTasksLib)" TaskName="MSBuild.Community.Tasks.Tfs.TfsVersion" />
Example to set the different versions:
<UsingTask AssemblyFile="$(MSBuildCommunityTasksLib)" TaskName="MSBuild.Community.Tasks.AssemblyInfo" />
<MSBuild.Community.tasks.AssemblyInfo OutputFile="$(AssemblyVersionFilePath)"
CodeLanguage="C#"
AssemblyFileVersion="$(FileVersion)"
AssemblyInformationalVersion="$(InformationalVersion)"
AssemblyVersion="$(SemanticVersion)" />
Once you have created the file simply add that file as a link to each project and voila! all your projects are sharing the common assembly info.
In the end a colleague of mine wrote the following MSBuild task that solved the problem.
public class GetNextBuildNumber : Task
{
[Required]
public string TfsCommand { get; set; }
[Required]
public string TfsArgument { get; set; }
[Output]
public int BuildNumber { get; set; }
public override bool Execute()
{
BuildNumber = GetLatestVersionNumber();
return true;
}
private int GetLatestVersionNumber()
{
var process = new RunProcess();
var result = process.ExecuteCommand(TfsCommand, TfsArgument);
return ParseResult(result);
}
private int ParseResult(string result)
{
const string changeset = "Changeset:";
const string user = "User:";
if (string.IsNullOrEmpty(result) || !result.Contains(changeset))
{
// Invalid result
Log.LogWarning("Could not get latest build number. Reason: " + result);
return 0;
}
var indexOfChangeset = result.IndexOf(changeset, StringComparison.InvariantCulture) + changeset.Length;
var indexOfUser = result.IndexOf(user, StringComparison.InvariantCulture);
var revision = result.Substring(indexOfChangeset, indexOfUser - indexOfChangeset).Trim();
return Convert.ToInt32(revision);
}
}
For what purpose are you wanted to do that ?
If you want to have a relation between a DLL and the source code to pull from TFS the best way is to index the symbols using TFS Source Control in the PDB generation.
This way when you debug any version of your software Visual Studio will get the right version of the source from TFS when needed.