mirror of
https://github.com/PowerShell/PowerShell.git
synced 2024-11-23 01:34:19 +08:00
Add support for back porting PRs from GitHub or the Private Azure Repos (#20670)
Co-authored-by: Dongbo Wang <dongbow@microsoft.com> --------- Co-authored-by: Dongbo Wang <dongbow@microsoft.com>
This commit is contained in:
parent
c11e4cf0d1
commit
b409e5613a
78
test/releaseTools/releaseTools.tests.ps1
Normal file
78
test/releaseTools/releaseTools.tests.ps1
Normal file
@ -0,0 +1,78 @@
|
||||
# Copyright (c) Microsoft Corporation.
|
||||
# Licensed under the MIT License.
|
||||
|
||||
BeforeDiscovery {
|
||||
|
||||
$testCases = @(
|
||||
@{
|
||||
remoteInfo = 'upstream git@ssh.dev.azure.com:v3/azDoOrg/PowerShellCore/PowerShell (fetch)'
|
||||
upstreamRemote = 'upstream'
|
||||
org = 'azDoOrg'
|
||||
project = 'PowerShellCore'
|
||||
UpstreamHost = 'git@ssh.dev.azure.com'
|
||||
RemoteType = 'AzureRepo'
|
||||
}
|
||||
@{
|
||||
remoteInfo = 'upstream https://azDoOrg.visualstudio.com/PowerShell/_git/PowerShell (fetch)'
|
||||
upstreamRemote = 'upstream'
|
||||
org = 'azDoOrg'
|
||||
project = 'PowerShell'
|
||||
UpstreamHost = 'azDoOrg.visualstudio.com'
|
||||
RemoteType = 'AzureRepo'
|
||||
}
|
||||
@{
|
||||
remoteInfo = 'upstream https://github.com/PowerShell/PowerShell.git (fetch)'
|
||||
upstreamRemote = 'upstream'
|
||||
org = 'PowerShell'
|
||||
project = 'github.com'
|
||||
UpstreamHost = 'github.com'
|
||||
RemoteType = 'GitHub'
|
||||
}
|
||||
@{
|
||||
remoteInfo = 'github https://github.com/PowerShell/PowerShell.git (fetch)'
|
||||
upstreamRemote = 'github'
|
||||
org = 'PowerShell'
|
||||
project = 'github.com'
|
||||
UpstreamHost = 'github.com'
|
||||
RemoteType = 'GitHub'
|
||||
}
|
||||
@{
|
||||
remoteInfo = 'asonetuhasoeu git@github.com:PowerShell/PowerShell.git (fetch)'
|
||||
upstreamRemote = 'asonetuhasoeu'
|
||||
org = 'PowerShell'
|
||||
project = 'github.com'
|
||||
UpstreamHost = 'github.com'
|
||||
RemoteType = 'GitHub'
|
||||
}
|
||||
|
||||
)
|
||||
}
|
||||
Describe "Get-UpstreamInfo" {
|
||||
BeforeAll {
|
||||
Import-Module $PSScriptRoot/../../tools/releaseTools.psm1 -force -Verbose
|
||||
}
|
||||
It "parses remote Info correctly: <RemoteInfo>" -TestCases $testCases -Test {
|
||||
param(
|
||||
[string]
|
||||
$RemoteInfo,
|
||||
[string]
|
||||
$UpstreamRemote,
|
||||
[string]
|
||||
$org,
|
||||
[string]
|
||||
$Project,
|
||||
[string]
|
||||
$UpstreamHost,
|
||||
[string]
|
||||
$remoteType
|
||||
)
|
||||
|
||||
$upstreamInfo = Get-UpstreamInfo -Upstream $RemoteInfo -UpstreamRemote $UpstreamRemote
|
||||
$upstreamInfo | Should -Not -BeNullOrEmpty
|
||||
$upstreamInfo.org | Should -Be $org
|
||||
$upstreamInfo.project | Should -Be $Project
|
||||
$upstreamInfo.repo | Should -Be 'PowerShell'
|
||||
$upstreamInfo.host | Should -Be $UpstreamHost
|
||||
$upstreamInfo.remoteType | Should -Be $remoteType
|
||||
}
|
||||
}
|
@ -723,6 +723,74 @@ function Get-PRBackportReport {
|
||||
$prs
|
||||
}
|
||||
}
|
||||
enum RemoteType {
|
||||
GitHub
|
||||
AzureRepo
|
||||
}
|
||||
|
||||
function Get-UpstreamInfo {
|
||||
param(
|
||||
[Parameter(Mandatory=$true)]
|
||||
[string[]]$Upstream,
|
||||
|
||||
[Parameter(Mandatory=$true)]
|
||||
[string]$UpstreamRemote
|
||||
)
|
||||
|
||||
$upstreamName = '(powershell(core)?)(/_git)?/(powershell)'
|
||||
$pattern = "^$UpstreamRemote\s*(.*)\:(.*/([-\w.]+)/)?$upstreamName(\.git)?.*fetch"
|
||||
Write-Verbose -Verbose "searching for an upstream with regex: '$pattern'"
|
||||
$Upstream = $Upstream | Where-Object { $_ -match $pattern }
|
||||
|
||||
Write-Verbose -Verbose "found $Upstream"
|
||||
|
||||
if (!$Upstream) {
|
||||
throw "Please create an upstream remote that points to $upstreamName"
|
||||
}
|
||||
|
||||
$matches | Format-Table | Out-String -Stream -Width 9999 | Write-Verbose
|
||||
$org = $matches[3]
|
||||
if ($org -ne 'github.com' -and $matches[1] -ne 'git@github.com') {
|
||||
Write-Verbose 'parsing Azure repo remote' -Verbose
|
||||
# Azure Repo remote
|
||||
$project = $matches[4]
|
||||
$repo = $matches[7]
|
||||
$upstreamHost = $matches[1]
|
||||
|
||||
if ($upstreamHost -eq 'https') {
|
||||
$upstreamHost = $org
|
||||
}
|
||||
# matches everything but `.` ending in a `.`
|
||||
# in other word, matching the first part of a hostname.
|
||||
# like `www.microsoft.com` it would match `www.` with `www` in a capture group.
|
||||
if ($org -match '([^\..]*)\.') {
|
||||
$org = $Matches[1]
|
||||
}
|
||||
} else {
|
||||
Write-Verbose 'parsing github remote' -Verbose
|
||||
# GitHub Repo remote
|
||||
$org = $matches[4]
|
||||
$repo = $matches[7]
|
||||
$upstreamHost = 'github.com'
|
||||
$project = $upstreamHost
|
||||
}
|
||||
|
||||
$remoteType = [RemoteType]::GitHub
|
||||
|
||||
if ($upstreamHost -match '.*azure.com$' -or $upstreamHost -match '.*visualstudio.com$') {
|
||||
[RemoteType] $remoteType = [RemoteType]::AzureRepo
|
||||
}
|
||||
|
||||
$upstreamMatchInfo = @{
|
||||
org = $org
|
||||
project = $project
|
||||
repo = $repo
|
||||
host = $upstreamHost
|
||||
remoteType = $remoteType
|
||||
}
|
||||
|
||||
return $upstreamMatchInfo
|
||||
}
|
||||
|
||||
# Backports a PR
|
||||
# requires:
|
||||
@ -748,7 +816,10 @@ function Invoke-PRBackport {
|
||||
$Overwrite,
|
||||
|
||||
[string]
|
||||
$BranchPostFix
|
||||
$BranchPostFix,
|
||||
|
||||
[string]
|
||||
$UpstreamRemote = 'upstream'
|
||||
)
|
||||
function script:Invoke-NativeCommand {
|
||||
param(
|
||||
@ -792,15 +863,14 @@ function Invoke-PRBackport {
|
||||
throw "PR is not merged ($state)"
|
||||
}
|
||||
|
||||
$upstream = $null
|
||||
$upstreamName = 'powershell/powershell'
|
||||
$upstream = Invoke-NativeCommand { git remote -v } | Where-Object { $_ -match "^upstream.*$upstreamName.*fetch" }
|
||||
$upstream = Invoke-NativeCommand { git remote -v }
|
||||
$upstreamMatchInfo = Get-UpstreamInfo -Upstream $upstream -UpstreamRemote $UpstreamRemote
|
||||
$remoteType = $upstreamMatchInfo.remoteType
|
||||
|
||||
if (!$upstream) {
|
||||
throw "Please create an upstream remote that points to $upstreamName"
|
||||
}
|
||||
Write-Verbose -Verbose "remotetype: $remoteType"
|
||||
$upstreamMatchInfo | Format-Table | Out-String -Stream -Width 9999 | Write-Verbose -Verbose
|
||||
|
||||
Invoke-NativeCommand { git fetch upstream $Target }
|
||||
Invoke-NativeCommand { git fetch $UpstreamRemote $Target }
|
||||
|
||||
$switch = '-c'
|
||||
if ($Overwrite) {
|
||||
@ -812,10 +882,22 @@ function Invoke-PRBackport {
|
||||
$branchName += "-$BranchPostFix"
|
||||
}
|
||||
|
||||
if ($PSCmdlet.ShouldProcess("Create branch $branchName from upstream/$Target")) {
|
||||
Invoke-NativeCommand { git switch upstream/$Target $switch $branchName }
|
||||
if ($PSCmdlet.ShouldProcess("Create branch $branchName from $UpstreamRemote/$Target")) {
|
||||
Invoke-NativeCommand { git switch $UpstreamRemote/$Target $switch $branchName }
|
||||
}
|
||||
|
||||
try {
|
||||
$revParseParams = @(
|
||||
'--verify'
|
||||
"$commitId^{commit}"
|
||||
)
|
||||
Invoke-NativeCommand { git rev-parse --quiet $revParseParams }
|
||||
}
|
||||
catch {
|
||||
throw "Commit does not exist. Try fetching the upstream. (git rev-parse $revParseParams)"
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
Invoke-NativeCommand { git cherry-pick $commitId }
|
||||
}
|
||||
@ -824,7 +906,72 @@ function Invoke-PRBackport {
|
||||
}
|
||||
|
||||
if ($PSCmdlet.ShouldProcess("Create the PR")) {
|
||||
gh pr create --base $Target --title $backportTitle --body "Backport #$PrNumber" --web
|
||||
$body = "Backport #$PrNumber"
|
||||
switch($remoteType) {
|
||||
"AzureRepo" {
|
||||
Write-Verbose -Verbose "Pushing branch to $UpstreamRemote"
|
||||
git push --set-upstream $UpstreamRemote HEAD
|
||||
$parameters = @(
|
||||
'repos'
|
||||
'pr'
|
||||
'create'
|
||||
)
|
||||
# Open in the browser
|
||||
$parameters += @(
|
||||
'--open'
|
||||
)
|
||||
$parameters += @(
|
||||
'--target-branch'
|
||||
$Target
|
||||
)
|
||||
$parameters += @(
|
||||
'--title'
|
||||
$backportTitle
|
||||
)
|
||||
$parameters += @(
|
||||
'--description'
|
||||
$body
|
||||
)
|
||||
$parameters += @(
|
||||
'--squash'
|
||||
'true'
|
||||
)
|
||||
$parameters += @(
|
||||
'--auto-complete'
|
||||
'true'
|
||||
)
|
||||
$parameters += @(
|
||||
'--delete-source-branch'
|
||||
'true'
|
||||
)
|
||||
$parameters += @(
|
||||
'--org'
|
||||
"https://dev.azure.com/$($upstreamMatchInfo.org)"
|
||||
)
|
||||
$parameters += @(
|
||||
'--project'
|
||||
$upstreamMatchInfo.project
|
||||
)
|
||||
$parameters += @(
|
||||
'--source-branch'
|
||||
$branchName
|
||||
)
|
||||
$parameters += @(
|
||||
'--repository'
|
||||
$upstreamMatchInfo.repo
|
||||
)
|
||||
|
||||
Write-Verbose -Verbose "az $parameters"
|
||||
$null = Invoke-NativeCommand { az $parameters }
|
||||
}
|
||||
"GitHub" {
|
||||
Write-Verbose -Verbose "Creating PR using gh CLI"
|
||||
gh pr create --base $Target --title $backportTitle --body $body --web
|
||||
}
|
||||
default {
|
||||
throw "unknown remoteType: $remoteType"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -848,4 +995,4 @@ function Invoke-PRBackportApproved {
|
||||
}
|
||||
}
|
||||
|
||||
Export-ModuleMember -Function Get-ChangeLog, Get-NewOfficalPackage, Update-PsVersionInCode, Get-PRBackportReport, Invoke-PRBackport, Invoke-PRBackportApproved
|
||||
Export-ModuleMember -Function Get-ChangeLog, Get-NewOfficalPackage, Update-PsVersionInCode, Get-PRBackportReport, Invoke-PRBackport, Invoke-PRBackportApproved, Get-UpstreamInfo
|
||||
|
Loading…
Reference in New Issue
Block a user