Skip to content

Commit da1b765

Browse files
tablackburnclaude
andcommitted
style: enforce quoted literals, named parameters, and parameter validation
The repo's own powershell.instructions.md mandates three rules for in-tree code: - literal string parameter values are single-quoted - cmdlet calls use named parameters (when more than one arg is passed) - every function parameter has an appropriate validator This commit applies those rules to the template's first-party files — the example public/private functions, the test scaffolding, the meta helper modules, and build.ps1. Notable changes: - build.ps1 gains [ValidateNotNullOrEmpty()] on $Task - tests/MetaFixers.psm1 + tests/ManifestHelpers.psm1 gain validators on every parameter that didn't already have one - tests/Help.tests.ps1, tests/Manifest.tests.ps1, tests/Meta.tests.ps1 rename positional Split-Path / Join-Path / Get-Module / Get-Content calls to use named -Path / -ChildPath / -Name / -Pattern parameters - the example Get-{{Prefix}}Example.ps1 / its tests get the same treatment so newly-scaffolded modules start out compliant No behavioural changes. CI on the un-initialized template still skips build/test (the {{GUID}} placeholder is unparseable until init runs); parse-checks confirm every edited file is syntactically valid. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent f0bdb02 commit da1b765

9 files changed

Lines changed: 46 additions & 34 deletions

File tree

build.ps1

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ param(
4040
@()
4141
}
4242
})]
43+
[ValidateNotNullOrEmpty()]
4344
[string[]]$Task = 'default',
4445

4546
# Bootstrap dependencies

tests/Help.tests.ps1

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -57,10 +57,10 @@ BeforeDiscovery {
5757
}
5858

5959
# PowerShellBuild outputs to Output/<ModuleName>/<Version>/, override BHBuildOutput
60-
$projectRoot = Split-Path -Parent $PSScriptRoot
61-
$sourceManifest = Join-Path $projectRoot "$Env:BHProjectName/$Env:BHProjectName.psd1"
60+
$projectRoot = Split-Path -Path $PSScriptRoot -Parent
61+
$sourceManifest = Join-Path -Path $projectRoot -ChildPath "$Env:BHProjectName/$Env:BHProjectName.psd1"
6262
$moduleVersion = (Import-PowerShellDataFile -Path $sourceManifest).ModuleVersion
63-
$Env:BHBuildOutput = Join-Path $projectRoot "Output/$Env:BHProjectName/$moduleVersion"
63+
$Env:BHBuildOutput = Join-Path -Path $projectRoot -ChildPath "Output/$Env:BHProjectName/$moduleVersion"
6464

