Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .github/actions/Publish-PSModule/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,13 @@ inputs:
description: Name of the uploaded artifact to download. Must match the name used in the upstream upload-artifact step.
required: false
default: module
VersionPrefix:
description: |
Prefix put in front of the version in the git tag of the GitHub release, for example 'v'.
Comes from Settings.Publish.Module.VersionPrefix, which the Plan job resolves. The compiled manifest carries the module version as
Major.Minor.Patch and cannot carry the prefix, so it is supplied here. An empty value tags the release without a prefix.
required: false
default: ''

runs:
using: composite
Expand Down Expand Up @@ -65,4 +72,5 @@ runs:
PSMODULE_PUBLISH_PSMODULE_INPUT_UsePRBodyAsReleaseNotes: ${{ inputs.UsePRBodyAsReleaseNotes }}
PSMODULE_PUBLISH_PSMODULE_INPUT_UsePRTitleAsReleaseName: ${{ inputs.UsePRTitleAsReleaseName }}
PSMODULE_PUBLISH_PSMODULE_INPUT_UsePRTitleAsNotesHeading: ${{ inputs.UsePRTitleAsNotesHeading }}
PSMODULE_PUBLISH_PSMODULE_INPUT_VersionPrefix: ${{ inputs.VersionPrefix }}
run: ${{ github.action_path }}/src/publish.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
ο»Ώfunction Get-ReleaseTag {
<#
.SYNOPSIS
Builds the git tag used for the GitHub release.

.DESCRIPTION
Composes the release tag from the configured version prefix, the module version, and the
prerelease label when there is one. The version comes from the compiled manifest, which is the
artifact that is published, so the tag always names the exact bytes that were tested and pushed
to the PowerShell Gallery. The manifest's ModuleVersion is Major.Minor.Patch by definition and
cannot carry the prefix, so the prefix is supplied from the resolved settings
(Publish.Module.VersionPrefix) instead. An empty prefix produces an unprefixed tag.

.OUTPUTS
String with the release tag.

.EXAMPLE
Get-ReleaseTag -VersionPrefix 'v' -ModuleVersion '1.1.10'

Returns 'v1.1.10'.

.EXAMPLE
Get-ReleaseTag -VersionPrefix 'v' -ModuleVersion '1.1.10' -Prerelease 'mybranch001'

Returns 'v1.1.10-mybranch001'.

.EXAMPLE
Get-ReleaseTag -VersionPrefix '' -ModuleVersion '1.1.10'

Returns '1.1.10'.
#>
[CmdletBinding()]
[OutputType([string])]
param(
# The module version from the compiled manifest, in Major.Minor.Patch format.
[Parameter(Mandatory)]
[ValidateNotNullOrEmpty()]
[string] $ModuleVersion,

# The prefix put in front of the version, for example 'v'. Empty for an unprefixed repository.
[Parameter()]
[AllowEmptyString()]
[AllowNull()]
[string] $VersionPrefix,

# The prerelease label from the compiled manifest. Empty for a stable release.
[Parameter()]
[AllowEmptyString()]
[AllowNull()]
[string] $Prerelease
)

$tag = "$($VersionPrefix.Trim())$ModuleVersion"
Comment thread
MariusStorhaug marked this conversation as resolved.
Outdated

if ([string]::IsNullOrWhiteSpace($Prerelease)) {
return $tag
}

"$tag-$($Prerelease.Trim())"
}
14 changes: 10 additions & 4 deletions .github/actions/Publish-PSModule/src/publish.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ param()
$PSStyle.OutputRendering = 'Ansi'

Import-Module -Name 'PSModule' -Force
Import-Module -Name "$PSScriptRoot/Publish-PSModule.Helpers.psm1" -Force

