Public/Approve-PSUGithubPullRequest.ps1
|
function Approve-PSUGithubPullRequest { <# .SYNOPSIS Approves a pull request in GitHub using REST API. .DESCRIPTION This function creates a review approval for a pull request in GitHub by its number. It supports different review states including approval, request changes, or comments only. .PARAMETER Owner (Optional) The GitHub repository owner (username or organization). Default value is auto-detected from git remote origin URL. .PARAMETER Repository (Optional) The GitHub repository name. Default value is auto-detected from git remote origin URL. .PARAMETER PullRequestNumber (Mandatory) The number/ID of the pull request to approve. .PARAMETER ReviewState (Optional) The review state to submit: - 'APPROVE': Approve the pull request - 'REQUEST_CHANGES': Request changes before approval - 'COMMENT': Comment without explicit approval Default value is 'APPROVE'. .PARAMETER Comment (Optional) Comment to add with the review. .PARAMETER Token (Optional) GitHub Personal Access Token for authentication. When omitted, the token is resolved by Get-PSUSecret -Name 'GITHUB_TOKEN', which prefers Windows Credential Manager, then SecretManagement, and finally the GITHUB_TOKEN environment variable. Store it securely with: Set-PSUCredentialToManager -Target "GITHUB_TOKEN" .EXAMPLE Approve-PSUGithubPullRequest -PullRequestNumber 42 Approves pull request #42 using auto-detected repository. .EXAMPLE Approve-PSUGithubPullRequest -Owner "myuser" -Repository "myrepo" -PullRequestNumber 42 -Comment "LGTM! Great work." Approves pull request #42 with a comment. .EXAMPLE Approve-PSUGithubPullRequest -PullRequestNumber 42 -ReviewState "REQUEST_CHANGES" -Comment "Please fix the unit tests" Requests changes on pull request #42 with a comment. .OUTPUTS [PSCustomObject] .NOTES Author: Lakshmanachari Panuganti Date: 19th August 2025 Requires: GitHub Personal Access Token with repo permissions .LINK https://github.com/lakshmanachari-panuganti/OMG.PSUtilities/tree/main/OMG.PSUtilities.Core https://www.linkedin.com/in/lakshmanachari-panuganti/ https://www.powershellgallery.com/packages/OMG.PSUtilities.Core https://docs.github.com/en/rest/pulls/reviews#create-a-review-for-a-pull-request #> [CmdletBinding()] [Diagnostics.CodeAnalysis.SuppressMessageAttribute( 'PSAvoidUsingWriteHost', '', Justification = 'This is intended for this function to display formatted output to the user on the console' )] param ( [Parameter()] [string]$Owner, [Parameter()] [string]$Repository, [Parameter(Mandatory)] [ValidateNotNullOrEmpty()] [int]$PullRequestNumber, [Parameter()] [ValidateSet('APPROVE', 'REQUEST_CHANGES', 'COMMENT')] [string]$ReviewState = 'APPROVE', [Parameter()] [string]$Comment, [Parameter()] [ValidateNotNullOrEmpty()] [string]$Token ) process { try { # Auto-detect repository info if not provided if (-not $Owner -or -not $Repository) { $remoteUrl = git remote get-url origin 2>$null if (-not $remoteUrl) { throw "No git remote origin found and Owner/Repository not specified." } if ($remoteUrl -match 'github\.com[/:]([^/]+)/([^/]+?)(?:\.git)?/?$') { if (-not $Owner) { $Owner = $matches[1] } if (-not $Repository) { $Repository = $matches[2] } } else { throw "Could not parse GitHub repository from remote URL: $remoteUrl. Please specify Owner and Repository parameters." } } # Resolve the token from secure storage when the caller did not supply one. # Get-PSUSecret prefers Windows Credential Manager, then SecretManagement, and # falls back to the GITHUB_TOKEN environment variable for compatibility. # Plaintext is requested here because it is needed for the Authorization header. if (-not $Token) { $Token = Get-PSUSecret -Name 'GITHUB_TOKEN' -AsPlainText } # Prepare headers $headers = @{ 'Authorization' = "Bearer $Token" 'Accept' = 'application/vnd.github.v3+json' 'X-GitHub-Api-Version' = '2022-11-28' } # Get PR details first to validate it exists $prUri = "https://api.github.com/repos/$Owner/$Repository/pulls/$PullRequestNumber" Write-Verbose "Getting pull request details from: $prUri" $prDetails = Invoke-RestMethod -Method Get -Uri $prUri -Headers $headers -ErrorAction Stop # Prepare review body $body = @{ event = $ReviewState } if ($Comment) { $body.body = $Comment } $bodyJson = $body | ConvertTo-Json -Depth 10 # Submit the review $reviewUri = "https://api.github.com/repos/$Owner/$Repository/pulls/$PullRequestNumber/reviews" Write-Verbose "Submitting review for pull request #$PullRequestNumber in repository: $Owner/$Repository" Write-Verbose "Review state: $ReviewState" Write-Verbose "API URI: $reviewUri" $response = Invoke-RestMethod -Method Post -Uri $reviewUri -Headers $headers -Body $bodyJson -ContentType "application/json" -ErrorAction Stop # Determine action text for display $actionText = switch ($ReviewState) { 'APPROVE' { 'approved' } 'REQUEST_CHANGES' { 'requested changes for' } 'COMMENT' { 'commented on' } default { 'reviewed' } } Write-Host "Successfully $actionText pull request #$PullRequestNumber" -ForegroundColor Green Write-Host "PR URL: $($prDetails.html_url)" -ForegroundColor Cyan Write-Host "Review URL: $($response.html_url)" -ForegroundColor Cyan if ($Comment) { Write-Host "Comment: $Comment" -ForegroundColor Yellow } # Return structured result [PSCustomObject]@{ PullRequestNumber = $PullRequestNumber ReviewId = $response.id ReviewState = $response.state ActionText = $actionText Comment = $Comment ReviewerLogin = $response.user.login SubmittedAt = $response.submitted_at Owner = $Owner Repository = $Repository PullRequestUrl = $prDetails.html_url ReviewUrl = $response.html_url PSTypeName = 'PSU.GitHub.PullRequestApproval' } } catch { $PSCmdlet.ThrowTerminatingError($_) } } } |