From 8ea8982688a5155dbce62709c62040bcb30440dc Mon Sep 17 00:00:00 2001 From: Trent Blackburn Date: Thu, 27 Aug 2026 14:36:32 -0400 Subject: [PATCH 1/2] docs: Align the README settings table with build.properties.ps1 `$PSBPreference.Docs.AlphabeticParamsOrder` was removed in #105 when help generation moved to Microsoft.PowerShell.PlatyPS 1.x, which always sorts parameters alphabetically. The removal was recorded in the changelog and the migration guide, but the README settings table and the `Docs` row in `instructions/repository-specific.instructions.md` still advertised it as a setting a consumer could set. Auditing the rest of the same table against the defaults turned up more of the same. `$PSBPreference.Build.Dependencies` was replaced by the `$PSB{TaskName}Dependency` variables in #72, back in 0.7.0 - it no longer exists in the defaults, and IB.tasks.ps1 now throws a NotSupportedException if a consumer sets it. Four `Test` defaults documented the parameter defaults of `Test-PSBuildPester` rather than the `$PSBPreference` values that actually reach it: `Test.OutputFile` and `Test.CodeCoverage.OutputFile` both default to absolute paths under the project root, `Test.CodeCoverage.Files` defaults to an empty array, and `Test.CodeCoverage.OutputFileFormat` defaults to JaCoCo. Nothing checked the README against the defaults, which is how this survived several releases, so this adds the drift guard next to the one that covers the task files. It resolves every `$PSBPreference` path in the README table against `build.properties.ps1`, allowing the four optional `Compile*` settings that are deliberately absent from the defaults. Only the documented-to-defined direction is asserted; the reverse would fail today on the Sign section, which the README has never covered. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01U1Jhu7fgTRJq7LK5MuKteE --- README.md | 10 +-- .../repository-specific.instructions.md | 2 +- tests/IBTasks.tests.ps1 | 80 ++++++++++++++----- 3 files changed, 67 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index fddd1e2..923463f 100644 --- a/README.md +++ b/README.md @@ -91,7 +91,6 @@ match your environment. | $PSBPreference.General.ModuleVersion | `\` | The version of the module | | $PSBPreference.General.ModuleManifestPath | `$env:BHPSModuleManifest` | Path to the module manifest (PSD1) | | $PSBPreference.Build.OutDir | `$projectRoot/Output` | Output directory when building the module | -| $PSBPreference.Build.Dependencies | 'StageFiles, 'BuildHelp' | Default task dependencies for the `Build` task | | $PSBPreference.Build.ModuleOutDir | `$outDir/$moduleName/$moduleVersion` | `For internal use only. Do not overwrite. Use '$PSBPreference.Build.OutDir' to set output directory` | | $PSBPreference.Build.CompileModule | `$false` | Controls whether to "compile" module into single PSM1 or not | | $PSBPreference.Build.CompileDirectories | `@('Enum', 'Classes', 'Private', 'Public')` | List of directories to "compile" into monolithic PSM1. Only valid when `$PSBPreference.Build.CompileModule` is `$true`. | @@ -103,16 +102,16 @@ match your environment. | $PSBPreference.Build.Exclude | `` | Array of files (regular expressions) to exclude when building module | | $PSBPreference.Test.Enabled | `$true` | Enable/disable Pester tests | | $PSBPreference.Test.RootDir | `$projectRoot/tests` | Directory containing Pester tests | -| $PSBPreference.Test.OutputFile | `$null` | Output file path Pester will save test results to | +| $PSBPreference.Test.OutputFile | `$projectRoot/testResults.xml` | Output file path Pester will save test results to | | $PSBPreference.Test.OutputFormat | `NUnitXml` | Test output format to use when saving Pester test results | | $PSBPreference.Test.ScriptAnalysis.Enabled | `$true` | Enable/disable use of PSScriptAnalyzer to perform script analysis | | $PSBPreference.Test.ScriptAnalysis.FailBuildOnSeverityLevel | `Error` | PSScriptAnalyzer threshold to fail the build on | | $PSBPreference.Test.ScriptAnalysis.SettingsPath | `./ScriptAnalyzerSettings.psd1` | Path to the PSScriptAnalyzer settings file | | $PSBPreference.Test.CodeCoverage.Enabled | `$false` | Enable/disable Pester code coverage reporting | | $PSBPreference.Test.CodeCoverage.Threshold | `.75` | Fail Pester code coverage test if below this threshold | -| $PSBPreference.Test.CodeCoverage.Files | `*.ps1, *.psm1` | Files to perform code coverage analysis on | -| $PSBPreference.Test.CodeCoverage.OutputFile | `coverage.xml` | Output file path (relative to Pester test directory) where Pester will save code coverage results to | -| $PSBPreference.Test.CodeCoverage.OutputFileFormat | `$null` | Test output format to use when saving Pester code coverage results | +| $PSBPreference.Test.CodeCoverage.Files | `@()` | Files to perform code coverage analysis on | +| $PSBPreference.Test.CodeCoverage.OutputFile | `$projectRoot/codeCoverage.xml` | Output file path (relative to Pester test directory) where Pester will save code coverage results to | +| $PSBPreference.Test.CodeCoverage.OutputFileFormat | `JaCoCo` | Test output format to use when saving Pester code coverage results | | $PSBPreference.Test.ImportModule | `$false` | Import module from output directory prior to running Pester tests | | $PSBPreference.Test.SkipRemainingOnFailure | `None` | Skip remaining tests after failure for selected scope. Options are None, Run, Container and Block. | | $PSBPreference.Test.OutputVerbosity | `Detailed` | Set verbosity of output. Options are None, Normal, Detailed and Diagnostic. | @@ -121,7 +120,6 @@ match your environment. | $PSBPreference.Help.ConvertReadMeToAboutHelp | `$false` | Convert project readme into the module about file | | $PSBPreference.Docs.RootDir | `$projectRoot/docs` | Directory PlatyPS markdown documentation will be saved to. Other content in this directory, such as a README or an images folder, is left alone. | | $PSBPreference.Docs.Overwrite | `$false` | Overwrite the markdown files in the docs folder using the comment based help as the source of truth. | -| $PSBPreference.Docs.AlphabeticParamsOrder | `$false` | Order parameters alphabetically by name in PARAMETERS section. There are 5 exceptions: -Confirm, -WhatIf, -IncludeTotalCount, -Skip, and -First parameters will be the last. | | $PSBPreference.Docs.ExcludeDontShow | `$false` | Exclude the parameters marked with `DontShow` in the parameter attribute from the help content. | | $PSBPreference.Docs.UseFullTypeName | `$false` | Indicates that the target document will use a full type name instead of a short name for parameters. | | $PSBPreference.Publish.PSRepository | `PSGallery` | PowerShell repository name to publish | diff --git a/instructions/repository-specific.instructions.md b/instructions/repository-specific.instructions.md index 388e2d8..8d9322b 100644 --- a/instructions/repository-specific.instructions.md +++ b/instructions/repository-specific.instructions.md @@ -72,7 +72,7 @@ Sections: | `Build` | OutDir, ModuleOutDir, CompileModule, CompileDirectories, CopyDirectories, Exclude | | `Test` | Enabled, RootDir, OutputFile/Format, ScriptAnalysis, CodeCoverage, ImportModule, etc. | | `Help` | UpdatableHelpOutDir, DefaultLocale, ConvertReadMeToAboutHelp | -| `Docs` | RootDir, Overwrite, AlphabeticParamsOrder, ExcludeDontShow, UseFullTypeName | +| `Docs` | RootDir, Overwrite, ExcludeDontShow, UseFullTypeName | | `Publish` | PSRepository, PSRepositoryApiKey, PSRepositoryCredential | | `Sign` | Enabled, CertificateSource, CertStoreLocation, Thumbprint, EnvVar/PfxFile sources, TimestampServer, HashAlgorithm, FilesToSign, Catalog | | `Sign.Catalog` | Enabled, Version, FileName | diff --git a/tests/IBTasks.tests.ps1 b/tests/IBTasks.tests.ps1 index 2ceb104..3f10b2f 100644 --- a/tests/IBTasks.tests.ps1 +++ b/tests/IBTasks.tests.ps1 @@ -1,5 +1,26 @@ #requires -module InvokeBuild,Psake +# Shared by both of the drift guards below, so each stays runnable on its own filter. +BeforeAll { + $script:moduleSourcePath = [IO.Path]::Combine( + (Split-Path -Path $PSScriptRoot -Parent), 'PowerShellBuild' + ) + $script:defaultPreference = . ([IO.Path]::Combine($script:moduleSourcePath, 'build.properties.ps1')) + + function script:Test-PreferencePath { + param($Root, [string[]]$Segment) + $node = $Root + foreach ($name in $Segment) { + if ($node -is [System.Collections.IDictionary] -and $node.Contains($name)) { + $node = $node[$name] + } else { + return $false + } + } + $true + } +} + Describe 'Invoke-Build Tasks' { BeforeAll { $manifest = Import-PowerShellDataFile -Path $env:BHPSModuleManifest @@ -54,24 +75,6 @@ Describe 'Settings referenced by the task files' { # task NAME, which cannot see a divergence inside a task body. BeforeAll { - $script:moduleSourcePath = [IO.Path]::Combine( - (Split-Path -Path $PSScriptRoot -Parent), 'PowerShellBuild' - ) - $script:defaultPreference = . ([IO.Path]::Combine($script:moduleSourcePath, 'build.properties.ps1')) - - function script:Test-PreferencePath { - param($Root, [string[]]$Segment) - $node = $Root - foreach ($name in $Segment) { - if ($node -is [System.Collections.IDictionary] -and $node.Contains($name)) { - $node = $node[$name] - } else { - return $false - } - } - $true - } - # Two references are expected not to resolve, both deliberately: # Build.Keys - the hashtable's own Keys property, used to enumerate it # Build.Dependencies - removed from the defaults on purpose; IB.tasks.ps1 reads it @@ -99,3 +102,44 @@ Describe 'Settings referenced by the task files' { $unresolvable -join ', ' | Should -BeNullOrEmpty } } + +Describe 'Settings documented in the README' { + + # The README settings table is what consumers actually read, and until now nothing tied it + # back to the defaults. $PSBPreference.Docs.AlphabeticParamsOrder survived its removal in + # psake/PowerShellBuild#105 there, and $PSBPreference.Build.Dependencies survived being + # replaced by the $PSB{TaskName}Dependency variables in #72, back in 0.7.0. + # + # Only the documented-to-defined direction is asserted. The reverse direction would fail + # today on the whole Sign section, which the README has never covered. + + BeforeAll { + # Documented settings that are deliberately absent from the defaults. Both task files + # forward these to Build-PSBuildModule only when the consumer has added the key, so + # defining them in build.properties.ps1 would inject empty strings into every + # compiled PSM1 instead of leaving the parameter defaults alone. + $script:documentedWithoutDefault = @( + 'Build.CompileHeader' + 'Build.CompileFooter' + 'Build.CompileScriptHeader' + 'Build.CompileScriptFooter' + ) + } + + It 'every setting the README table lists resolves against build.properties.ps1' { + $readMePath = [IO.Path]::Combine((Split-Path -Path $PSScriptRoot -Parent), 'README.md') + $documentedPath = [regex]::Matches( + (Get-Content -Path $readMePath -Raw), + '(?m)^\|\s*\$PSBPreference((?:\.[A-Za-z_][A-Za-z0-9_]*)+)' + ).ForEach({ $_.Groups[1].Value.TrimStart('.') }) | Sort-Object -Unique + + $documentedPath | Should -Not -BeNullOrEmpty -Because 'the regex must still match the table' + + $undefined = $documentedPath.Where({ + $_ -notin $script:documentedWithoutDefault -and + -not (Test-PreferencePath -Root $script:defaultPreference -Segment ($_ -split '\.')) + }) + + $undefined -join ', ' | Should -BeNullOrEmpty + } +} From 2aa6c97f7ac89328866eb1362453324a09cf9d17 Mon Sep 17 00:00:00 2001 From: Trent Blackburn Date: Thu, 27 Aug 2026 14:41:53 -0400 Subject: [PATCH 2/2] docs: Reword the code coverage output file description Correcting `Test.CodeCoverage.OutputFile`'s default to the absolute `$projectRoot/codeCoverage.xml` left the description contradicting the column beside it: a parenthetical claiming the path is relative to the Pester test directory, next to a default that plainly is not relative. The parenthetical was incomplete rather than wrong. `Test-PSBuildPester` does `Push-Location -LiteralPath $Path` into the test directory before assigning `$configuration.CodeCoverage.OutputPath`, so a relative value does resolve against the test directory - but the shipped default is absolute. State both facts instead of only the one that does not describe the default. `Test.OutputFile` has the same absolute default and the same relative-path behaviour, but its README description makes no relativity claim, so it needed no change. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01U1Jhu7fgTRJq7LK5MuKteE --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 923463f..ea7795a 100644 --- a/README.md +++ b/README.md @@ -110,7 +110,7 @@ match your environment. | $PSBPreference.Test.CodeCoverage.Enabled | `$false` | Enable/disable Pester code coverage reporting | | $PSBPreference.Test.CodeCoverage.Threshold | `.75` | Fail Pester code coverage test if below this threshold | | $PSBPreference.Test.CodeCoverage.Files | `@()` | Files to perform code coverage analysis on | -| $PSBPreference.Test.CodeCoverage.OutputFile | `$projectRoot/codeCoverage.xml` | Output file path (relative to Pester test directory) where Pester will save code coverage results to | +| $PSBPreference.Test.CodeCoverage.OutputFile | `$projectRoot/codeCoverage.xml` | Output file path where Pester will save code coverage results to. A relative path resolves against the Pester test directory. | | $PSBPreference.Test.CodeCoverage.OutputFileFormat | `JaCoCo` | Test output format to use when saving Pester code coverage results | | $PSBPreference.Test.ImportModule | `$false` | Import module from output directory prior to running Pester tests | | $PSBPreference.Test.SkipRemainingOnFailure | `None` | Skip remaining tests after failure for selected scope. Options are None, Run, Container and Block. |