6565
# Define the path to the module manifest
6666
$moduleManifestFilename = $Env:BHProjectName + '.psd1'
@@ -72,18 +72,18 @@ BeforeDiscovery {
7272
'Classes'
7373
) | ForEach-Object {
7474
$path = Join-Path -Path $Env:BHBuildOutput -ChildPath $_
75-
if (Test-Path $path) {
75+
if (Test-Path -Path $path) {
7676
$global:CustomTypes += (Get-ChildItem -Path $path -Recurse -ErrorAction 'SilentlyContinue').BaseName
7777
}
7878
}
7979

8080
# Remove all versions of the module from the session. Pester can't handle multiple versions.
81-
Get-Module $Env:BHProjectName | Remove-Module -Force -ErrorAction 'Ignore'
81+
Get-Module -Name $Env:BHProjectName | Remove-Module -Force -ErrorAction 'Ignore'
8282
Import-Module -Name $moduleManifestPath -Verbose:$false -ErrorAction 'Stop'
8383

8484
# Get module commands
8585
$getCommandParameters = @{
86-
Module = (Get-Module $Env:BHProjectName)
86+
Module = (Get-Module -Name $Env:BHProjectName)
8787
CommandType = [System.Management.Automation.CommandTypes[]]'Cmdlet, Function' # Not alias
8888
}
8989
if ($PSVersionTable.PSVersion.Major -lt 6) {

tests/Manifest.tests.ps1

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -69,10 +69,10 @@ BeforeDiscovery {
6969
}
7070

7171
# PowerShellBuild outputs to Output/<ModuleName>/<Version>/, override BHBuildOutput
72-
$projectRoot = Split-Path -Parent $PSScriptRoot
73-
$sourceManifest = Join-Path $projectRoot "$Env:BHProjectName/$Env:BHProjectName.psd1"
72+
$projectRoot = Split-Path -Path $PSScriptRoot -Parent
73+
$sourceManifest = Join-Path -Path $projectRoot -ChildPath "$Env:BHProjectName/$Env:BHProjectName.psd1"
7474
$moduleVersion = (Import-PowerShellDataFile -Path $sourceManifest).ModuleVersion
75-
$Env:BHBuildOutput = Join-Path $projectRoot "Output/$Env:BHProjectName/$moduleVersion"
75+
$Env:BHBuildOutput = Join-Path -Path $projectRoot -ChildPath "Output/$Env:BHProjectName/$moduleVersion"
7676

7777
# Define the path to the module manifest
7878
$moduleManifestFilename = $Env:BHProjectName + '.psd1'
@@ -108,10 +108,10 @@ BeforeAll {
108108
}
109109

110110
# PowerShellBuild outputs to Output/<ModuleName>/<Version>/, override BHBuildOutput
111-
$projectRoot = Split-Path -Parent $PSScriptRoot
112-
$sourceManifest = Join-Path $projectRoot "$Env:BHProjectName/$Env:BHProjectName.psd1"
111+
$projectRoot = Split-Path -Path $PSScriptRoot -Parent
112+
$sourceManifest = Join-Path -Path $projectRoot -ChildPath "$Env:BHProjectName/$Env:BHProjectName.psd1"
113113
$moduleVersion = (Import-PowerShellDataFile -Path $sourceManifest).ModuleVersion
114-
$Env:BHBuildOutput = Join-Path $projectRoot "Output/$Env:BHProjectName/$moduleVersion"
114+
$Env:BHBuildOutput = Join-Path -Path $projectRoot -ChildPath "Output/$Env:BHProjectName/$moduleVersion"
115115

116116
# Define the path to the module manifest
117117
$moduleManifestFilename = $Env:BHProjectName + '.psd1'
@@ -135,12 +135,12 @@ BeforeAll {
135135
Import-Module -Name (Join-Path -Path $PSScriptRoot -ChildPath 'ManifestHelpers.psm1') -Verbose:$false -Force
136136

137137
$requirementsPath = Join-Path -Path $env:BHProjectPath -ChildPath 'requirements.psd1'
138-
$requirements = Import-PowerShellDataFile -Path $requirementsPath -ErrorAction Stop
138+
$requirements = Import-PowerShellDataFile -Path $requirementsPath -ErrorAction 'Stop'
139139

140140
# Parse the version from the changelog
141141
$changelogPath = Join-Path -Path $Env:BHProjectPath -ChildPath 'CHANGELOG.md'
142142
$changelogVersionPattern = '^##\s\\?\[(?<Version>(\d+\.){1,3}\d+)\\?\]' # Matches on a line that starts with '## [Version]' or '## \[Version\]'
143-
$changelogVersion = Get-Content $changelogPath | ForEach-Object {
143+
$changelogVersion = Get-Content -Path $changelogPath | ForEach-Object {
144144
if ($_ -match $changelogVersionPattern) {
145145
$changelogVersion = $matches.Version
146146
break

tests/ManifestHelpers.psm1

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,12 @@ function Split-SemVerString {
3636
[OutputType([hashtable])]
3737
param(
3838
[Parameter(Mandatory = $true)]
39+
[ValidateNotNullOrEmpty()]
3940
[string]$VersionString
4041
)
4142

4243
if ([string]::IsNullOrEmpty($VersionString)) {
43-
throw "VersionString cannot be empty or null"
44+
throw 'VersionString cannot be empty or null'
4445
}
4546

4647
# Strip build metadata per SemVer 2.0.0 — it does not affect precedence and is
@@ -92,9 +93,11 @@ function Compare-SemVerPrerelease {
9293
[OutputType([int])]
9394
param(
9495
[Parameter(Mandatory = $true)]
96+
[ValidateNotNullOrEmpty()]
9597
[string]$FirstPrerelease,
9698

9799
[Parameter(Mandatory = $true)]
100+
[ValidateNotNullOrEmpty()]
98101
[string]$SecondPrerelease
99102
)
100103

@@ -208,13 +211,15 @@ function Test-VersionComparison {
208211
[OutputType([bool])]
209212
param(
210213
[Parameter(Mandatory = $true)]
214+
[ValidateNotNullOrEmpty()]
211215
[string]$FirstVersion,
212216

213217
[Parameter(Mandatory = $false)]
214218
[AllowNull()]
215219
[string]$FirstPrerelease,
216220

217221
[Parameter(Mandatory = $true)]
222+
[ValidateNotNullOrEmpty()]
218223
[string]$SecondVersion,
219224

220225
[Parameter(Mandatory = $false)]
@@ -325,9 +330,11 @@ function Test-VersionConstraint {
325330
[OutputType([bool])]
326331
param(
327332
[Parameter(Mandatory = $true)]
333+
[ValidateNotNullOrEmpty()]
328334
[string]$ManifestVersion,
329335

330336
[Parameter(Mandatory = $true)]
337+
[ValidateNotNullOrEmpty()]
331338
[string]$RequirementsVersion,
332339

333340
[Parameter(Mandatory = $true)]
@@ -337,14 +344,14 @@ function Test-VersionConstraint {
337344

338345
# Validate input versions are not empty
339346
if ([string]::IsNullOrWhiteSpace($ManifestVersion)) {
340-
throw "ManifestVersion cannot be empty or whitespace"
347+
throw 'ManifestVersion cannot be empty or whitespace'
341348
}
342349
if ([string]::IsNullOrWhiteSpace($RequirementsVersion)) {
343-
throw "RequirementsVersion cannot be empty or whitespace"
350+
throw 'RequirementsVersion cannot be empty or whitespace'
344351
}
345352

346-
$manifestParts = Split-SemVerString $ManifestVersion
347-
$requirementsParts = Split-SemVerString $RequirementsVersion
353+
$manifestParts = Split-SemVerString -VersionString $ManifestVersion
354+
$requirementsParts = Split-SemVerString -VersionString $RequirementsVersion
348355

349356
$comparisonParameters = @{
350357
FirstVersion = $requirementsParts.Version

tests/Meta.tests.ps1

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,11 @@ BeforeAll {
99
$projectRoot = $PSScriptRoot
1010
}
1111

12-
$allTextFiles = Get-TextFilesList $projectRoot
12+
$allTextFiles = Get-TextFilesList -Root $projectRoot
1313
$unicodeFilesCount = 0
1414
$totalTabsCount = 0
1515
foreach ($textFile in $allTextFiles) {
16-
if (Test-FileUnicode $textFile) {
16+
if (Test-FileUnicode -FileInfo $textFile) {
1717
$unicodeFilesCount++
1818
Write-Warning (
1919
"File $($textFile.FullName) contains 0x00 bytes." +
@@ -24,7 +24,7 @@ BeforeAll {
2424
$unicodeFilesCount | Should -Be 0
2525

2626
$fileName = $textFile.FullName
27-
(Get-Content $fileName -Raw) | Select-String "`t" | Foreach-Object {
27+
(Get-Content -Path $fileName -Raw) | Select-String -Pattern "`t" | Foreach-Object {
2828
Write-Warning (
2929
"There are tabs in $fileName." +
3030
' Use Fixer "Get-TextFilesList `$pwd | ConvertTo-SpaceIndentation".'

tests/MetaFixers.psm1

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ function ConvertTo-UTF8 {
2727
[OutputType([void])]
2828
param(
2929
[Parameter(Mandatory = $true, ValueFromPipeline = $true)]
30+
[ValidateNotNull()]
3031
[System.IO.FileInfo]$FileInfo
3132
)
3233

@@ -56,6 +57,7 @@ function ConvertTo-SpaceIndentation {
5657
[OutputType([void])]
5758
param(
5859
[Parameter(Mandatory = $true, ValueFromPipeline = $true)]
60+
[ValidateNotNull()]
5961
[System.IO.FileInfo]$FileInfo
6062
)
6163

@@ -85,6 +87,7 @@ function Get-TextFilesList {
8587
[OutputType([System.IO.FileInfo])]
8688
param(
8789
[Parameter(Mandatory = $true, ValueFromPipeline = $true)]
90+
[ValidateNotNullOrEmpty()]
8891
[string]$Root
8992
)
9093

@@ -159,10 +162,11 @@ function Get-UnicodeFilesList {
159162
[OutputType([System.IO.FileInfo])]
160163
param(
161164
[Parameter(Mandatory = $true)]
165+
[ValidateNotNullOrEmpty()]
162166
[string]$Root
163167
)
164168

165169
$root | Get-TextFilesList | Where-Object {
166-
Test-FileUnicode $_
170+
Test-FileUnicode -FileInfo $_
167171
}
168172
}

tests/Unit/Private/Invoke-{{Prefix}}Helper.tests.ps1

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,20 +17,20 @@ BeforeDiscovery {
1717
}
1818

1919
# PowerShellBuild outputs to Output/<ModuleName>/<Version>/
20-
$projectRoot = Split-Path -Parent (Split-Path -Parent (Split-Path -Parent $PSScriptRoot))
21-
$sourceManifest = Join-Path $projectRoot "$Env:BHProjectName/$Env:BHProjectName.psd1"
20+
$projectRoot = Split-Path -Path (Split-Path -Path (Split-Path -Path $PSScriptRoot -Parent) -Parent) -Parent
21+
$sourceManifest = Join-Path -Path $projectRoot -ChildPath "$Env:BHProjectName/$Env:BHProjectName.psd1"
2222
$moduleVersion = (Import-PowerShellDataFile -Path $sourceManifest).ModuleVersion
23-
$Env:BHBuildOutput = Join-Path $projectRoot "Output/$Env:BHProjectName/$moduleVersion"
23+
$Env:BHBuildOutput = Join-Path -Path $projectRoot -ChildPath "Output/$Env:BHProjectName/$moduleVersion"
2424
}
2525

2626
BeforeAll {
2727
# Import the module from the build output
2828
$moduleManifestPath = Join-Path -Path $Env:BHBuildOutput -ChildPath "$Env:BHProjectName.psd1"
29-
Get-Module $Env:BHProjectName | Remove-Module -Force -ErrorAction 'Ignore'
29+
Get-Module -Name $Env:BHProjectName | Remove-Module -Force -ErrorAction 'Ignore'
3030
Import-Module -Name $moduleManifestPath -Force -ErrorAction 'Stop'
3131
}
3232

33-
InModuleScope $Env:BHProjectName {
33+
InModuleScope -ModuleName $Env:BHProjectName -ScriptBlock {
3434
Describe 'Invoke-{{Prefix}}Helper' {
3535

3636
Context 'Basic functionality' {

tests/Unit/Public/Get-{{Prefix}}Example.tests.ps1

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,16 @@ BeforeDiscovery {
1717
}
1818

1919
# PowerShellBuild outputs to Output/<ModuleName>/<Version>/
20-
$projectRoot = Split-Path -Parent (Split-Path -Parent (Split-Path -Parent $PSScriptRoot))
21-
$sourceManifest = Join-Path $projectRoot "$Env:BHProjectName/$Env:BHProjectName.psd1"
20+
$projectRoot = Split-Path -Path (Split-Path -Path (Split-Path -Path $PSScriptRoot -Parent) -Parent) -Parent
21+
$sourceManifest = Join-Path -Path $projectRoot -ChildPath "$Env:BHProjectName/$Env:BHProjectName.psd1"
2222
$moduleVersion = (Import-PowerShellDataFile -Path $sourceManifest).ModuleVersion
23-
$Env:BHBuildOutput = Join-Path $projectRoot "Output/$Env:BHProjectName/$moduleVersion"
23+
$Env:BHBuildOutput = Join-Path -Path $projectRoot -ChildPath "Output/$Env:BHProjectName/$moduleVersion"
2424
}
2525

2626
BeforeAll {
2727
# Import the module from the build output
2828
$moduleManifestPath = Join-Path -Path $Env:BHBuildOutput -ChildPath "$Env:BHProjectName.psd1"
29-
Get-Module $Env:BHProjectName | Remove-Module -Force -ErrorAction 'Ignore'
29+
Get-Module -Name $Env:BHProjectName | Remove-Module -Force -ErrorAction 'Ignore'
3030
Import-Module -Name $moduleManifestPath -Force -ErrorAction 'Stop'
3131
}
3232

{{ModuleName}}/Public/Get-{{Prefix}}Example.ps1

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ function Get-{{Prefix}}Example {
3737
)
3838

3939
begin {
40-
Write-Verbose "Starting Get-{{Prefix}}Example"
40+
Write-Verbose 'Starting Get-{{Prefix}}Example'
4141
}
4242

4343
process {
@@ -51,6 +51,6 @@ function Get-{{Prefix}}Example {
5151
}
5252

5353
end {
54-
Write-Verbose "Completed Get-{{Prefix}}Example"
54+
Write-Verbose 'Completed Get-{{Prefix}}Example'
5555
}
5656
}

0 commit comments

Comments
 (0)