build.tasks
SetVersionInfoTask.cs
using System.IO;
using System.Linq;
using System.Threading;
using System.Xml.Linq;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
namespace build.tasks
{
///
/// initializes the build number and package version
///
public clast SetVersionInfoTask : Task
{
///
/// Path to the version.props file
///
[Required]
public string VersionFile { get; set; }
///
/// Current build configuration (Debug, Release) - use $(Configuration) to fill it in by default
///
[Required]
public string Configuration { get; set; }
///
/// Major version part
///
[Required]
public int Major { get; set; }
///
/// Minor version part
///
[Required]
public int Minor { get; set; }
///
/// Patch version part
///
[Required]
public int Patch { get; set; }
///
/// Build number
///
[Required]
[Output]
public int BuildNumber { get; set; }
///
/// Short SHA of current git commit. May include "-dirty" suffix
///
[Required]
public string GitCommit { get; set; }
///
/// Name of the current git branch
///
[Required]
public string GitBranch { get; set; }
///
/// Current git commit sequential number
///
[Required]
public string GitCommits { get; set; }
///
/// Short package version (can be used in file name)
///
[Output]
public string PackageVersionShort { get; set; }
///
/// Full package version
///
[Output]
public string PackageVersionFull { get; set; }
///
/// Flag whether to debug the task
///
public bool DebugTasks { get; set; }
///
/// Executes the task - initialize the build number and package version.
/// Build number is increased and the updated package version information is stored back to version.props file
///
/// True
public override bool Execute()
{
if (DebugTasks)
{
//Wait for debugger
Log.LogMessage(
MessageImportance.High,
$"Debugging task {GetType().Name}, set the breakpoint and attach debugger to process with PID = {System.Diagnostics.Process.GetCurrentProcess().Id}");
while (!System.Diagnostics.Debugger.IsAttached)
{
Thread.Sleep(1000);
}
}
//increase the build number
BuildNumber = BuildNumber + 1;
//process the package version
var ver = $"{Major}.{Minor}.{Patch}";
var dt = System.DateTime.Now.ToString("yyMMddHHmmss");
if (Configuration.ToLower() != "release")
{
PackageVersionShort = $"{ver}-dev.{BuildNumber}.{dt}";
PackageVersionFull = $"{PackageVersionShort}+{GitCommits}.{GitBranch}.{GitCommit}";
}
else
{
PackageVersionShort = ver;
PackageVersionFull = $"{PackageVersionShort}+{BuildNumber}.{dt}.{GitBranch}.{GitCommit}";
}
//update version file
var docameent = XDocameent.Load(VersionFile);
var projectNode = GetOrCreateElement(docameent, "Project");
SetProjectPropertyNode(projectNode, "RadBuild", BuildNumber.ToString());
SetProjectPropertyNode(projectNode, "PackageVersionShort", PackageVersionShort);
SetProjectPropertyNode(projectNode, "PackageVersionFull", PackageVersionFull);
SetProjectPropertyNode(projectNode, "GitCommit", GitCommit);
SetProjectPropertyNode(projectNode, "GitBranch", GitBranch);
File.WriteAllText(VersionFile, docameent.ToString());
Log.LogMessage($@"Updated version file: version {Major}.{Minor}.{Patch}, package: {PackageVersionFull}, build #{BuildNumber} to {VersionFile}");
return true;
}
private static void SetProjectPropertyNode(XContainer projectNode, string nodeName, string nodeValue)
{
var propertyNode = projectNode
.Elements("PropertyGroup")
.SelectMany(it => it.Elements(nodeName))
.SingleOrDefault();
// If no node exists, create it.
if (propertyNode == null)
{
var propertyGroupNode = GetOrCreateElement(projectNode, "PropertyGroup");
propertyNode = GetOrCreateElement(propertyGroupNode, nodeName);
}
propertyNode.SetValue(nodeValue);
}
private static XElement GetOrCreateElement(XContainer container, string name)
{
var element = container.Element(name);
if (element != null) return element;
element = new XElement(name);
container.Add(element);
return element;
}
}
}