Just wondering what\'s the best approach to versioning of .NET builds?
I use:
Injecting the Changeset number is great, but it really doesn't do everything I need it to. For instance, if I know the changeset number of a build produced by my build system, do I really know what is in that executable? No I do not, as the build could have been a private build, or even a failed build.
We put our trust in the Build number (BuildID, really) instead, so that we can get as much data about that build as possible by querying the TFS system after the fact. This way we can determine if the build was a private build, was a build that had special command line parameters passed to it, and other pertinent details.
We use the following setup:
Set the build format in the build definition to be something like: 1.0.0.$(BuildId)
In the build process template, in the MSBuild task, inject the following to the MSBuildArguments item
String.format("/p:BuildNumber={0}", BuildDetail.BuildNumber)...ensure you leave what was already there.In your projects (or ideally, a common props file included in all your projects) defined a property called build number that defaults to something like 0.0.0.1.
0.0.0.1 note that you can further break this down however you like using property functions. We use this to get the Major number for instance:$(BuildNumber.Split('.')[0]) and yes, this does put a dependency on the build number format in our builds!In your project, you can make use of the build number property to inject into various files during build time. You can use custom build tasks (I use 'sed' and this macro to inject a version number into a .h file for instance - the same could be done with any text-based file type).
If you have more complex versioning requirements you can make use of custom MSBuild targets that inject the build number into other file types. I have done exactly that with versioning for NuGet packages that our builds automatically create for our common-library CS projects for example.
To query a build by its build number then, you can do the following in PowerShell (with the Visual Studio Team Foundation Server Power Tools installed):
Add-PSSnapin Microsoft.TeamFoundation.PowerShell # you must install the VS TFS Power tools with the powershell option enabled to get this... a must have IMHO
$tfs = Get-TfsServer http://yourtfsserver:8080/tfs/YourProjectCollectionName
[void][Reflection.Assembly]::LoadWithPartialName('Microsoft.TeamFoundation.Build.Client')
$buildserver = $tfs.GetService([Microsoft.TeamFoundation.Build.Client.IBuildServer])
$buildQuerySpec = $buildserver.CreateBuildDetailSpec("YourTFSProjectName","Your-Build-Definition-Name")
$buildQuerySpec.BuildNumber = '1.0.0.12345' # put your build number here.
$buildQuerySpec.QueryDeletedOption = 'IncludeDeleted'
$bld = $buildserver.QueryBuilds($buildQuerySpec)
With the '$bld' you can now query all the properties of that particular build. For instance, to see what changeset the build was based on, the status of the build, who instigated the build, and if there was a shelveset for the build:
$bld.Builds[0] | Ft -Property BuildFinished,RequestedFor,ShelvesetName,Status,SourceGetVersion -AutoSize
Edit: Correct typo in Powershell script