Skip to content

Commit c8f5586

Browse files
authored
Merge pull request #16 from tablackburn/chore/workflow-template-guards
Skip template-incompatible CI/Publish jobs on un-initialized template
2 parents eb80695 + d37b827 commit c8f5586

4 files changed

Lines changed: 86 additions & 14 deletions

File tree

.github/workflows/CI.yaml

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,23 @@ jobs:
1818
steps:
1919
- uses: actions/checkout@v6
2020

21+
# Skip lint on the un-initialized template — the literal `./{{ModuleName}}`
22+
# path argument can't be parsed by PowerShell (the double braces split into
23+
# mismatched script-block delimiters), so Invoke-ScriptAnalyzer fails with
24+
# a positional-argument error before it ever touches the folder. Same
25+
# marker as the unit-tests job below.
26+
- name: Detect template state
27+
id: template_guard
28+
shell: bash
29+
run: |
30+
if [ -f CHANGELOG.template.md ]; then
31+
echo "is_template=true" >> "$GITHUB_OUTPUT"
32+
else
33+
echo "is_template=false" >> "$GITHUB_OUTPUT"
34+
fi
35+
2136
- name: Cache PowerShell modules
37+
if: steps.template_guard.outputs.is_template == 'false'
2238
id: cache-lint-modules
2339
uses: actions/cache@v5
2440
with:
@@ -28,13 +44,14 @@ jobs:
2844
${{ runner.os }}-psmodules-lint-
2945
3046
- name: Install PSScriptAnalyzer
31-
if: steps.cache-lint-modules.outputs.cache-hit != 'true'
47+
if: steps.template_guard.outputs.is_template == 'false' && steps.cache-lint-modules.outputs.cache-hit != 'true'
3248
shell: pwsh
3349
run: |
3450
Set-PSRepository -Name PSGallery -InstallationPolicy Trusted
3551
Install-Module -Name PSScriptAnalyzer -Force -Scope CurrentUser
3652
3753
- name: Run PSScriptAnalyzer
54+
if: steps.template_guard.outputs.is_template == 'false'
3855
shell: pwsh
3956
run: |
4057
$results = Invoke-ScriptAnalyzer -Path ./{{ModuleName}} -Recurse -Settings PSGallery -ReportSummary
@@ -63,7 +80,27 @@ jobs:
6380
steps:
6481
- uses: actions/checkout@v6
6582

83+
# Skip subsequent steps on the un-initialized template — Build's
84+
# GENERATEMARKDOWN task can't import the manifest while {{GUID}} is still
85+
# a literal placeholder. Marker: CHANGELOG.template.md exists only
86+
# pre-init; Initialize-Template.ps1 moves it onto CHANGELOG.md during
87+
# init, so downstream repos run the full job. The marker path contains
88+
# no placeholder token, so init's substitution loop leaves this guard
89+
# intact when the workflow is copied into a new module.
90+
# hashFiles() is not allowed in jobs.<job_id>.if, so we evaluate it in a
91+
# step and gate downstream steps on the resulting output.
92+
- name: Detect template state
93+
id: template_guard
94+
shell: bash
95+
run: |
96+
if [ -f CHANGELOG.template.md ]; then
97+
echo "is_template=true" >> "$GITHUB_OUTPUT"
98+
else
99+
echo "is_template=false" >> "$GITHUB_OUTPUT"
100+
fi
101+
66102
- name: Cache PowerShell modules
103+
if: steps.template_guard.outputs.is_template == 'false'
67104
uses: actions/cache@v5
68105
with:
69106
path: |
@@ -74,23 +111,24 @@ jobs:
74111
${{ runner.os }}-psmodules-
75112
76113
- name: Build and Test
114+
if: steps.template_guard.outputs.is_template == 'false'
77115
shell: pwsh
78116
run: |
79117
New-Item -Path out -ItemType Directory -Force | Out-Null
80118
./build.ps1 -Task Build,Test -Bootstrap
81119
82120
- name: Upload Coverage to Codecov
121+
if: success() && steps.template_guard.outputs.is_template == 'false'
83122
uses: codecov/codecov-action@v6
84-
if: success()
85123
with:
86124
token: ${{ secrets.CODECOV_TOKEN }}
87125
files: out/codeCoverage.xml
88126
flags: ${{ matrix.os }}
89127
fail_ci_if_error: false
90128

91129
- name: Upload Test Results
130+
if: always() && steps.template_guard.outputs.is_template == 'false'
92131
uses: actions/upload-artifact@v7
93-
if: always()
94132
with:
95133
name: test-results-${{ matrix.os }}
96134
path: out/

.github/workflows/PublishModuleToPowerShellGallery.yaml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,26 @@ jobs:
2121
with:
2222
fetch-depth: 0
2323

