Get-TimeBasedVersionString.ps1
$ErrorActionPreference = "Stop" function Get-TimeBasedVersionString([string]$buildType) { # Only compatible with Azure DevOps (for now). # We expect the name of the pipeline (in Build.BuildNumber) to be "$(date:yyyyMMdd)$(rev:.rr)"". # This is transformed into a version number of the form "yyyy.Mdd.r". # To this, we suffix the Git commit ID (-abcabcabc). # To this, we prefix the branch name if this is not the default branch (my-branch-123-). # Note about incrementing build numbers: The major and minor part are date-based, so strictly increasing. # The revision, however, is specific to the build pipeline! Different pipelines have different revision counters. # As such, you could theoretically create multiple builds from different pipelines with the same version string. # This is not ideal, especially for NuGet which will reject duplicates we attempt to publish. # The solution? Suffix the version string with the build type. # This suffix will also serve as the NuGet "preview version" marker string (1.2.3-foobar). # So the final full version string will be [branch-name-]1111.2222.33-abcabca[-foobar] # Number of digits may vary in some components. $commitId = $env:BUILD_SOURCEVERSION $original = $env:BUILD_BUILDNUMBER if (!$commitId) { Write-Error "BUILD_SOURCEVERSION environment variable not defined." } if (!$original) { Write-Error "BUILD_BUILDNUMBER environment variable not defined." } ### Figure out the version number. $buildNumberParser = '^(?<major>\d{4})(?<minor>\d{4})\.(?<revision>\d+)$' if (-not ($original -match $buildNumberParser)) { Write-Error "Pipeline name $original does not match regex: $buildNumberParser" } $major = $Matches.major $minor = $Matches.minor.TrimStart('0') $revision = $Matches.revision.TrimStart('0') $versionNumber = "$major.$minor.$revision" Write-Host "Version number is $versionNumber" ### Add Git commit ID. $DESIRED_COMMIT_ID_LENGTH = 7 if ($commitId.Length -gt $DESIRED_COMMIT_ID_LENGTH) { $commitId = $commitId.Substring(0, $DESIRED_COMMIT_ID_LENGTH) } ### Add branch prefix. $PRIMARY_BRANCH_NAMES = @("master", "main", "dev") if ($env:SYSTEM_PULLREQUEST_SOURCEBRANCH) { # This is an Azure PR build. $sourceRef = $env:SYSTEM_PULLREQUEST_SOURCEBRANCH # We obtained the reference to the source branch but don't have the prefix figured out yet. # So we cut the reference string (refs/heads/abc123) after the last / and life is easy again. if ($sourceRef.Contains("/")) { $branchPrefix = $sourceRef.Substring($sourceRef.LastIndexOf("/") + 1) } else { Write-Error "Unable to parse source reference: $sourceRef" } } elseif ($env:BUILD_SOURCEBRANCHNAME -and $PRIMARY_BRANCH_NAMES -notcontains $env:BUILD_SOURCEBRANCHNAME) { # This is an ADO build of a non-primary branch but is not a pull request. # Just tick the branch name in front (lowercase). $branchPrefix = ($env:BUILD_SOURCEBRANCHNAME).ToLower() } if ($branchPrefix) { $branchPrefix = $branchPrefix + "-" } ### Make the final version string. if ($buildType) { $buildTypeSuffix = "-$buildType" } $versionString = "$branchPrefix$versionNumber-$commitId$buildTypeSuffix" Write-Host "Version string is $versionString" Write-Host "##vso[task.setvariable variable=VERSION_STRING;]$versionString" return $versionString } |