@@ -109,45 +109,6 @@ function Select-PullRequestForPush {
109109 Select-Object - First 1
110110}
111111
112- function Test-ShouldResolveAssociatedPullRequest {
113- <#
114- . SYNOPSIS
115- Decides whether a commit's associated pull request must be resolved from the GitHub API.
116-
117- . DESCRIPTION
118- A push to any branch resolves its associated pull request so a default-branch release
119- honours the merged pull request's version label. A manual dispatch on the default branch is
120- the documented recovery route for a failed or cancelled release run and targets the same
121- merge commit, so it must resolve the same pull request. Excluding it left the pull request
122- null and silently downgraded a labelled Major or Minor release to a Patch bump.
123-
124- . OUTPUTS
125- Boolean. True when the association lookup must run.
126-
127- . EXAMPLE
128- Test-ShouldResolveAssociatedPullRequest -IsPush $false -IsManualDispatchToDefaultBranch $true -CommitSha 'abc123'
129-
130- Returns $true, because a default-branch dispatch releases the same commit a push would.
131- #>
132- [CmdletBinding ()]
133- [OutputType ([bool ])]
134- param (
135- # Whether the workflow was triggered by a push event.
136- [Parameter ()]
137- [bool ] $IsPush ,
138-
139- # Whether the workflow was manually dispatched against the default branch.
140- [Parameter ()]
141- [bool ] $IsManualDispatchToDefaultBranch ,
142-
143- # The commit the workflow is resolving a release for.
144- [Parameter ()]
145- [string ] $CommitSha
146- )
147-
148- ($IsPush -or $IsManualDispatchToDefaultBranch ) -and -not [string ]::IsNullOrWhiteSpace($CommitSha )
149- }
150-
151112function Get-DiscardedReleasePullRequest {
152113 <#
153114 . SYNOPSIS
@@ -206,6 +167,112 @@ function Get-DiscardedReleasePullRequest {
206167 }
207168}
208169
170+ function Resolve-ReleasePullRequest {
171+ <#
172+ . SYNOPSIS
173+ Resolves the pull request whose version label drives the release for a commit.
174+
175+ . DESCRIPTION
176+ A push resolves the pull request associated with the pushed commit so a default-branch
177+ release honours the merged pull request's version label. A manual dispatch on the default
178+ branch is the documented recovery route for a failed or cancelled release run and targets
179+ the same merge commit, so it must resolve the same pull request. Excluding it left the pull
180+ request unresolved, and the version silently fell back to a patch bump through AutoPatching.
181+
182+ When no pull request is selected, the outcome depends on why. A commit pushed directly to
183+ the default branch has no label to honour, so the release proceeds with the default patch
184+ bump. A commit associated with a merged default-branch pull request that does not match it
185+ does carry a label, and applying a patch bump would publish a version nobody asked for. A
186+ PowerShell Gallery version cannot be reclaimed, so that case throws instead.
187+
188+ . OUTPUTS
189+ PSCustomObject with Resolved, indicating whether the lookup ran, and PullRequest, which is
190+ null when the commit has no associated release pull request.
191+
192+ . EXAMPLE
193+ Resolve-ReleasePullRequest -EventName workflow_dispatch -CommitSha $sha -DefaultBranch main `
194+ -IsManualDispatchToDefaultBranch $true -GetAssociatedPullRequest { param($Sha) $pulls }
195+
196+ Resolves the merged pull request for a recovery dispatch so its version label is honoured.
197+ #>
198+ [Diagnostics.CodeAnalysis.SuppressMessageAttribute (' PSReviewUnusedParameter' , ' ' ,
199+ Justification = ' Parameters are used inside a LogGroup script block.' )]
200+ [CmdletBinding ()]
201+ [OutputType ([PSCustomObject ])]
202+ param (
203+ # The name of the GitHub event that triggered the workflow.
204+ [Parameter (Mandatory )]
205+ [string ] $EventName ,
206+
207+ # The commit the workflow is resolving a release for.
208+ [Parameter ()]
209+ [AllowEmptyString ()]
210+ [AllowNull ()]
211+ [string ] $CommitSha ,
212+
213+ # The repository default branch a release must target.
214+ [Parameter (Mandatory )]
215+ [string ] $DefaultBranch ,
216+
217+ # Whether the workflow was triggered by a push to the default branch.
218+ [Parameter ()]
219+ [bool ] $IsPushToDefaultBranch ,
220+
221+ # Whether the workflow was manually dispatched against the default branch.
222+ [Parameter ()]
223+ [bool ] $IsManualDispatchToDefaultBranch ,
224+
225+ # Returns the pull requests GitHub associates with a commit. Takes the commit SHA.
226+ [Parameter (Mandatory )]
227+ [scriptblock ] $GetAssociatedPullRequest
228+ )
229+
230+ $isPush = $EventName -eq ' push'
231+ $shouldResolve = (
232+ ($isPush -or $IsManualDispatchToDefaultBranch ) -and
233+ -not [string ]::IsNullOrWhiteSpace($CommitSha )
234+ )
235+ if (-not $shouldResolve ) {
236+ return [pscustomobject ]@ { Resolved = $false ; PullRequest = $null }
237+ }
238+
239+ LogGroup " Resolve pull request for commit [$CommitSha ]" {
240+ $associated = @ ((& $GetAssociatedPullRequest $CommitSha ) | Where-Object { $null -ne $_ })
241+ $pullRequest = Select-PullRequestForPush - PullRequest $associated `
242+ - DefaultBranch $DefaultBranch `
243+ - CommitSha $CommitSha
244+
245+ if ($pullRequest ) {
246+ Write-Host " Resolved pull request #$ ( $pullRequest.Number ) from commit [$CommitSha ]."
247+ return [pscustomobject ]@ { Resolved = $true ; PullRequest = $pullRequest }
248+ }
249+
250+ # Only a release-bearing event can publish a wrong version. A push to a feature branch has
251+ # no release to get wrong, and its commit is legitimately claimed by an open pull request.
252+ $isReleaseEvent = $IsPushToDefaultBranch -or $IsManualDispatchToDefaultBranch
253+ $discarded = if ($isReleaseEvent ) {
254+ @ (Get-DiscardedReleasePullRequest - PullRequest $associated `
255+ - DefaultBranch $DefaultBranch `
256+ - CommitSha $CommitSha )
257+ } else {
258+ @ ()
259+ }
260+ if ($discarded.Count -gt 0 ) {
261+ throw (
262+ " Commit [$CommitSha ] cannot be released because its version label cannot be determined. " +
263+ ' The following merged pull request(s) are associated with it but none matches the commit ' +
264+ " being released: $ ( $discarded -join ' ; ' ) . " +
265+ ' Refusing to fall back to a patch bump, because a wrong version published to the ' +
266+ ' PowerShell Gallery cannot be reclaimed. Re-run the workflow against the merge commit ' +
267+ ' of the pull request you intend to release.'
268+ )
269+ }
270+
271+ Write-Host " ::notice::No pull request is associated with commit [$CommitSha ]."
272+ [pscustomobject ]@ { Resolved = $true ; PullRequest = $null }
273+ }
274+ }
275+
209276function Get-FilesFromGitTree {
210277 <#
211278 . SYNOPSIS
0 commit comments