Skip to content

Commit f017813

Browse files
Keep the version prefix on the release tag only
The PowerShell Gallery and the module manifest only accept plain SemVer, so the prefix must not reach either. Both version strings now come from one composition, Get-ModuleVersionString, with Get-ReleaseTag adding the prefix on top, which removes the duplicated prerelease handling that could have drifted. The resolved-version summary and the closing log line report both strings so the separation is visible in the log. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
1 parent 2d23d93 commit f017813

3 files changed

Lines changed: 137 additions & 16 deletions

File tree

.github/actions/Publish-PSModule/src/Publish-PSModule.Helpers.psm1

Lines changed: 58 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,65 @@
1-
function Get-ReleaseTag {
1+
function Get-ModuleVersionString {
2+
<#
3+
.SYNOPSIS
4+
Builds the SemVer version string that identifies the module itself.
5+
6+
.DESCRIPTION
7+
Composes the module version and, when there is one, the prerelease label. This is the string the
8+
PowerShell Gallery and the module manifest understand: `Major.Minor.Patch` optionally followed by
9+
`-<prerelease>`. It never carries the repository's version prefix, because neither the manifest's
10+
`ModuleVersion` nor a Gallery package version accepts one.
11+
12+
.OUTPUTS
13+
String with the module version.
14+
15+
.EXAMPLE
16+
Get-ModuleVersionString -ModuleVersion '1.1.10'
17+
18+
Returns '1.1.10'.
19+
20+
.EXAMPLE
21+
Get-ModuleVersionString -ModuleVersion '1.1.10' -Prerelease 'mybranch001'
22+
23+
Returns '1.1.10-mybranch001'.
24+
#>
25+
[CmdletBinding()]
26+
[OutputType([string])]
27+
param(
28+
# The module version from the compiled manifest, in Major.Minor.Patch format.
29+
[Parameter(Mandatory)]
30+
[ValidateNotNullOrEmpty()]
31+
[string] $ModuleVersion,
32+
33+
# The prerelease label from the compiled manifest. Empty for a stable release.
34+
[Parameter()]
35+
[AllowEmptyString()]
36+
[AllowNull()]
37+
[string] $Prerelease
38+
)
39+
40+
if ([string]::IsNullOrWhiteSpace($Prerelease)) {
41+
return $ModuleVersion
42+
}
43+
44+
"$ModuleVersion-$($Prerelease.Trim())"
45+
}
46+
47+
function Get-ReleaseTag {
248
<#
349
.SYNOPSIS
450
Builds the git tag used for the GitHub release.
551
652
.DESCRIPTION
7-
Composes the release tag from the configured version prefix, the module version, and the
8-
prerelease label when there is one. The version comes from the compiled manifest, which is the
9-
artifact that is published, so the tag always names the exact bytes that were tested and pushed
10-
to the PowerShell Gallery. The manifest's ModuleVersion is Major.Minor.Patch by definition and
11-
cannot carry the prefix, so the prefix is supplied from the resolved settings
12-
(Publish.Module.VersionPrefix) instead. An empty prefix produces an unprefixed tag.
53+
Prefixes the module's SemVer version string with the configured version prefix. The version comes
54+
from the compiled manifest, which is the artifact that is published, so the tag always names the
55+
exact bytes that were tested and pushed to the PowerShell Gallery. The manifest's ModuleVersion is
56+
Major.Minor.Patch by definition and cannot carry the prefix, so the prefix is supplied from the
57+
resolved settings (Publish.Module.VersionPrefix) instead.
58+
59+
The prefix belongs to the GitHub release tag and to nothing else. PowerShell manifests and Gallery
60+
package versions only accept plain SemVer, so callers that need the module's own version use
61+
Get-ModuleVersionString. Deriving both from the same composition keeps the prefix as the only
62+
difference between them.
1363
1464
.OUTPUTS
1565
String with the release tag.
@@ -50,11 +100,5 @@
50100
[string] $Prerelease
51101
)
52102

53-
$tag = "$($VersionPrefix.Trim())$ModuleVersion"
54-
55-
if ([string]::IsNullOrWhiteSpace($Prerelease)) {
56-
return $tag
57-
}
58-
59-
"$tag-$($Prerelease.Trim())"
103+
"$($VersionPrefix.Trim())$(Get-ModuleVersionString -ModuleVersion $ModuleVersion -Prerelease $Prerelease)"
60104
}

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

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,13 +134,18 @@ LogGroup 'Resolve version from manifest' {
134134
$createPrerelease = $true
135135
}
136136

