Skip to content

Commit

Permalink
Fix PGO Pipeline (#6796)
Browse files Browse the repository at this point in the history
  • Loading branch information
kmahone authored Mar 8, 2022
1 parent fad4b58 commit 5bb3b05
Show file tree
Hide file tree
Showing 5 changed files with 136 additions and 56 deletions.
1 change: 1 addition & 0 deletions build/AzurePipelinesTemplates/MUX-BuildProject-Steps.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ steps:
targetType: filePath
workingDirectory: $(Build.SourcesDirectory)\tools\MUXPGODatabase
filePath: $(Build.SourcesDirectory)\tools\MUXPGODatabase\restore-pgodb.ps1
arguments: -NuGetConfigPath $(Build.SourcesDirectory)\nuget.config
- task: 333b11bd-d341-40d9-afcf-b32d5ce6f23b@2
displayName: 'NuGet restore ${{ parameters.solutionPath }}'
Expand Down
6 changes: 4 additions & 2 deletions tools/MUXPGODatabase/config.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,7 @@ $packageId = "MUXPGODatabase"

# Get release version
[xml] $customProps = ( Get-Content "..\..\version.props" )
$releaseVersionMajor = ( [int]::Parse( $customProps.GetElementsByTagName("MUXVersionMajor").'#text' ) )
$releaseVersionMinor = ( [int]::Parse( $customProps.GetElementsByTagName("MUXVersionMinor").'#text' ) )
$releaseVersionMajor = ( [int64]::Parse( $customProps.GetElementsByTagName("MUXVersionMajor").'#text' ) )
$releaseVersionMinor = ( [int64]::Parse( $customProps.GetElementsByTagName("MUXVersionMinor").'#text' ) )
$releaseVersionPatch = [int64] 0
$releaseVersionPrerelease = $null
5 changes: 3 additions & 2 deletions tools/MUXPGODatabase/generate-nuspec.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ Param(
. .\template.ps1
. .\config.ps1

$version = FormatVersion ( MakeVersion $releaseVersionMajor $releaseVersionMinor ( GetDatetimeStamp $pgoBranch ) )
Write-Host ( "PGO INSTRUMENT: generating {0} version {1}" -f $packageId, $version )
$forkPoint = ( GetForkPoint $pgoBranch )
$version = FormatVersion ( MakeVersion $releaseVersionMajor $releaseVersionMinor $releaseVersionPatch $releaseVersionPrerelease $forkPoint.DateString $forkPoint.BranchString )
Write-Host ( "PGO INSTRUMENT: generating {0} version {1} ({2})" -f $packageId, $version, $forkPoint.SHA )
FillOut-Template $templatePath $outputPath @{ "version" = $version; "id" = $packageId }
80 changes: 59 additions & 21 deletions tools/MUXPGODatabase/restore-pgodb.ps1
Original file line number Diff line number Diff line change
@@ -1,47 +1,85 @@
Param(
[Parameter(Position=0, Mandatory=$true)]
[string] $NuGetConfigPath
)

. .\version.ps1
. .\template.ps1
. .\config.ps1

$feedUri = "https://pkgs.dev.azure.com/ms/microsoft-ui-xaml/_packaging/MUX-Dependencies/nuget/v2"
function Get-AvailablePackages ( $package )
{
$result = @()

$output = ( & nuget.exe list $package -prerelease -allversions -configfile $NuGetConfigPath )

$currentVersion = MakeVersion $releaseVersionMajor $releaseVersionMinor ( GetDatetimeStamp $pgoBranch )
if ( $LastExitCode -ne 0 )
{
throw "FAILED: nuget.exe list"
}

Write-Host ( "PGO OPTIMIZE: requesting {0} version {1}" -f $packageId, ( FormatVersion $currentVersion ) )
foreach ( $line in $output )
{
$name, $version = $line.Split(" ")

$packageSource = Register-PackageSource -ForceBootstrap -Name MUX_Dependencies -Location $feedUri -ProviderName NuGet -Trusted
$packages = ( Find-Package $packageId -Source MUX_Dependencies -AllowPrereleaseVersions -AllVersions ) | Sort-Object -Property Version -Descending
if ( $name -eq $package )
{
$result += ( MakeVersionFromString $version )
}
}

$best = $null
return $result
}

foreach ( $existing in $packages )
function Install-Package ( $package, $version )
{
$existingVersion = MakeVersionFromString $existing.Version
& nuget.exe install $package -prerelease -version $version -configfile $NuGetConfigPath

if ( $LastExitCode -ne 0 )
{
throw "FAILED: nuget.exe install"
}
}

$forkPoint = ( GetForkPoint $pgoBranch )

$requestedVersion = MakeVersion $releaseVersionMajor $releaseVersionMinor $releaseVersionPatch $releaseVersionPrerelease $forkPoint.DateString $forkPoint.BranchString

Write-Host ( "PGO OPTIMIZE: requesting {0} version {1} ({2})" -f $packageId, ( FormatVersion $requestedVersion ), $forkPoint.SHA )

if ( ( CompareBranches $existingVersion $currentVersion ) -eq $False -or
( CompareReleases $existingVersion $currentVersion ) -ne 0 )
$packageVersions = ( Get-AvailablePackages $packageId ) | Sort-Object -Descending -Property Major, Minor, Patch, Prerelease, Branch, Revision

$bestVersion = $null

foreach ( $existingVersion in $packageVersions )
{
if ( ( CompareReleaseAndBranch $existingVersion $requestedVersion ) -eq $False )
{
# If this is different release or branch, then skip it.
# If this is different release number, pre-release tag or branch, then skip it.
continue
}

if ( ( CompareRevisions $existingVersion $currentVersion ) -le 0 )
# Sorting guarantees that all eligible entries are consecutive and sorted according to decreasing revision time stamp.
# Revisions are fixed, 10 character strings containing numbers (YYMMHHhhmm). Sorting will arrange them reverse-chronologically.
# Once we are here, we are beginning of that segment.

if ( ( CompareRevisions $existingVersion $requestedVersion ) -le 0 )
{
# Version are sorted in descending order, the first one less than or equal to the current is the one we want.
# NOTE: at this point the only difference between versions will be revision (date-time stamp)
# which is formatted as a fixed-length string, so string comparison WILL sort it correctly.
$best = $existing
# Revisions are sorted in descending order, the first one less than or equal to the current is the one we want.
$bestVersion = $existingVersion
break
}
}

if ( $best -eq $null )
if ( $bestVersion -eq $null )
{
throw "Appropriate database cannot be found"
}

Write-Host ( "PGO OPTIMIZE: picked {0} version {1}" -f $packageId, $best.Version )
$bestVersionAsString = ( FormatVersion $bestVersion )

Write-Host ( "PGO OPTIMIZE: picked {0} version {1}" -f $packageId, $bestVersionAsString )

$best | Install-Package -Destination ..\..\packages -Force
$packageSource | Unregister-PackageSource
Install-Package $packageId $bestVersionAsString

FillOut-Template "PGO.version.props.template" "PGO.version.props" @{ "version" = $best.Version; "id" = $packageId }
FillOut-Template "PGO.version.props.template" "PGO.version.props" @{ "version" = $bestVersionAsString; "id" = $packageId }
100 changes: 69 additions & 31 deletions tools/MUXPGODatabase/version.ps1
Original file line number Diff line number Diff line change
@@ -1,61 +1,95 @@
function MakeVersion ( $major, $minor, $datetimeStamp )
{
$revision, $branch = $datetimeStamp.Split("-")

if ( $branch -eq $null )
{
$branch = ""
}
$REVISION_FMT = 'yyMMddHHmm'

function MakeVersion ( $major, $minor, $patch, $prerelease, $revision, $branch )
{
return [PSCustomObject] @{
Major = $major
Minor = $minor
Revision = $revision
Branch = $branch
Major = [int64] $major
Minor = [int64] $minor
Patch = [int64] $patch
Prerelease = [string] $prerelease
Revision = [string] $revision
Branch = [string] $branch
}
}

function MakeVersionFromString ( $str )
{
$parts = $str.Split(".")
return MakeVersion ( [int]::Parse($parts[0]) ) ( [int]::Parse($parts[1]) ) $parts[2]
$match = [Regex]::match($str, '^(?<major>0|[1-9]\d*)\.(?<minor>0|[1-9]\d*)\.(?<patch>0|[1-9]\d*)(?:-(?<prerelease>(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+(?<buildmetadata>[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$')

if ( -not $match.Success )
{
throw "Failed to parse version string."
}

$REVISION_RE = '(?<revision>[0-9]{10})'
$BRANCH_RE = '(?<branch>[a-zA-Z0-9-]+)'

$prereleaseMatch = [Regex]::match($match.Groups["prerelease"].Value, "^((?<actualprerelease>.*)-)?$REVISION_RE-$BRANCH_RE$")

if ( $prereleaseMatch.Success )
{
# new way: revision + branch encoded in prerelease tag
return MakeVersion $match.Groups["major"].Value `
$match.Groups["minor"].Value `
$match.Groups["patch"].Value `
$prereleaseMatch.Groups["actualprerelease"].Value `
$prereleaseMatch.Groups["revision"].Value `
$prereleaseMatch.Groups["branch"].Value
}
else
{
# old way: revision in patch and branch is prerelease
$patchMatch = [Regex]::match($match.Groups["patch"].Value, "^$REVISION_RE$")
$prereleaseMatch = [Regex]::match($match.Groups["prerelease"].Value, "^$BRANCH_RE$")

if ( -not ( $patchMatch.Success -and $prereleaseMatch.Success ) )
{
throw "Failed to parse fork point form version string."
}

return MakeVersion $match.Groups["major"].Value `
$match.Groups["minor"].Value `
0 `
$null `
$patchMatch.Groups["revision"].Value `
$prereleaseMatch.Groups["branch"].Value
}
}

function FormatVersion ( $version )
{
$branch = ""

if ( $version.Branch -ne "" )
if ( $version.Branch -and $version.Branch -ne "" )
{
$branch = "-{0}" -f $version.Branch
}

return "{0}.{1}.{2}{3}" -f $version.Major, $version.Minor, $version.Revision, $branch
}
$prerelease = ""

function CompareReleases ( $version1, $version2 )
{
$cmpMajor = [Math]::Sign($version1.Major - $version2.Major)

if ( $cmpMajor -ne 0 )
if ( $version.Prerelease -and $version.Prerelease -ne "" )
{
return $cmpMajor
$prerelease = "-{0}" -f $version.Prerelease
}

return [Math]::Sign($version1.Minor - $version2.Minor)
return "{0}.{1}.{2}{3}-{4}{5}" -f $version.Major, $version.Minor, $version.Patch, $prerelease, $version.Revision, $branch
}

function CompareRevisions ( $version1, $version2 )
function CompareReleaseAndBranch ( $version1, $version2 )
{
return [Math]::Sign($version1.Revision - $version2.Revision)
return ( $version1.Major -eq $version2.Major ) -and
( $version1.Minor -eq $version2.Minor ) -and
( $version1.Patch -eq $version2.Patch ) -and
( $version1.Prerelease -like $version2.Prerelease ) -and
( $version1.Branch -like $version2.Branch )
}

function CompareBranches ( $version1, $version2 )
function CompareRevisions ( $version1, $version2 )
{
return $version1.Branch -eq $version2.Branch
return [DateTime]::ParseExact($version1.Revision, $REVISION_FMT, $null) - [DateTime]::ParseExact($version2.Revision, $REVISION_FMT, $null)
}

function GetDatetimeStamp ( $pgoBranch )
function GetForkPoint ( $pgoBranch )
{
$forkSHA = $( git merge-base origin/$pgoBranch HEAD )

Expand All @@ -64,12 +98,16 @@ function GetDatetimeStamp ( $pgoBranch )
throw "FAILED: git merge-base"
}

$forkDate = ( Get-Date -Date $( git log -1 $forkSHA --date=iso --pretty=format:"%ad" ) ).ToUniversalTime().ToString("yyMMddHHmm")
$forkDate = ( Get-Date -Date $( git log -1 $forkSHA --date=iso --pretty=format:"%ad" ) ).ToUniversalTime().ToString($REVISION_FMT)

if ( $LastExitCode -ne 0 )
{
throw "FAILED: Get forkDate"
}

return $forkDate + "-" + $pgoBranch.Replace("/", "_").Replace("-", "_").Replace(".", "_")
return [PSCustomObject] @{
DateString = $forkDate
BranchString = ( $pgoBranch -replace "(/|\.|@|>|<)", "-" )
SHA = $forkSHA
}
}

0 comments on commit 5bb3b05

Please sign in to comment.