Skip to content

Commit b5ebe12

Browse files
🧪 [Test]: Cover push and PR release routing
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
1 parent b3efa04 commit b5ebe12

4 files changed

Lines changed: 241 additions & 39 deletions

File tree

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
function Resolve-WorkflowEventRouting {
2+
<#
3+
.SYNOPSIS
4+
Resolves release and execution routing from normalized GitHub event state.
5+
#>
6+
[CmdletBinding()]
7+
[OutputType([PSCustomObject])]
8+
param(
9+
[Parameter(Mandatory)]
10+
[string] $EventName,
11+
12+
[Parameter()]
13+
[string] $EventAction,
14+
15+
[Parameter()]
16+
[bool] $PullRequestIsMerged,
17+
18+
[Parameter()]
19+
[bool] $IsTargetDefaultBranch,
20+
21+
[Parameter()]
22+
[bool] $IsPushToDefaultBranch,
23+
24+
[Parameter()]
25+
[bool] $HasPullRequestContext,
26+
27+
[Parameter()]
28+
[bool] $HasImportantChanges,
29+
30+
[Parameter()]
31+
[bool] $HasPrereleaseLabel,
32+
33+
[Parameter()]
34+
[bool] $AllowDirectPushRelease
35+
)
36+
37+
$isPR = $EventName -eq 'pull_request'
38+
$isPush = $EventName -eq 'push'
39+
$isOpenOrUpdatedPR = $isPR -and $EventAction -in @('opened', 'reopened', 'synchronize', 'labeled', 'unlabeled')
40+
$isOpenOrLabeledPR = $isPR -and $EventAction -in @('opened', 'reopened', 'synchronize', 'labeled')
41+
$isClosedPR = $isPR -and $EventAction -eq 'closed'
42+
$isAbandonedPR = $isClosedPR -and -not $PullRequestIsMerged
43+
$isMergedPR = $isClosedPR -and $PullRequestIsMerged
44+
$shouldPrerelease = $isOpenOrLabeledPR -and $HasPrereleaseLabel -and $HasImportantChanges
45+
46+
$releaseType = if (
47+
$IsPushToDefaultBranch -and
48+
$HasImportantChanges -and
49+
($HasPullRequestContext -or $AllowDirectPushRelease)
50+
) {
51+
'Release'
52+
} elseif ($shouldPrerelease) {
53+
'Prerelease'
54+
} else {
55+
'None'
56+
}
57+
58+
[pscustomobject]@{
59+
IsPR = $isPR
60+
IsPush = $isPush
61+
IsOpenOrUpdatedPR = $isOpenOrUpdatedPR
62+
IsOpenOrLabeledPR = $isOpenOrLabeledPR
63+
IsClosedPR = $isClosedPR
64+
IsAbandonedPR = $isAbandonedPR
65+
IsMergedPR = $isMergedPR
66+
IsTargetDefaultBranch = $IsTargetDefaultBranch
67+
IsPushToDefaultBranch = $IsPushToDefaultBranch
68+
ShouldPrerelease = $shouldPrerelease
69+
ReleaseType = $releaseType
70+
ShouldRunBuildTest = (-not $isClosedPR) -and $HasImportantChanges
71+
ShouldCleanupEvent = (
72+
($releaseType -eq 'Release') -or
73+
$isClosedPR -or
74+
($IsPushToDefaultBranch -and $HasPullRequestContext)
75+
)
76+
}
77+
}

.github/actions/Get-PSModuleSettings/src/main.ps1

Lines changed: 25 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
'powershell-yaml', 'Hashtable' | Install-PSResource -Repository PSGallery -TrustRepository
2+
Import-Module -Name "$PSScriptRoot/Get-PSModuleSettings.Helpers.psm1" -Force
23