137+
# The PowerShell Gallery and the module manifest only accept plain SemVer, so the configured
138+
# VersionPrefix is applied to the GitHub release tag and to nothing else. Both strings are derived
139+
# from the same composition here, so the prefix is the only difference between them.
140+
$publishPSVersion = Get-ModuleVersionString -ModuleVersion $moduleVersion -Prerelease $prerelease
137141
$releaseTag = Get-ReleaseTag -VersionPrefix $versionPrefix -ModuleVersion $moduleVersion -Prerelease $prerelease
138142

139143
[PSCustomObject]@{
140144
ModuleVersion = $moduleVersion
141145
VersionPrefix = $versionPrefix
142146
Prerelease = $prerelease
143147
CreatePrerelease = $createPrerelease
148+
GalleryVersion = $publishPSVersion
144149
ReleaseTag = $releaseTag
145150
PRNumber = $prNumber
146151
PRHeadRef = $prHeadRef
@@ -160,7 +165,6 @@ LogGroup 'Install module dependencies' {
160165
#region Publish to PSGallery
161166
LogGroup 'Publish to PSGallery' {
162167
$releaseType = if ($createPrerelease) { 'New prerelease' } else { 'New release' }
163-
$publishPSVersion = if ($createPrerelease) { "$moduleVersion-$prerelease" } else { $moduleVersion }
164168
$psGalleryReleaseLink = "https://www.powershellgallery.com/packages/$name/$publishPSVersion"
165169

166170
Write-Host 'Publish module to PowerShell Gallery using API key from environment.'
@@ -286,4 +290,4 @@ LogGroup 'Create GitHub release' {
286290
}
287291
#endregion Create GitHub release
288292

289-
Write-Host "Publishing complete. Version: [$releaseTag]"
293+
Write-Host "Publishing complete. PowerShell Gallery version: [$publishPSVersion]. GitHub release tag: [$releaseTag]."

.github/actions/Publish-PSModule/tests/Publish-PSModule.Helpers.Tests.ps1

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,40 @@ BeforeAll {
1111
}
1212

1313
Describe 'Publish-PSModule.Helpers' {
14+
Describe 'Get-ModuleVersionString' {
15+
Context 'Get-ModuleVersionString - SemVer only, never prefixed' {
16+
It 'Get-ModuleVersionString - returns the module version for a stable release' {
17+
Get-ModuleVersionString -ModuleVersion '1.1.10' | Should -Be '1.1.10'
18+
}
19+
20+
It 'Get-ModuleVersionString - appends the prerelease label' {
21+
Get-ModuleVersionString -ModuleVersion '1.1.10' -Prerelease 'mybranch001' |
22+
Should -Be '1.1.10-mybranch001'
23+
}
24+
25+
It 'Get-ModuleVersionString - treats an empty prerelease label as a stable release' {
26+
Get-ModuleVersionString -ModuleVersion '1.1.10' -Prerelease '' | Should -Be '1.1.10'
27+
}
28+
29+
It 'Get-ModuleVersionString - treats a whitespace-only prerelease label as a stable release' {
30+
Get-ModuleVersionString -ModuleVersion '1.1.10' -Prerelease ' ' | Should -Be '1.1.10'
31+
}
32+
33+
It 'Get-ModuleVersionString - trims whitespace around the prerelease label' {
34+
Get-ModuleVersionString -ModuleVersion '1.1.10' -Prerelease ' mybranch001 ' |
35+
Should -Be '1.1.10-mybranch001'
36+
}
37+
38+
It 'Get-ModuleVersionString - takes no version prefix parameter at all' {
39+
(Get-Command Get-ModuleVersionString).Parameters.Keys | Should -Not -Contain 'VersionPrefix'
40+
}
41+
42+
It 'Get-ModuleVersionString - requires a module version' {
43+
{ Get-ModuleVersionString -ModuleVersion '' } | Should -Throw
44+
}
45+
}
46+
}
47+
1448
Describe 'Get-ReleaseTag' {
1549
Context 'Get-ReleaseTag - repository with a version prefix' {
1650
It 'Get-ReleaseTag - prefixes a stable release tag with the configured prefix' {
@@ -90,5 +124,44 @@ Describe 'Publish-PSModule.Helpers' {
90124
$first | Should -Be $second
91125
}
92126
}
127+
128+
# The PowerShell Gallery and the module manifest only accept plain SemVer. The prefix therefore
129+
# belongs to the GitHub release tag and to nothing else, and the two strings must differ by exactly
130+
# the prefix - never by anything else, and never in the other direction.
131+
Context 'Get-ReleaseTag - the prefix reaches the release tag and nothing else' {
132+
It 'Get-ReleaseTag - the tag is the prefix followed by the module version string' -ForEach @(
133+
@{ Prefix = 'v'; Version = '1.1.10'; Label = '' }
134+
@{ Prefix = 'v'; Version = '1.1.10'; Label = 'mybranch001' }
135+
@{ Prefix = ''; Version = '1.1.10'; Label = '' }
136+
@{ Prefix = ''; Version = '1.1.10'; Label = 'mybranch001' }
137+
@{ Prefix = 'release-v'; Version = '2.0.0'; Label = 'mybranch001' }
138+
) {
139+
$moduleVersion = Get-ModuleVersionString -ModuleVersion $Version -Prerelease $Label
140+
$tag = Get-ReleaseTag -VersionPrefix $Prefix -ModuleVersion $Version -Prerelease $Label
141+
$tag | Should -Be "$Prefix$moduleVersion"
142+
}
143+
144+
It 'Get-ReleaseTag - the module version string never gains the prefix' -ForEach @(
145+
@{ Prefix = 'v'; Version = '1.1.10'; Label = '' }
146+
@{ Prefix = 'v'; Version = '1.1.10'; Label = 'mybranch001' }
147+
@{ Prefix = 'release-v'; Version = '2.0.0'; Label = 'mybranch001' }
148+
) {
149+
$moduleVersion = Get-ModuleVersionString -ModuleVersion $Version -Prerelease $Label
150+
$moduleVersion | Should -Not -BeLike "$Prefix*"
151+
$moduleVersion | Should -Match '^\d+\.\d+\.\d+(-[0-9A-Za-z\-.]+)?$'
152+
}
153+
154+
It 'Get-ReleaseTag - an unprefixed repository gets identical strings' {
155+
$moduleVersion = Get-ModuleVersionString -ModuleVersion '1.1.10' -Prerelease 'mybranch001'
156+
$tag = Get-ReleaseTag -VersionPrefix '' -ModuleVersion '1.1.10' -Prerelease 'mybranch001'
157+
$tag | Should -Be $moduleVersion
158+
}
159+
160+
It 'Get-ReleaseTag - stripping the prefix from the tag yields the module version string' {
161+
$moduleVersion = Get-ModuleVersionString -ModuleVersion '1.1.10' -Prerelease 'mybranch001'
162+
$tag = Get-ReleaseTag -VersionPrefix 'v' -ModuleVersion '1.1.10' -Prerelease 'mybranch001'
163+
$tag -replace '^v' | Should -Be $moduleVersion
164+
}
165+
}
93166
}
94167
}

0 commit comments

Comments
 (0)