-
Couldn't load subscription status.
- Fork 4.1k
Add Merge-DevPullRequest cmdlet and update documentation #28718
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,198 @@ | ||||||||||
| function Merge-DevPullRequest { | ||||||||||
| <# | ||||||||||
| .SYNOPSIS | ||||||||||
| Merges pull requests in the azure-powershell repository. | ||||||||||
|
|
||||||||||
| .DESCRIPTION | ||||||||||
| Helps merge pull requests in the azure-powershell repo. When using -AllArchivePR, for safety, | ||||||||||
| it only supports merging PRs with the "[skip ci]" prefix in the title and created by the | ||||||||||
| "azure-powershell-bot" user, which are the archive PRs for generated modules. | ||||||||||
| When using -Number, any PR can be merged. | ||||||||||
|
|
||||||||||
| .PARAMETER Number | ||||||||||
| The pull request number(s) to merge. Can be a single number or an array of numbers. | ||||||||||
|
|
||||||||||
| .PARAMETER AllArchivePR | ||||||||||
| Lists all matching PRs (ordered by CreatedAt ascending) and prompts for confirmation before merging. | ||||||||||
|
|
||||||||||
| .PARAMETER Approve | ||||||||||
| Approve the pull request before merging. | ||||||||||
|
|
||||||||||
| .PARAMETER Force | ||||||||||
| Skip confirmation prompts. | ||||||||||
|
|
||||||||||
| .EXAMPLE | ||||||||||
| Merge-DevPullRequest -Approve -Number 28690 | ||||||||||
|
|
||||||||||
| .EXAMPLE | ||||||||||
| Merge-DevPullRequest -Approve -Number 28690, 28691, 28692 | ||||||||||
|
|
||||||||||
| .EXAMPLE | ||||||||||
| Merge-DevPullRequest -Approve -AllArchivePR -Force | ||||||||||
|
|
||||||||||
| .NOTES | ||||||||||
| Requires GitHub CLI to be installed and authenticated (gh auth login). | ||||||||||
| #> | ||||||||||
| [CmdletBinding(DefaultParameterSetName = 'Single')] | ||||||||||
| [Alias('Merge-DevPR')] | ||||||||||
| param( | ||||||||||
| [Parameter(Mandatory = $true, ParameterSetName = 'Single')] | ||||||||||
| [int[]]$Number, | ||||||||||
|
|
||||||||||
| [Parameter(Mandatory = $true, ParameterSetName = 'All')] | ||||||||||
| [switch]$AllArchivePR, | ||||||||||
|
|
||||||||||
| [switch]$Approve, | ||||||||||
|
|
||||||||||
| [switch]$Force | ||||||||||
| ) | ||||||||||
|
|
||||||||||
| # Check if GitHub CLI is available | ||||||||||
| try { | ||||||||||
| gh --version | Out-Null | ||||||||||
| } | ||||||||||
| catch { | ||||||||||
| throw "GitHub CLI is not installed or not in PATH. Please install GitHub CLI and authenticate with 'gh auth login'." | ||||||||||
| } | ||||||||||
|
|
||||||||||
| # Check if authenticated | ||||||||||
| try { | ||||||||||
| gh auth status | Out-Null | ||||||||||
| } | ||||||||||
| catch { | ||||||||||
| throw "GitHub CLI is not authenticated. Please run 'gh auth login' first." | ||||||||||
| } | ||||||||||
|
|
||||||||||
| $mergedPRs = @() | ||||||||||
| $failedPRs = @() | ||||||||||
|
|
||||||||||
| if ($PSCmdlet.ParameterSetName -eq 'Single') { | ||||||||||
| # Get PR details for each number | ||||||||||
| $prsToMerge = @() | ||||||||||
| foreach ($prNumber in $Number) { | ||||||||||
| try { | ||||||||||
| $prJson = gh pr view $prNumber --json number,title,author,createdAt,url 2>$null | ||||||||||
| if ($LASTEXITCODE -ne 0) { | ||||||||||
| throw "Pull request #$prNumber not found." | ||||||||||
| } | ||||||||||
| $pr = $prJson | ConvertFrom-Json | ||||||||||
| $prsToMerge += $pr | ||||||||||
| } | ||||||||||
| catch { | ||||||||||
| throw "Failed to get pull request #$prNumber: $_" | ||||||||||
| } | ||||||||||
| } | ||||||||||
| } | ||||||||||
| else { | ||||||||||
| # Get all archive PRs | ||||||||||
| try { | ||||||||||
| $allPRsJson = gh pr list --state open --author azure-powershell-bot --json number,title,author,createdAt,url 2>$null | ||||||||||
DanielMicrosoft marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||
| if ($LASTEXITCODE -ne 0) { | ||||||||||
| throw "Failed to list pull requests." | ||||||||||
| } | ||||||||||
| $allPRs = $allPRsJson | ConvertFrom-Json | ||||||||||
| } | ||||||||||
| catch { | ||||||||||
| throw "Failed to list pull requests: $_" | ||||||||||
| } | ||||||||||
|
|
||||||||||
| # Filter for archive PRs (with [skip ci] prefix) | ||||||||||
| $archivePRs = $allPRs | Where-Object { $_.title.StartsWith('[skip ci]') } | Sort-Object createdAt | ||||||||||
|
|
||||||||||
| if ($archivePRs.Count -eq 0) { | ||||||||||
| Write-Host "No archive PRs found matching criteria." | ||||||||||
| return @() | ||||||||||
| } | ||||||||||
|
|
||||||||||
| $prsToMerge = $archivePRs | ||||||||||
| } | ||||||||||
|
|
||||||||||
| # Display PRs to be merged | ||||||||||
| if ($prsToMerge.Count -gt 0) { | ||||||||||
| if (-not $Force) { | ||||||||||
| $confirmMessage = "Do you want to" | ||||||||||
| if ($Approve) { $confirmMessage += " approve and" } | ||||||||||
| $confirmMessage += " merge the following pull request$(if($prsToMerge.Count -gt 1){'s'})?" | ||||||||||
| Write-Host $confirmMessage | ||||||||||
| } | ||||||||||
|
|
||||||||||
| # Format and display PRs | ||||||||||
| $prTable = $prsToMerge | ForEach-Object { | ||||||||||
| [PSCustomObject]@{ | ||||||||||
| 'No.' = $_.number | ||||||||||
| 'Title' = $_.title | ||||||||||
| 'CreatedBy' = $_.author.login | ||||||||||
| 'CreatedAt' = [DateTime]::Parse($_.createdAt).ToString('M/d/yyyy h:mm:ss tt') | ||||||||||
|
||||||||||
| 'CreatedAt' = [DateTime]::Parse($_.createdAt).ToString('M/d/yyyy h:mm:ss tt') | |
| 'CreatedAt' = ([DateTime]::Parse($_.createdAt).ToUniversalTime().ToString('yyyy-MM-ddTHH:mm:ssZ')) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@isra-fel I believe this could be a valid point.
DanielMicrosoft marked this conversation as resolved.
Show resolved
Hide resolved
DanielMicrosoft marked this conversation as resolved.
Show resolved
Hide resolved
Copilot
AI
Oct 20, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The function throws (line 183) before reaching the return block (line 186) when any PR fails, contradicting the documented behavior that successfully merged PRs are still returned. Move the return construction before the throw or replace the throw with a non-terminating Write-Error so merged PRs are output. Example fix: build the result object, Write-Error if failures exist, then return the result without throwing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is valid as there is no wrapping catch.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated: merged PRs are returned before the errors are thrown
Copilot
AI
Oct 20, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nitpick] Using a culture-dependent format ('M/d/yyyy h:mm:ss tt') produces ambiguous dates and hampers machine parsing. Prefer an invariant/ISO 8601 format such as ToString('yyyy-MM-ddTHH:mm:ssZ') (after ensuring UTC) or return the DateTime object directly for consumers to format.
| 'CreatedAt' = [DateTime]::Parse($_.createdAt).ToString('M/d/yyyy h:mm:ss tt') | |
| 'CreatedAt' = ([DateTime]::Parse($_.createdAt).ToUniversalTime().ToString('yyyy-MM-ddTHH:mm:ssZ')) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| 'CreatedAt' = [DateTime]::Parse($_.createdAt).ToString('M/d/yyyy h:mm:ss tt') | |
| 'CreatedAt' = [DateTime]::Parse($_.createdAt).ToString('M/d/yyyy h:mm:ss tt') |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -13,6 +13,8 @@ Like many other tools, this module targets `net8.0` so always run it in PowerShe | |||||
| - [Connect azure-powershell and azure-powershell-common](#connect-azure-powershell-and-azure-powershell-common) | ||||||
| - [Autorest helper](#autorest-helper) | ||||||
| - [Open swagger online](#open-swagger-online) | ||||||
| - [GitHub Helpers](#github-helpers) | ||||||
| - [Merge PRs](#merge-prs) | ||||||
| - [Development](#development) | ||||||
| - [Design](#design) | ||||||
| - [Testing](#testing) | ||||||
|
|
@@ -116,6 +118,37 @@ Enter the number corresponding to your selection | |||||
| Opening https://github.com/Azure/azure-rest-api-specs/blob/202321f386ea5b0c103b46902d43b3d3c50e029c/specification/workloads/resource-manager/Microsoft.Workloads/SAPVirtualInstance/readme.md in default browser... | ||||||
| ``` | ||||||
|
|
||||||
| ### GitHub Helpers | ||||||
|
|
||||||
| Prerequisite: You need to install [GitHub CLI](https://cli.github.com/) and set up GitHub authentication first with `gh auth login`. | ||||||
|
|
||||||
| #### Merge PRs | ||||||
|
|
||||||
| `Merge-DevPullRequest` (alias: `Merge-DevPR`) helps you merge pull requests in the azure-powershell repo. It supports two parameter sets: merging a specific PR by number, and merging all archive PRs. | ||||||
|
|
||||||
| With the `-AllArchivePR` switch, the cmdlet lists all the matching PRs, ordered by CreatedAt ascending, and prompts you to confirm before merging. Use the `-Force` switch to skip the confirmation. For safety, this parameter set only supports merging PRs with the "[skip ci]" prefix in the title and created by the `azure-powershell-bot` user, which are the archive PRs for generated modules. | ||||||
|
|
||||||
| The cmdlet returns the list of merged PRs. In case any PR fails to merge, an error is thrown, and the successfully merged PRs are still returned. | ||||||
|
||||||
| The cmdlet returns the list of merged PRs. In case any PR fails to merge, an error is thrown, and the successfully merged PRs are still returned. | |
| The cmdlet returns the list of merged PRs. If any PR fails to merge, an error is thrown and no results are returned. |
Uh oh!
There was an error while loading. Please reload this page.