csharp/adamecr/Common.DMN.Engine/build.tasks/SetVersionInfoTask.cs

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;
        }
    }
}