34
$name = $env:PSMODULE_GET_SETTINGS_INPUT_Name
45
$settingsPath = $env:PSMODULE_GET_SETTINGS_INPUT_SettingsPath
@@ -300,21 +301,17 @@ LogGroup 'Calculate Job Run Conditions:' {
300301
TargetBranch = $targetBranch
301302
DefaultBranch = $defaultBranch
302303
IsTargetDefaultBranch = $isTargetDefaultBranch
303-
IsPushToDefaultBranch = $isPushToDefaultBranch
304-
AssociatedPullRequest = $pullRequestContext.Number
304+
IsPushToDefaultBranch = $isPushToDefaultBranch
305+
AssociatedPullRequest = $pullRequestContext.Number
305306
} | Format-List | Out-String
306307

307308
$isOpenOrUpdatedPR = $isPR -and $pullRequestAction -in @('opened', 'reopened', 'synchronize', 'labeled', 'unlabeled')
308-
$isClosedPR = $isPR -and $pullRequestAction -eq 'closed'
309-
$isAbandonedPR = $isPR -and $pullRequestAction -eq 'closed' -and $pullRequestIsMerged -ne $true
310-
$isMergedPR = $isPR -and $pullRequestAction -eq 'closed' -and $pullRequestIsMerged -eq $true
311309
$hasPullRequestContext = $null -ne $pullRequestContext
312310

313311
# Check if a prerelease label exists on the PR
314312
$prereleaseLabels = $settings.Publish.Module.PrereleaseLabels -split ',' | ForEach-Object { $_.Trim() }
315313
$prLabels = @($pullRequestContext.Labels)
316314
$hasPrereleaseLabel = ($prLabels | Where-Object { $prereleaseLabels -contains $_ }).Count -gt 0
317-
$isOpenOrLabeledPR = $isPR -and $pullRequestAction -in @('opened', 'reopened', 'synchronize', 'labeled')
318315

319316
# Check if important files have changed in the PR
320317
# Important files are determined by the configured ImportantFilePatterns setting
@@ -406,35 +403,28 @@ If you believe this is incorrect, please verify that your changes are in the cor
406403
Write-Host 'Non-PR event - treating as having important changes'
407404
}
408405

409-
# Prerelease requires both: prerelease label AND important file changes
410-
# No point creating a prerelease if only non-module files changed
411-
$shouldPrerelease = $isOpenOrLabeledPR -and $hasPrereleaseLabel -and $hasImportantChanges
412-
413-
# Determine ReleaseType - what type of release to create
414-
# Values: 'Release', 'Prerelease', 'None'
415-
# Stable releases are push-driven. A direct push requires explicit opt-in.
416-
$releaseType = if (
417-
$isPushToDefaultBranch -and
418-
$hasImportantChanges -and
419-
($hasPullRequestContext -or $settings.Publish.Module.AllowDirectPushRelease)
420-
) {
421-
'Release'
422-
} elseif ($shouldPrerelease) {
423-
'Prerelease'
424-
} else {
425-
'None'
426-
}
406+
$routing = Resolve-WorkflowEventRouting -EventName $eventName `
407+
-EventAction $pullRequestAction `
408+
-PullRequestIsMerged $pullRequestIsMerged `
409+
-IsTargetDefaultBranch $isTargetDefaultBranch `
410+
-IsPushToDefaultBranch $isPushToDefaultBranch `
411+
-HasPullRequestContext $hasPullRequestContext `
412+
-HasImportantChanges $hasImportantChanges `
413+
-HasPrereleaseLabel $hasPrereleaseLabel `
414+
-AllowDirectPushRelease $settings.Publish.Module.AllowDirectPushRelease
415+
$shouldPrerelease = $routing.ShouldPrerelease
416+
$releaseType = $routing.ReleaseType
427417

