Private/Find-AvmOpenPullRequests.ps1
|
function Find-AvmOpenPullRequests { <# .SYNOPSIS Lists open pull requests whose source/head branch starts with the given prefix. .DESCRIPTION Used to make PR creation idempotent: the caller matches the deterministic branch name for the current update set against this list to find a PR to refresh in place, and treats any other open PR under the same prefix as stale (same prefix, different content hash) to warn about instead of silently leaving duplicates behind. .PARAMETER ApprovalMode 'github' or 'azuredevops'. .PARAMETER BranchPrefix Prefix shared by all AvmUpdater branches (e.g. 'avm-updates'). .PARAMETER AzureDevOpsConfig Optional hashtable with organization/project/repository overrides, passed through to 'az repos pr list' when set. .OUTPUTS Array of PSCustomObject with: number, url, branchName. Empty array if the relevant CLI is missing or the list operation fails (treated as "no known open PRs" rather than a terminating error, since this is best-effort discovery). #> [CmdletBinding()] [OutputType([PSCustomObject[]])] param( [Parameter(Mandatory)] [ValidateSet('github', 'azuredevops')] [string]$ApprovalMode, [Parameter(Mandatory)] [string]$BranchPrefix, [Parameter()] [hashtable]$AzureDevOpsConfig ) $results = [System.Collections.Generic.List[PSCustomObject]]::new() switch ($ApprovalMode) { 'github' { if (-not (Get-Command gh -ErrorAction SilentlyContinue)) { return $results.ToArray() } $raw = gh pr list --state open --json number,url,headRefName --limit 200 2>&1 if ($LASTEXITCODE -ne 0) { Write-Verbose "gh pr list failed: $($raw -join ' ')" return $results.ToArray() } $parsed = @($raw | ConvertFrom-Json -ErrorAction SilentlyContinue) foreach ($pr in $parsed) { if ($pr.headRefName -like "$BranchPrefix/*") { $results.Add([PSCustomObject]@{ number = $pr.number; url = $pr.url; branchName = $pr.headRefName }) } } } 'azuredevops' { if (-not (Get-Command az -ErrorAction SilentlyContinue)) { return $results.ToArray() } $argsList = @('repos', 'pr', 'list', '--status', 'active', '-o', 'json') if ($AzureDevOpsConfig) { if ($AzureDevOpsConfig.organization) { $argsList += @('--organization', $AzureDevOpsConfig.organization) } if ($AzureDevOpsConfig.project) { $argsList += @('--project', $AzureDevOpsConfig.project) } if ($AzureDevOpsConfig.repository) { $argsList += @('--repository', $AzureDevOpsConfig.repository) } } $raw = & az @argsList 2>&1 if ($LASTEXITCODE -ne 0) { Write-Verbose "az repos pr list failed: $($raw -join ' ')" return $results.ToArray() } $parsed = @($raw | ConvertFrom-Json -ErrorAction SilentlyContinue) foreach ($pr in $parsed) { $branchName = $pr.sourceRefName -replace '^refs/heads/', '' if ($branchName -like "$BranchPrefix/*") { $url = if ($pr.PSObject.Properties['url']) { $pr.url } else { $null } $results.Add([PSCustomObject]@{ number = $pr.pullRequestId; url = $url; branchName = $branchName }) } } } } return $results.ToArray() } |