#region Load inputs
LogGroup 'Load inputs' {
Expand Down Expand Up @@ -58,10 +59,14 @@ LogGroup 'Load inputs' {
$usePRBodyAsReleaseNotes = $env:PSMODULE_PUBLISH_PSMODULE_INPUT_UsePRBodyAsReleaseNotes -eq 'true'
$usePRTitleAsReleaseName = $env:PSMODULE_PUBLISH_PSMODULE_INPUT_UsePRTitleAsReleaseName -eq 'true'
$usePRTitleAsNotesHeading = $env:PSMODULE_PUBLISH_PSMODULE_INPUT_UsePRTitleAsNotesHeading -eq 'true'
# The prefix the repository tags releases with, resolved by the Plan job from
# Settings.Publish.Module.VersionPrefix. Empty means the repository tags without a prefix.
$versionPrefix = $env:PSMODULE_PUBLISH_PSMODULE_INPUT_VersionPrefix

Write-Host "Module name: [$name]"
Write-Host "Module path: [$modulePath]"
Write-Host "WhatIf: [$whatIf]"
Write-Host "Module name: [$name]"
Write-Host "Module path: [$modulePath]"
Write-Host "Version prefix: [$versionPrefix]"
Write-Host "WhatIf: [$whatIf]"
}
#endregion Load inputs

Expand Down Expand Up @@ -129,10 +134,11 @@ LogGroup 'Resolve version from manifest' {
$createPrerelease = $true
}

$releaseTag = if ($createPrerelease) { "$moduleVersion-$prerelease" } else { $moduleVersion }
$releaseTag = Get-ReleaseTag -VersionPrefix $versionPrefix -ModuleVersion $moduleVersion -Prerelease $prerelease

[PSCustomObject]@{
ModuleVersion = $moduleVersion
VersionPrefix = $versionPrefix
Prerelease = $prerelease
CreatePrerelease = $createPrerelease
ReleaseTag = $releaseTag
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
ο»Ώ[Diagnostics.CodeAnalysis.SuppressMessageAttribute(
'PSUseDeclaredVarsMoreThanAssignments', '',
Justification = 'Variables are assigned in BeforeAll and used inside It blocks.'
)]
[CmdletBinding()]
param()

BeforeAll {
Import-Module -Name 'PSModule' -Force
Import-Module -Name (Join-Path -Path $PSScriptRoot -ChildPath '../src/Publish-PSModule.Helpers.psm1') -Force
}

Describe 'Publish-PSModule.Helpers' {
Describe 'Get-ReleaseTag' {
Context 'Get-ReleaseTag - repository with a version prefix' {
It 'Get-ReleaseTag - prefixes a stable release tag with the configured prefix' {
Get-ReleaseTag -VersionPrefix 'v' -ModuleVersion '1.1.10' | Should -Be 'v1.1.10'
}

It 'Get-ReleaseTag - prefixes a stable release tag when the prerelease label is empty' {
Get-ReleaseTag -VersionPrefix 'v' -ModuleVersion '1.1.10' -Prerelease '' | Should -Be 'v1.1.10'
}

It 'Get-ReleaseTag - prefixes a prerelease tag with the configured prefix' {
Get-ReleaseTag -VersionPrefix 'v' -ModuleVersion '1.1.10' -Prerelease 'mybranch001' |
Should -Be 'v1.1.10-mybranch001'
}

It 'Get-ReleaseTag - supports a multi-character prefix' {
Get-ReleaseTag -VersionPrefix 'release-v' -ModuleVersion '2.0.0' | Should -Be 'release-v2.0.0'
}
}

Context 'Get-ReleaseTag - repository without a version prefix' {
It 'Get-ReleaseTag - leaves a stable release tag unprefixed' {
Get-ReleaseTag -VersionPrefix '' -ModuleVersion '1.1.10' | Should -Be '1.1.10'
}

It 'Get-ReleaseTag - leaves a prerelease tag unprefixed' {
Get-ReleaseTag -VersionPrefix '' -ModuleVersion '1.1.10' -Prerelease 'mybranch001' |
Should -Be '1.1.10-mybranch001'
}

It 'Get-ReleaseTag - treats an absent prefix as no prefix' {
Get-ReleaseTag -ModuleVersion '1.1.10' | Should -Be '1.1.10'
}

It 'Get-ReleaseTag - treats a null prefix as no prefix' {
Get-ReleaseTag -VersionPrefix $null -ModuleVersion '1.1.10' | Should -Be '1.1.10'
}
}

Context 'Get-ReleaseTag - input normalization' {
It 'Get-ReleaseTag - trims whitespace around the prefix' {
Get-ReleaseTag -VersionPrefix ' v ' -ModuleVersion '1.1.10' | Should -Be 'v1.1.10'
}

It 'Get-ReleaseTag - trims whitespace around the prerelease label' {
Get-ReleaseTag -VersionPrefix 'v' -ModuleVersion '1.1.10' -Prerelease ' mybranch001 ' |
Should -Be 'v1.1.10-mybranch001'
}

It 'Get-ReleaseTag - treats a whitespace-only prerelease label as a stable release' {
Get-ReleaseTag -VersionPrefix 'v' -ModuleVersion '1.1.10' -Prerelease ' ' | Should -Be 'v1.1.10'
}

It 'Get-ReleaseTag - requires a module version' {
{ Get-ReleaseTag -VersionPrefix 'v' -ModuleVersion '' } | Should -Throw
}
}

# Cleanup-PSModulePrereleases selects the releases to delete with
# `tagName -like "*$prereleaseName*" -and tagName -ne $publishedReleaseTag`, where the published tag is
# the value publish.ps1 exports as PSMODULE_PUBLISH_PSMODULE_CONTEXT_ReleaseTag. Both halves of that
# filter have to keep working once the tag carries a prefix.
Context 'Get-ReleaseTag - AutoCleanup tag matching contract' {
It 'Get-ReleaseTag - keeps the prerelease name inside a prefixed tag so cleanup still matches it' {
Get-ReleaseTag -VersionPrefix 'v' -ModuleVersion '1.1.10' -Prerelease 'mybranch001' |
Should -BeLike '*mybranch*'
}

It 'Get-ReleaseTag - keeps the prerelease name inside an unprefixed tag so cleanup still matches it' {
Get-ReleaseTag -VersionPrefix '' -ModuleVersion '1.1.10' -Prerelease 'mybranch001' |
Should -BeLike '*mybranch*'
}

It 'Get-ReleaseTag - produces the same tag twice so cleanup can exclude the published release' {
$first = Get-ReleaseTag -VersionPrefix 'v' -ModuleVersion '1.1.10' -Prerelease 'mybranch001'
$second = Get-ReleaseTag -VersionPrefix 'v' -ModuleVersion '1.1.10' -Prerelease 'mybranch001'
$first | Should -Be $second
}
}
}
}
1 change: 1 addition & 0 deletions .github/workflows/Publish-Module.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ jobs:
UsePRTitleAsReleaseName: ${{ fromJson(inputs.Settings).Publish.Module.UsePRTitleAsReleaseName }}
UsePRBodyAsReleaseNotes: ${{ fromJson(inputs.Settings).Publish.Module.UsePRBodyAsReleaseNotes }}
UsePRTitleAsNotesHeading: ${{ fromJson(inputs.Settings).Publish.Module.UsePRTitleAsNotesHeading }}
VersionPrefix: ${{ fromJson(inputs.Settings).Publish.Module.VersionPrefix }}
WorkingDirectory: ${{ fromJson(inputs.Settings).WorkingDirectory }}

- name: Cleanup prereleases
Expand Down
15 changes: 15 additions & 0 deletions tests/srcTestRepo/.github/PSModule.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,18 @@
Name: PSModuleTest2
Linter:
Skip: true
Publish:
Module:
# 'Fix' is here so that Process-PSModule's own self-test exercises the publish path. The framework
# repository labels its bugfix pull requests 'Fix', which makes Get-PSModuleSettings resolve
# ReleaseType to 'Prerelease' for this fixture, so Publish-PSModule actually runs and its resolved
# release tag is visible in the workflow log. Publish-Module.yml sets WhatIf whenever the workflow
# runs in PSModule/Process-PSModule, so nothing is published and no release is created.
#
# Never add a label that PSModule/Auto-Release recognises. It matches the literal string 'prerelease'
# with -Contains, which is case-insensitive in PowerShell, and would make this repository create a
# real prerelease release and tag of itself.
#
# This is a stopgap that covers the Settings -> action input -> environment variable hop until the
# end-to-end publish harness in PSModule/Process-PSModule#436 exists.
PrereleaseLabels: 'prerelease, Fix'
Loading