24+
# Never publish the un-initialized template — the .psd1 still has
25+
# {{ModuleName}} and {{GUID}} placeholders. Same marker as CI.yaml:
26+
# CHANGELOG.template.md exists only pre-init. hashFiles() is not allowed
27+
# in jobs.<job_id>.if, so we evaluate it in a step and gate the
28+
# version-detection and release-check steps on the resulting output;
29+
# everything downstream cascades on those steps' outputs and skips
30+
# naturally when they don't run.
31+
- name: Detect template state
32+
id: template_guard
33+
shell: bash
34+
run: |
35+
if [ -f CHANGELOG.template.md ]; then
36+
echo "is_template=true" >> "$GITHUB_OUTPUT"
37+
else
38+
echo "is_template=false" >> "$GITHUB_OUTPUT"
39+
fi
40+
2441
- name: Get Module Version
2542
id: version
43+
if: steps.template_guard.outputs.is_template == 'false'
2644
shell: pwsh
2745
run: |
2846
$manifest = Import-PowerShellDataFile -Path ./{{ModuleName}}/{{ModuleName}}.psd1
@@ -32,6 +50,7 @@ jobs:
3250
3351
- name: Check if Release Exists
3452
id: check_release
53+
if: steps.template_guard.outputs.is_template == 'false'
3554
shell: bash
3655
env:
3756
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

Initialize-Template.ps1

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -242,8 +242,9 @@ if (Test-Path -Path $templateModuleFolder) {
242242
# Rename example function files
243243
$publicFolder = Join-Path -Path $moduleFolder -ChildPath 'Public'
244244
$privateFolder = Join-Path -Path $moduleFolder -ChildPath 'Private'
245-
$testPublicFolder = Join-Path -Path $PSScriptRoot -ChildPath 'tests/Unit/Public'
246-
$testPrivateFolder = Join-Path -Path $PSScriptRoot -ChildPath 'tests/Unit/Private'
245+
$testUnitFolder = Join-Path -Path (Join-Path -Path $PSScriptRoot -ChildPath 'tests') -ChildPath 'Unit'
246+
$testPublicFolder = Join-Path -Path $testUnitFolder -ChildPath 'Public'
247+
$testPrivateFolder = Join-Path -Path $testUnitFolder -ChildPath 'Private'
247248

248249
$foldersToCheck = @($publicFolder, $privateFolder, $testPublicFolder, $testPrivateFolder)
249250

@@ -280,21 +281,34 @@ if (Test-Path -Path $docsFolder) {
280281
}
281282

282283
# Replace template-facing README.md with the module-facing README.template.md
283-
# (placeholders inside README.template.md were already substituted by the file-processing loop above)
284+
# (placeholders inside README.template.md were already substituted by the file-processing loop above).
285+
# If the destination already exists (e.g., the user is re-running init after customizing it),
286+
# leave both files in place and warn — manually resolving is safer than overwriting customizations.
284287
$readmeTemplate = Join-Path -Path $PSScriptRoot -ChildPath 'README.template.md'
285288
$readmePath = Join-Path -Path $PSScriptRoot -ChildPath 'README.md'
286289
if (Test-Path -Path $readmeTemplate) {
287-
Move-Item -Path $readmeTemplate -Destination $readmePath -Force
288-
Write-Host ' Generated module README.md from template' -ForegroundColor Green
290+
if (Test-Path -Path $readmePath) {
291+
Write-Warning ' README.md already exists; leaving it in place. Resolve README.template.md manually.'
292+
}
293+
else {
294+
Move-Item -Path $readmeTemplate -Destination $readmePath
295+
Write-Host ' Generated module README.md from template' -ForegroundColor Green
296+
}
289297
}
290298

291299
# Replace template-facing CHANGELOG.md with the module-facing CHANGELOG.template.md
292-
# (placeholders inside CHANGELOG.template.md were already substituted by the file-processing loop above)
300+
# (placeholders inside CHANGELOG.template.md were already substituted by the file-processing loop above).
301+
# Same guard as README above — preserve any existing CHANGELOG.md rather than clobber it.
293302
$changelogTemplate = Join-Path -Path $PSScriptRoot -ChildPath 'CHANGELOG.template.md'
294303
$changelogPath = Join-Path -Path $PSScriptRoot -ChildPath 'CHANGELOG.md'
295304
if (Test-Path -Path $changelogTemplate) {
296-
Move-Item -Path $changelogTemplate -Destination $changelogPath -Force
297-
Write-Host ' Generated module CHANGELOG.md from template' -ForegroundColor Green
305+
if (Test-Path -Path $changelogPath) {
306+
Write-Warning ' CHANGELOG.md already exists; leaving it in place. Resolve CHANGELOG.template.md manually.'
307+
}
308+
else {
309+
Move-Item -Path $changelogTemplate -Destination $changelogPath
310+
Write-Host ' Generated module CHANGELOG.md from template' -ForegroundColor Green
311+
}
298312
}
299313

300314
# Initialize Git repository if requested

tests/ManifestHelpers.psm1

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -123,9 +123,10 @@ function Compare-SemVerPrerelease {
123123

124124
if ($firstIsNumeric -and $secondIsNumeric) {
125125
# SemVer 2.0.0 permits arbitrarily large numeric identifiers — use BigInteger
126-
# rather than [long] to avoid overflow.
127-
$firstNum = [bigint]$firstId
128-
$secondNum = [bigint]$secondId
126+
# rather than [long] to avoid overflow. [bigint] is a PS 7+ accelerator only,
127+
# so spell out the full type for Windows PowerShell 5.1 compatibility.
128+
$firstNum = [System.Numerics.BigInteger]$firstId
129+
$secondNum = [System.Numerics.BigInteger]$secondId
129130

130131
if ($firstNum -lt $secondNum) {
131132
return -1

0 commit comments

Comments
 (0)