Skip to content

Commit 2646335

Browse files
Guard dispatch association through composed version tests
1 parent 189d3eb commit 2646335

2 files changed

Lines changed: 124 additions & 37 deletions

File tree

‎.github/actions/Get-PSModuleSettings/tests/Get-PSModuleSettings.Helpers.Tests.ps1‎

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,58 @@ Describe 'Resolve-ReleasePullRequest' {
278278
$result.Resolved | Should -BeTrue
279279
$result.PullRequest | Should -BeNullOrEmpty
280280
}
281+
282+
It 'rejects an unmatched merged pull request for a default-branch push' {
283+
$otherMerge = [pscustomobject]@{
284+
Number = 412
285+
Base = [pscustomobject]@{ Ref = 'main' }
286+
merged_at = '2026-09-01T00:00:00Z'
287+
merge_commit_sha = 'merge-of-412'
288+
}
289+
$parameters = @{
290+
EventName = 'push'
291+
CommitSha = 'released-sha'
292+
DefaultBranch = 'main'
293+
IsPushToDefaultBranch = $true
294+
GetAssociatedPullRequest = { @($otherMerge) }.GetNewClosure()
295+
}
296+
297+
{ Resolve-ReleasePullRequest @parameters } | Should -Throw '*#412*merge-of-412*cannot be reclaimed*'
298+
}
299+
300+
It 'uses the exact merge match when unrelated merged pull requests also claim the commit' {
301+
$otherMerge = [pscustomobject]@{
302+
Number = 412
303+
Base = [pscustomobject]@{ Ref = 'main' }
304+
merged_at = '2026-09-03T00:00:00Z'
305+
merge_commit_sha = 'merge-of-412'
306+
}
307+
$matchingPullRequest = $script:mergedPullRequest
308+
$parameters = @{
309+
EventName = 'workflow_dispatch'
310+
CommitSha = 'released-sha'
311+
DefaultBranch = 'main'
312+
IsManualDispatchToDefaultBranch = $true
313+
GetAssociatedPullRequest = { @($otherMerge, $matchingPullRequest) }.GetNewClosure()
314+
}
315+
316+
$result = Resolve-ReleasePullRequest @parameters
317+
318+
$result.PullRequest.Number | Should -Be 64
319+
$result.PullRequest.Labels.Name | Should -Be @('minor')
320+
}
321+
322+
It 'propagates an association lookup failure instead of treating it as a direct release' {
323+
$parameters = @{
324+
EventName = 'workflow_dispatch'
325+
CommitSha = 'released-sha'
326+
DefaultBranch = 'main'
327+
IsManualDispatchToDefaultBranch = $true
328+
GetAssociatedPullRequest = { throw 'Commit association lookup failed.' }
329+
}
330+
331+
{ Resolve-ReleasePullRequest @parameters } | Should -Throw '*Commit association lookup failed*'
332+
}
281333
}
282334

283335
Describe 'Get-DiscardedReleasePullRequest' {

‎.github/actions/Resolve-PSModuleVersion/tests/Resolve-PSModuleVersion.Helpers.Tests.ps1‎

Lines changed: 72 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,16 @@
22
'PSUseDeclaredVarsMoreThanAssignments', '',
33
Justification = 'Variables are assigned in BeforeAll and used inside It blocks.'
44
)]
5+
[Diagnostics.CodeAnalysis.SuppressMessageAttribute(
6+
'PSAvoidUsingCmdletAliases', 'Context',
7+
Justification = 'Context is a Pester test block, not an implicit call to Get-Context.'
8+
)]
59
[CmdletBinding()]
610
param()
711

