Skip to content

Commit a758ef4

Browse files
Resume Gallery-only stable publications
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
1 parent 4de61e0 commit a758ef4

5 files changed

Lines changed: 211 additions & 7 deletions

File tree

.github/actions/Publish-PSModule/src/publish.ps1

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -145,11 +145,14 @@ LogGroup 'Publish to PSGallery' {
145145
if ($whatIf) {
146146
Write-Host "Publish-PSResource -Path $modulePath -Repository PSGallery -ApiKey ***"
147147
} else {
148-
try {
148+
$publishedPackage = Find-PSResource -Name $name -Version $publishPSVersion -Repository PSGallery -ErrorAction Stop
149+
if ($publishedPackage) {
150+
Write-Host (
151+
"::notice title=♻️ Resuming Gallery-only publication::$name $publishPSVersion is already " +
152+
'published to the PowerShell Gallery.'
153+
)
154+
} else {
149155
Publish-PSResource -Path $modulePath -Repository PSGallery -ApiKey $psGalleryApiKey
150-
} catch {
151-
Write-Error $_.Exception.Message
152-
exit 1
153156
}
154157
}
155158

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
[Diagnostics.CodeAnalysis.SuppressMessageAttribute(
2+
'PSUseDeclaredVarsMoreThanAssignments', '',
3+
Justification = 'Variables are assigned in BeforeAll and used inside It blocks.'
4+
)]
5+
[CmdletBinding()]
6+
param()
7+
8+
BeforeAll {
9+
Import-Module -Name 'PSModule' -Force
10+
11+
$script:publishScriptPath = Join-Path -Path $PSScriptRoot -ChildPath '../src/publish.ps1'
12+
$script:environmentVariableNames = @(
13+
'GITHUB_EVENT_PATH'
14+
'GITHUB_REPOSITORY'
15+
'GITHUB_WORKSPACE'
16+
'PSMODULE_PUBLISH_PSMODULE_INPUT_Name'
17+
'PSMODULE_PUBLISH_PSMODULE_INPUT_ModulePath'
18+
'PSMODULE_PUBLISH_PSMODULE_INPUT_PSGALLERY_API_KEY'
19+
'PSMODULE_PUBLISH_PSMODULE_INPUT_PullRequest'
20+
'PSMODULE_PUBLISH_PSMODULE_INPUT_WhatIf'
21+
)
22+
$script:originalEnvironment = @{}
23+
foreach ($name in $script:environmentVariableNames) {
24+
$script:originalEnvironment[$name] = [System.Environment]::GetEnvironmentVariable($name)
25+
}
26+
}
27+
28+
AfterAll {
29+
foreach ($name in $script:environmentVariableNames) {
30+
[System.Environment]::SetEnvironmentVariable($name, $script:originalEnvironment[$name])
31+
}
32+
Remove-Item -Path function:global:Find-PSResource -ErrorAction SilentlyContinue
33+
Remove-Item -Path function:global:Publish-PSResource -ErrorAction SilentlyContinue
34+
Remove-Item -Path function:global:Resolve-PSModuleDependency -ErrorAction SilentlyContinue
35+
}
36+
37+
Describe 'Publish-PSModule recovery' {
38+
BeforeEach {
39+
$script:moduleName = 'TestModule'
40+
$script:workspacePath = Join-Path -Path $TestDrive -ChildPath 'workspace'
41+
$script:modulePath = Join-Path -Path $script:workspacePath -ChildPath "outputs/module/$script:moduleName"
42+
$manifestPath = Join-Path -Path $script:modulePath -ChildPath "$script:moduleName.psd1"
43+
$eventPath = Join-Path -Path $TestDrive -ChildPath 'event.json'
44+
$null = New-Item -Path $script:modulePath -ItemType Directory -Force
45+
Set-Content -Path (Join-Path -Path $script:modulePath -ChildPath "$script:moduleName.psm1") -Value ''
46+
Set-Content -Path $manifestPath -Value @"
47+
@{
48+
RootModule = '$script:moduleName.psm1'
49+
ModuleVersion = '1.2.4'
50+
GUID = '3c0f8d73-60b7-4f38-b3cf-9386db4982a4'
51+
Author = 'PSModule'
52+
Description = 'Test module'
53+
PowerShellVersion = '5.1'
54+
PrivateData = @{
55+
PSData = @{
56+
Prerelease = ''
57+
}
58+
}
59+
}
60+
"@
61+
@{} | ConvertTo-Json | Set-Content -Path $eventPath
62+
63+
$env:GITHUB_EVENT_PATH = $eventPath
64+
$env:GITHUB_REPOSITORY = "PSModule/$script:moduleName"
65+
$env:GITHUB_WORKSPACE = $script:workspacePath
66+
$env:PSMODULE_PUBLISH_PSMODULE_INPUT_Name = $script:moduleName
67+
$env:PSMODULE_PUBLISH_PSMODULE_INPUT_ModulePath = 'outputs/module'
68+
$env:PSMODULE_PUBLISH_PSMODULE_INPUT_PSGALLERY_API_KEY = 'test-key'
69+
$env:PSMODULE_PUBLISH_PSMODULE_INPUT_PullRequest = ''
70+
$env:PSMODULE_PUBLISH_PSMODULE_INPUT_WhatIf = 'false'
71+
$script:publishInvoked = $false
72+
73+
Set-Item -Path function:global:Resolve-PSModuleDependency -Value {}
74+
Set-Item -Path function:global:Find-PSResource -Value {
75+
[PSCustomObject]@{ Name = 'TestModule'; Version = '1.2.4' }
76+
}
77+
Set-Item -Path function:global:Publish-PSResource -Value {
78+
$script:publishInvoked = $true
79+
}
80+
}
81+
82+
It 'skips Gallery publication when the resolved version already exists' {
83+
{ & $script:publishScriptPath } | Should -Not -Throw
84+
85+
$script:publishInvoked | Should -BeFalse
86+
}
87+
}

.github/actions/Resolve-PSModuleVersion/src/Resolve-PSModuleVersion.Helpers.psm1

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -724,6 +724,86 @@ function Get-NextModuleVersion {
724724
}
725725
}
726726

727+
function Get-ResolvedModuleVersion {
728+
<#
729+
.SYNOPSIS
730+
Resolves the next module version and resumes an incomplete stable release when possible.
731+
732+
.DESCRIPTION
733+
Normally the highest version from GitHub Releases and the PowerShell Gallery is the
734+
version baseline. If Gallery contains exactly the stable version implied by the latest
735+
GitHub release and this run's version bump, Gallery publication succeeded but GitHub
736+
release creation did not. In that case, return the Gallery version rather than bumping
737+
again so the workflow can resume the missing GitHub release.
738+
739+
.OUTPUTS
740+
PSSemVer representing the resolved module version.
741+
#>
742+
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSReviewUnusedParameter', '',
743+
Justification = 'Parameter is used inside LogGroup script block.')]
744+
[CmdletBinding()]
745+
[OutputType([object])]
746+
param(
747+
# The latest version found in GitHub Releases.
748+
[Parameter(Mandatory)]
749+
[object] $GitHubVersion,
750+
751+
# The latest stable version found in the PowerShell Gallery.
752+
[Parameter(Mandatory)]
753+
[object] $PSGalleryVersion,
754+
755+
# The release decision for this workflow run.
756+
[Parameter(Mandatory)]
757+
[PSCustomObject] $Decision,
758+
759+
# The publish configuration object.
760+
[Parameter(Mandatory)]
761+
[PSCustomObject] $Configuration,
762+
763+
# The name of the module.
764+
[Parameter(Mandatory)]
765+
[ValidateNotNullOrEmpty()]
766+
[string] $ModuleName,
767+
768+
# The GitHub releases list, used for prerelease numbering.
769+
[Parameter()]
770+
[AllowNull()]
771+
[AllowEmptyCollection()]
772+
[array] $Releases = @()
773+
)
774+
775+
LogGroup 'Resolve module version' {
776+
$latestVersion = Get-LatestPublishedVersion -GitHubVersion $GitHubVersion -PSGalleryVersion $PSGalleryVersion
777+
$params = @{
778+
LatestVersion = $latestVersion
779+
Decision = $Decision
780+
Configuration = $Configuration
781+
ModuleName = $ModuleName
782+
Releases = $Releases
783+
}
784+
$resolvedVersion = Get-NextModuleVersion @params
785+
786+
if ($Decision.CreateRelease) {
787+
$githubParams = $params.Clone()
788+
$githubParams.LatestVersion = $GitHubVersion
789+
$githubCandidate = Get-NextModuleVersion @githubParams
790+
$galleryVersionString = "$($PSGalleryVersion.Major).$($PSGalleryVersion.Minor).$($PSGalleryVersion.Patch)"
791+
$githubCandidateString = "$($githubCandidate.Major).$($githubCandidate.Minor).$($githubCandidate.Patch)"
792+
793+
if ([string]::IsNullOrWhiteSpace($PSGalleryVersion.Prerelease) -and
794+
$galleryVersionString -eq $githubCandidateString) {
795+
Write-Host (
796+
"PowerShell Gallery contains [$galleryVersionString], the next stable version after " +
797+
"GitHub [$GitHubVersion]. Resuming the Gallery-only publication."
798+
)
799+
$resolvedVersion = $githubCandidate
800+
}
801+
}
802+
803+
$resolvedVersion
804+
}
805+
}
806+
727807
function Write-ActionOutput {
728808
<#
729809
.SYNOPSIS

.github/actions/Resolve-PSModuleVersion/src/main.ps1

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,15 +31,15 @@ $decision = if ($null -eq $pullRequest) {
3131
$releases = @(Get-GitHubRelease)
3232
$ghVersion = Get-LatestGitHubVersion -Releases $releases
3333
$psGalleryVersion = Get-LatestPSGalleryVersion -ModuleName $actionInput.Name
34-
$latestVersion = Get-LatestPublishedVersion -GitHubVersion $ghVersion -PSGalleryVersion $psGalleryVersion
3534

3635
$params = @{
37-
LatestVersion = $latestVersion
36+
GitHubVersion = $ghVersion
37+
PSGalleryVersion = $psGalleryVersion
3838
Decision = $decision
3939
Configuration = $config
4040
ModuleName = $actionInput.Name
4141
Releases = $releases
4242
}
43-
$newVersion = Get-NextModuleVersion @params
43+
$newVersion = Get-ResolvedModuleVersion @params
4444

4545
Write-ActionOutput -Decision $decision -NewVersion $newVersion

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

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,40 @@ Describe 'Resolve-PSModuleVersion' {
137137
$releases[0].tagName | Should -Be 'v1.2.3'
138138
}
139139
}
140+
141+
Describe 'Get-ResolvedModuleVersion' {
142+
Context 'Get-ResolvedModuleVersion - Gallery-only stable publication' {
143+
It 'Get-ResolvedModuleVersion - reuses the Gallery version that is the next GitHub patch release' {
144+
$params = @{
145+
GitHubVersion = New-PSSemVer -Version '1.2.3'
146+
PSGalleryVersion = New-PSSemVer -Version '1.2.4'
147+
Decision = Get-TestDecision -Bump 'Patch'
148+
Configuration = Get-TestConfiguration
149+
ModuleName = 'MyModule'
150+
Releases = @()
151+
}
152+
153+
$result = Get-ResolvedModuleVersion @params
154+
155+
$result.ToString() | Should -Be 'v1.2.4'
156+
}
157+
158+
It 'Get-ResolvedModuleVersion - preserves the normal Gallery baseline when versions do not identify a retry' {
159+
$params = @{
160+
GitHubVersion = New-PSSemVer -Version '1.2.3'
161+
PSGalleryVersion = New-PSSemVer -Version '1.2.5'
162+
Decision = Get-TestDecision -Bump 'Patch'
163+
Configuration = Get-TestConfiguration
164+
ModuleName = 'MyModule'
165+
Releases = @()
166+
}
167+
168+
$result = Get-ResolvedModuleVersion @params
169+
170+
$result.ToString() | Should -Be 'v1.2.6'
171+
}
172+
}
173+
}
140174
}
141175

142176
Describe 'Get-LatestGitHubVersion' {

0 commit comments

Comments
 (0)