diff --git a/scripts/GenerateTags.ps1 b/scripts/GenerateTags.ps1 index 958ab36378..5fc2ed9ee7 100755 --- a/scripts/GenerateTags.ps1 +++ b/scripts/GenerateTags.ps1 @@ -6,12 +6,15 @@ to the value in version.props .PARAMETER Push Push the tag to origin +.PARAMETER OutFile + When specified, generate a .csv with repo names and tags .PARAMETER WhatIf Dry run #> [cmdletbinding(PositionalBinding = $false, SupportsShouldProcess = $true)] param( - [switch]$Push + [switch]$Push, + [string]$OutFile ) $ErrorActionPreference = 'Stop' @@ -57,6 +60,7 @@ function New-GitTag { function Get-PackageVersion([string]$repoRoot) { $buildScript = if (-not $IsCoreCLR -or $IsWindows) { 'build.ps1' } else { 'build.sh' } $inspectTarget = "/p:CustomAfterKoreBuildTargets=$PSScriptRoot/GetPackageVersion.targets" + Write-Verbose "Running `"$repoRoot/$buildScript`" $inspectTarget /v:m /p:IsFinalBuild=true /t:Noop /t:GetPackageVersion" # Add the /t:Noop target which may be used by the bootstrapper to skip unimportant initialization $output = & "$repoRoot/$buildScript" $inspectTarget /v:m /p:IsFinalBuild=true /t:Noop /t:GetPackageVersion $output | out-string | Write-Verbose @@ -64,7 +68,7 @@ function Get-PackageVersion([string]$repoRoot) { throw "$buildScript failed on $repoRoot. Exit code $LASTEXITCODE" } $packageVersion = $output | where-object { $_ -like '*PackageVersion=*' } | select-object -first 1 - $packageVersion = $packageVersion -replace 'PackageVersion=','' + $packageVersion = $packageVersion -replace 'PackageVersion=', '' if ($packageVersion) { $packageVersion = $packageVersion.Trim() } if (-not $packageVersion) { throw "Could not determine final package version for $repoRoot" @@ -80,9 +84,16 @@ if (-not $PSCmdlet.ShouldContinue("Continue?", "This will apply tags to all subm exit 1 } + $universeTag = Get-PackageVersion $repoRoot New-GitTag $repoRoot $universeTag -WhatIf:$WhatIfPreference +$tags = @([pscustomobject] @{ + repo = $(git config remote.origin.url) + tag = $universeTag + commit = $(git rev-parse HEAD) + }) + Get-Submodules $repoRoot | ForEach-Object { $modPath = $_.path $module = $_.module @@ -96,6 +107,11 @@ Get-Submodules $repoRoot | ForEach-Object { if ($tag -ne $universeTag) { Write-Warning "${module}: version ($tag) does not match universe ($universeTag)" } + $tags += [pscustomobject] @{ + repo = $_.remote + tag = $tag + commit = $_.commit + } } catch { Write-Warning "${module}: Could not automatically determine tag for $modPath. Skipping" @@ -104,3 +120,9 @@ Get-Submodules $repoRoot | ForEach-Object { New-GitTag $_.path $tag -WhatIf:$WhatIfPreference } + +$tags | Format-Table + +if ($OutFile) { + $tags | Select-Object -Property * | Export-Csv -Path $OutFile -WhatIf:$false -NoTypeInformation +} diff --git a/scripts/common.psm1 b/scripts/common.psm1 index 0c3397fa96..b621d48193 100644 --- a/scripts/common.psm1 +++ b/scripts/common.psm1 @@ -1,3 +1,5 @@ +$ErrorActionPreference = 'Stop' + function Assert-Git { if (!(Get-Command git -ErrorAction Ignore)) { Write-Error 'git is required to execute this script' @@ -32,27 +34,32 @@ function Get-Submodules { $repos = $submoduleConfig.Project.ItemGroup.Repository | % { $_.Include } Get-ChildItem "$RepoRoot/modules/*" -Directory ` - | ? { (-not $Shipping) -or $($repos -contains $($_.Name)) -or $_.Name -eq 'Templating' } ` - | % { + | ? { (-not $Shipping) -or $($repos -contains $($_.Name)) -or $_.Name -eq 'Templating' } ` + | % { Push-Location $_ | Out-Null Write-Verbose "Attempting to get submodule info for $_" if (Test-Path 'version.props') { [xml] $versionXml = Get-Content 'version.props' - $versionPrefix = $versionXml.Project.PropertyGroup.VersionPrefix - } else { + $versionPrefix = $versionXml.Project.PropertyGroup.VersionPrefix | select-object -first 1 + $versionSuffix = $versionXml.Project.PropertyGroup.VersionSuffix | select-object -first 1 + } + else { $versionPrefix = '' + $versionSuffix = '' } try { $data = [PSCustomObject] @{ - path = $_ - module = $_.Name - commit = $(git rev-parse HEAD) - newCommit = $null - changed = $false - branch = $(git config -f $moduleConfigFile --get submodule.modules/$($_.Name).branch ) + path = $_ + module = $_.Name + commit = $(git rev-parse HEAD) + newCommit = $null + changed = $false + remote = $(git config remote.origin.url) + branch = $(git config -f $moduleConfigFile --get submodule.modules/$($_.Name).branch ) versionPrefix = $versionPrefix + versionSuffix = $versionSuffix } $submodules += $data @@ -78,7 +85,7 @@ function SaveXml([xml]$xml, [string]$path) { } function LoadXml([string]$path) { - Write-Verbose "Reading to $path" + Write-Verbose "Reading from $path" $ErrorActionPreference = 'stop' $obj = new-object xml @@ -86,3 +93,124 @@ function LoadXml([string]$path) { $obj.Load($path) return $obj } + +function PackageIdVarName([string]$packageId) { + $canonicalVarName = '' + $upperCaseNext = $true + for ($i = 0; $i -lt $packageId.Length; $i++) { + $ch = $packageId[$i] + if (-not [System.Char]::IsLetterOrDigit(($ch))) { + $upperCaseNext = $true + continue + } + if ($upperCaseNext) { + $ch = [System.Char]::ToUpperInvariant($ch) + $upperCaseNext = $false + } + $canonicalVarName += $ch + } + $canonicalVarName += "PackageVersion" + return $canonicalVarName +} + +function Ensure-Hub() { + $tmpDir = "$PSScriptRoot\tmp" + $zipDir = "$tmpDir\Hub" + $hubLocation = "$zipDir\bin\hub.exe" + + if (-Not (Test-Path $hubLocation) ) { + $source = "https://github.com/github/hub/releases/download/v2.3.0-pre9/hub-windows-amd64-2.3.0-pre9.zip" + $zipLocation = "$tmpDir\hub.zip" + if(-not (Test-Path $zipLocation)) { + New-Item -ItemType directory -Path $tmpDir + } + + Invoke-WebRequest -OutFile $zipLocation -Uri $source + + Expand-Archive -Path $zipLocation -DestinationPath $zipDir -Force + if (-Not (Test-Path $hubLocation)) { + throw "Hub couldn't be downloaded" + } + } + + return $hubLocation +} + +function CreatePR([string]$baseBranch, [string]$destinationBranch, [string]$body, [string]$gitHubToken) { + $hubLocation = Ensure-Hub + + Invoke-Block { git push -f https://$gitHubToken@github.com/aspnet/Universe.git $destinationBranch } + & $hubLocation pull-request -f -b $baseBranch -h $destinationBranch -m $body +} + +function Set-GithubInfo( + [string]$GitHubPassword, + [string]$GitHubUser, + [string]$GitHubEmail) +{ + $Env:GITHUB_TOKEN = $GitHubPassword + $Env:GITHUB_USER = $GitHubUser + $Env:GITHUB_EMAIL = $GitHubEmail +} +function CommitUpdatedVersions( + [hashtable]$updatedVars, + [xml]$dependencies, + [string]$depsPath) +{ + $count = $updatedVars.Count + if ($count -gt 0) { + & git add build\dependencies.props + + $subject = "Updating external dependencies" + + # Have to pipe null so that the output from this doesn't end up as part of the return value + $null = Invoke-Block { & git commit -m $subject } + + $body = "$subject`n`n" + + $body += "New versions:`n" + + foreach ($var in $updatedVars.GetEnumerator()) { + $body += " $($var.Name)`n" + } + + return $body + } +} + +function UpdateVersions([hashtable]$variables, [xml]$dependencies, [string]$depsPath) { + $updatedVars = @{} + + foreach ($varName in ($variables.Keys | sort)) { + $packageVersions = $variables[$varName] + if ($packageVersions.Length -gt 1) { + Write-Warning "Skipped $varName. Multiple version found. { $($packageVersions -join ', ') }." + continue + } + + $packageVersion = $packageVersions | Select-Object -First 1 + + $depVarNode = $dependencies.SelectSingleNode("//PropertyGroup[`@Label=`"Package Versions: Auto`"]/$varName") + if ($depVarNode -and $depVarNode.InnerText -ne $packageVersion) { + $depVarNode.InnerText = $packageVersion + Write-Host -f DarkGray " Updating $varName to $packageVersion" + $updatedVars[$varName] = $packageVersion + } + elseif ($depVarNode) { + Write-Host -f DarkBlue " Didn't update $varName to $packageVersion because it was $($depVarNode.InnerText)" + } + else { + # This isn't a dependency we use + } + } + + if ($updatedVars.Count -gt 0) { + Write-Host -f Cyan "Updating $count version variables in $depsPath" + SaveXml $dependencies $depsPath + } + else { + Write-Host -f Green "No changes found" + } + + return $updatedVars +}