812
BeforeAll {
913
Import-Module -Name 'PSModule' -Force
14+
Import-Module -Name (Join-Path -Path $PSScriptRoot -ChildPath '../../Get-PSModuleSettings/src/Get-PSModuleSettings.Helpers.psm1') -Force
1015
Import-Module -Name (Join-Path -Path $PSScriptRoot -ChildPath '../src/Resolve-PSModuleVersion.Helpers.psm1') -Force
1116

1217
function Get-TestConfiguration {
@@ -574,45 +579,75 @@ Describe 'Resolve-PSModuleVersion' {
574579
$result.PatchRelease | Should -BeTrue
575580
}
576581

577-
It 'resolves the labeled minor version once a recovery dispatch supplies pull request context' {
578-
# End-to-end guard for issue #530, using the reproduction numbers from
579-
# MariusStorhaug/MariusTestModule: latest release v0.4.13 and merged pull request #64
580-
# labeled 'minor', so the correct release is 0.5.0. This asserts the version consequence
581-
# of the two possible contexts a default-branch dispatch can produce. Get-PSModuleSettings
582-
# decides which one it is; that decision is guarded by
583-
# Test-ShouldResolveAssociatedPullRequest in the settings action tests.
584-
$configuration = Get-TestConfiguration
585-
$versionFor = {
586-
param($SettingsJson)
587-
$pullRequest = Get-GitHubPullRequest -SettingsJson $SettingsJson
588-
$decision = Resolve-ReleaseDecision -Configuration $configuration -PullRequest $pullRequest
589-
$resolved = Get-ResolvedModuleVersion -GitHubVersion ([PSSemVer]'0.4.13') `
590-
-PSGalleryVersion ([PSSemVer]'0.4.13') `
591-
-Decision $decision `
592-
-Configuration $configuration `
593-
-ModuleName 'MariusTestModule'
594-
$resolved.ToString()
595-
}
596-
597-
$dispatchContext = @{
598-
IsPushToDefaultBranch = $false
599-
IsManualDispatchToDefaultBranch = $true
582+
It 'resolves <ExpectedVersion> for a <EventName> with <Label> release intent' -ForEach @(
583+
@{ EventName = 'workflow_dispatch'; Label = 'major'; ExpectedVersion = 'v1.0.0' }
584+
@{ EventName = 'workflow_dispatch'; Label = 'minor'; ExpectedVersion = 'v0.5.0' }
585+
@{ EventName = 'workflow_dispatch'; Label = 'patch'; ExpectedVersion = 'v0.4.14' }
586+
@{ EventName = 'workflow_dispatch'; Label = ''; ExpectedVersion = 'v0.4.14' }
587+
@{ EventName = 'push'; Label = 'major'; ExpectedVersion = 'v1.0.0' }
588+
@{ EventName = 'push'; Label = 'minor'; ExpectedVersion = 'v0.5.0' }
589+
@{ EventName = 'push'; Label = 'patch'; ExpectedVersion = 'v0.4.14' }
590+
@{ EventName = 'push'; Label = ''; ExpectedVersion = 'v0.4.14' }
591+
) {
592+
$associatedPullRequests = if ($Label) {
593+
@([pscustomobject]@{
594+
Number = 64
595+
Base = [pscustomobject]@{ Ref = 'main' }
596+
Head = [pscustomobject]@{ Ref = 'feature/recovered-release' }
597+
merged_at = '2026-09-02T09:02:24Z'
598+
merge_commit_sha = 'released-sha'
599+
Labels = @([pscustomobject]@{ Name = $Label })
600+
})
601+
} else {
602+
@()
603+
}
604+
$parameters = @{
605+
EventName = $EventName
606+
CommitSha = 'released-sha'
600607
DefaultBranch = 'main'
608+
IsPushToDefaultBranch = $EventName -eq 'push'
609+
IsManualDispatchToDefaultBranch = $EventName -eq 'workflow_dispatch'
610+
GetAssociatedPullRequest = { $associatedPullRequests }.GetNewClosure()
611+
}
612+
$resolution = Resolve-ReleasePullRequest @parameters
613+
$resolvedPullRequest = $resolution.PullRequest
614+
$normalizedPullRequest = if ($resolvedPullRequest) {
615+
@{
616+
Number = $resolvedPullRequest.Number
617+
HeadRef = $resolvedPullRequest.Head.Ref
618+
Labels = @($resolvedPullRequest.Labels.Name)
619+
}
620+
} else {
621+
$null
622+
}
623+
$settingsJson = @{
624+
Context = @{
625+
IsPushToDefaultBranch = $parameters.IsPushToDefaultBranch
626+
IsManualDispatchToDefaultBranch = $parameters.IsManualDispatchToDefaultBranch
627+
DefaultBranch = 'main'
628+
PullRequest = $normalizedPullRequest
629+
}
630+
} | ConvertTo-Json -Depth 5
631+
$configuration = Get-TestConfiguration
632+
$pullRequest = Get-GitHubPullRequest -SettingsJson $settingsJson
633+
$decision = Resolve-ReleaseDecision -Configuration $configuration -PullRequest $pullRequest
634+
$versionParameters = @{
635+
GitHubVersion = New-PSSemVer -Version '0.4.13'
636+
PSGalleryVersion = New-PSSemVer -Version '0.4.13'
637+
Decision = $decision
638+
Configuration = $configuration
639+
ModuleName = 'DispatchTestModule'
640+
}
641+
$resolvedVersion = Get-ResolvedModuleVersion @versionParameters
642+
643+
$resolution.Resolved | Should -BeTrue
644+
$decision.ShouldPublish | Should -BeTrue
645+
$resolvedVersion.ToString() | Should -Be $ExpectedVersion
646+
if ($Label) {
647+
$pullRequest.Number | Should -Be 64
648+
} else {
649+
$pullRequest.IsDirectRelease | Should -BeTrue
601650
}
602-
603-
$withoutPullRequest = & $versionFor (@{
604-
Context = $dispatchContext + @{ PullRequest = $null }
605-
} | ConvertTo-Json -Depth 5)
606-
$withPullRequest = & $versionFor (@{
607-
Context = $dispatchContext + @{
608-
PullRequest = @{ Number = 64; HeadRef = 'feature/recovered-release'; Labels = @('minor') }
609-
}
610-
} | ConvertTo-Json -Depth 5)
611-
612-
# The silent downgrade the defect produced.
613-
$withoutPullRequest | Should -Be 'v0.4.14'
614-
# The version the merged pull request's label asks for.
615-
$withPullRequest | Should -Be 'v0.5.0'
616651
}
617652

618653
It 'does not publish an unlabeled prerelease when AutoPatching is disabled' {

0 commit comments

Comments
 (0)