428418
[pscustomobject]@{
429-
isPR = $isPR
430-
isOpenOrUpdatedPR = $isOpenOrUpdatedPR
431-
isOpenOrLabeledPR = $isOpenOrLabeledPR
432-
isClosedPR = $isClosedPR
433-
isAbandonedPR = $isAbandonedPR
434-
isMergedPR = $isMergedPR
435-
isPush = $isPush
436-
isPushToDefaultBranch = $isPushToDefaultBranch
437-
isTargetDefaultBranch = $isTargetDefaultBranch
419+
isPR = $routing.IsPR
420+
isOpenOrUpdatedPR = $routing.IsOpenOrUpdatedPR
421+
isOpenOrLabeledPR = $routing.IsOpenOrLabeledPR
422+
isClosedPR = $routing.IsClosedPR
423+
isAbandonedPR = $routing.IsAbandonedPR
424+
isMergedPR = $routing.IsMergedPR
425+
isPush = $routing.IsPush
426+
isPushToDefaultBranch = $routing.IsPushToDefaultBranch
427+
isTargetDefaultBranch = $routing.IsTargetDefaultBranch
438428
hasPullRequestContext = $hasPullRequestContext
439429
hasPrereleaseLabel = $hasPrereleaseLabel
440430
shouldPrerelease = $shouldPrerelease
@@ -607,11 +597,7 @@ $settings.Test.Module | Add-Member -MemberType NoteProperty -Name Suites -Value
607597
LogGroup 'Calculate Job Run Conditions:' {
608598
# Calculate if prereleases should be cleaned up:
609599
# Closed PRs only clean up prereleases. Push runs also clean up the associated PR channel.
610-
$shouldCleanupEvent = (
611-
($releaseType -eq 'Release') -or
612-
$isClosedPR -or
613-
($isPushToDefaultBranch -and $hasPullRequestContext)
614-
)
600+
$shouldCleanupEvent = $routing.ShouldCleanupEvent
615601
$shouldAutoCleanup = $shouldCleanupEvent -and ($settings.Publish.Module.AutoCleanup -eq $true)
616602

617603
# Update Publish.Module with computed release values
@@ -621,7 +607,7 @@ LogGroup 'Calculate Job Run Conditions:' {
621607
# For open PRs, we only want to run build/test stages if important files changed.
622608
# Closed PR events are cleanup-only. workflow_dispatch and schedule retain build/test behavior.
623609
# Note: $shouldPrerelease already requires $hasImportantChanges, so no separate check needed.
624-
$shouldRunBuildTest = (-not $isClosedPR) -and $hasImportantChanges
610+
$shouldRunBuildTest = $routing.ShouldRunBuildTest
625611

626612
# Check if setup/teardown scripts exist in the repository
627613
$hasBeforeAllScript = Test-Path -Path 'tests/BeforeAll.ps1'
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
BeforeAll {
2+
Import-Module "$PSScriptRoot/../src/Get-PSModuleSettings.Helpers.psm1" -Force
3+
}
4+
5+
Describe 'Resolve-WorkflowEventRouting' {
6+
It 'routes an associated push to the default branch to a stable release' {
7+
$result = Resolve-WorkflowEventRouting -EventName push `
8+
-IsTargetDefaultBranch $true `
9+
-IsPushToDefaultBranch $true `
10+
-HasPullRequestContext $true `
11+
-HasImportantChanges $true
12+
13+
$result.ReleaseType | Should -Be 'Release'
14+
$result.ShouldRunBuildTest | Should -BeTrue
15+
$result.ShouldCleanupEvent | Should -BeTrue
16+
}
17+
18+
It 'does not publish an unassociated direct push by default' {
19+
$result = Resolve-WorkflowEventRouting -EventName push `
20+
-IsTargetDefaultBranch $true `
21+
-IsPushToDefaultBranch $true `
22+
-HasImportantChanges $true
23+
24+
$result.ReleaseType | Should -Be 'None'
25+
}
26+
27+
It 'allows an explicitly enabled direct push release' {
28+
$result = Resolve-WorkflowEventRouting -EventName push `
29+
-IsTargetDefaultBranch $true `
30+
-IsPushToDefaultBranch $true `
31+
-HasImportantChanges $true `
32+
-AllowDirectPushRelease $true
33+
34+
$result.ReleaseType | Should -Be 'Release'
35+
}
36+
37+
It 'routes a labeled open PR with important changes to a prerelease' {
38+
$result = Resolve-WorkflowEventRouting -EventName pull_request `
39+
-EventAction labeled `
40+
-IsTargetDefaultBranch $true `
41+
-HasPullRequestContext $true `
42+
-HasImportantChanges $true `
43+
-HasPrereleaseLabel $true
44+
45+
$result.ReleaseType | Should -Be 'Prerelease'
46+
$result.ShouldRunBuildTest | Should -BeTrue
47+
}
48+
49+
It 'routes an abandoned PR to cleanup only' {
50+
$result = Resolve-WorkflowEventRouting -EventName pull_request `
51+
-EventAction closed `
52+
-IsTargetDefaultBranch $true `
53+
-HasPullRequestContext $true `
54+
-HasImportantChanges $true
55+
56+
$result.ReleaseType | Should -Be 'None'
57+
$result.IsAbandonedPR | Should -BeTrue
58+
$result.ShouldRunBuildTest | Should -BeFalse
59+
$result.ShouldCleanupEvent | Should -BeTrue
60+
}
61+
62+
It 'routes a merged PR event to cleanup only' {
63+
$result = Resolve-WorkflowEventRouting -EventName pull_request `
64+
-EventAction closed `
65+
-PullRequestIsMerged $true `
66+
-IsTargetDefaultBranch $true `
67+
-HasPullRequestContext $true `
68+
-HasImportantChanges $true
69+
70+
$result.ReleaseType | Should -Be 'None'
71+
$result.IsMergedPR | Should -BeTrue
72+
$result.ShouldRunBuildTest | Should -BeFalse
73+
$result.ShouldCleanupEvent | Should -BeTrue
74+
}
75+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
BeforeAll {
2+
function global:LogGroup {
3+
<#
4+
.SYNOPSIS
5+
Executes a test script block without GitHub Actions log grouping.
6+
#>
7+
param(
8+
[Parameter(Position = 0)]
9+
[string] $Name,
10+
11+
[Parameter(Position = 1)]
12+
[scriptblock] $ScriptBlock
13+
)
14+
15+
$null = $Name
16+
& $ScriptBlock
17+
}
18+
19+
Import-Module "$PSScriptRoot/../src/Resolve-PSModuleVersion.Helpers.psm1" -Force
20+
}
21+
22+
AfterAll {
23+
Remove-Item Function:/LogGroup -ErrorAction SilentlyContinue
24+
}
25+
26+
Describe 'Get-GitHubPullRequest' {
27+
It 'reads push-derived pull request context from settings' {
28+
$settings = @{
29+
Context = @{
30+
IsPushToDefaultBranch = $true
31+
DefaultBranch = 'main'
32+
PullRequest = @{
33+
Number = 390
34+
HeadRef = 'feature/push-release'
35+
Labels = @('minor', 'prerelease')
36+
}
37+
}
38+
Publish = @{ Module = @{ ReleaseType = 'Release' } }
39+
} | ConvertTo-Json -Depth 5
40+
41+
$result = Get-GitHubPullRequest -SettingsJson $settings
42+
43+
$result.Number | Should -Be 390
44+
$result.HeadRef | Should -Be 'feature/push-release'
45+
$result.Labels | Should -Be @('minor', 'prerelease')
46+
}
47+
48+
It 'creates release context for an explicitly enabled direct push' {
49+
$settings = @{
50+
Context = @{
51+
IsPushToDefaultBranch = $true
52+
DefaultBranch = 'main'
53+
PullRequest = $null
54+
}
55+
Publish = @{ Module = @{ ReleaseType = 'Release' } }
56+
} | ConvertTo-Json -Depth 5
57+
58+
$result = Get-GitHubPullRequest -SettingsJson $settings
59+
60+
$result.Number | Should -BeNullOrEmpty
61+
$result.HeadRef | Should -Be 'main'
62+
$result.Labels | Should -BeNullOrEmpty
63+
}
64+
}

0 commit comments

Comments
 (0)