From 67c73473df8595f65d7c02d5e37e90d67819e59e Mon Sep 17 00:00:00 2001 From: Trent Blackburn Date: Sun, 3 May 2026 21:26:17 -0400 Subject: [PATCH 1/3] fix(build): target staged output for code coverage Pester reports 0% coverage because the coverage globs in build.psake.ps1 point at the source tree (PlexAutomationToolkit/{Public,Private}/*.ps1) while the test files Import-Module from the staged build output (Output///). Pester treats the two paths as different files, so every executed line counts as "missed." Compute the staged path explicitly from the manifest version (read via $Env:BHPSModuleManifest, which BuildHelpers populates before psake runs), and guard against missing env vars so direct Invoke-psake invocations fail fast with an actionable message. Same fix as upstream tablackburn/PowerShellModuleTemplate#19, the template this module was scaffolded from. Co-Authored-By: Claude Opus 4.7 (1M context) --- build.psake.ps1 | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/build.psake.ps1 b/build.psake.ps1 index 1976670..5eb9b16 100644 --- a/build.psake.ps1 +++ b/build.psake.ps1 @@ -21,9 +21,19 @@ properties { $PSBPreference.Test.OutputFile = [IO.Path]::Combine($PSScriptRoot, 'out', 'testResults.xml') $PSBPreference.Test.OutputFormat = 'NUnitXml' $PSBPreference.Test.CodeCoverage.Enabled = $true + # Coverage must target the staged build output, not the source tree — tests + # Import-Module from Output//, so Pester only records hits + # against those paths. $Env:BHBuildOutput points at /BuildOutput at + # properties-evaluation time (PowerShellBuild rewrites it later inside its + # tasks), so we compute the staged path from the manifest version here. + if (-not $Env:BHPSModuleManifest -or -not $Env:BHProjectName) { + throw 'Coverage configuration requires BuildHelpers env vars. Run via ./build.ps1 or call Set-BuildEnvironment first.' + } + $_moduleVersion = (Import-PowerShellDataFile -Path $Env:BHPSModuleManifest).ModuleVersion + $_stagedOutput = [IO.Path]::Combine($PSScriptRoot, 'Output', $Env:BHProjectName, $_moduleVersion) $PSBPreference.Test.CodeCoverage.Files = @( - "$PSScriptRoot/PlexAutomationToolkit/Public/*.ps1" - "$PSScriptRoot/PlexAutomationToolkit/Private/*.ps1" + "$_stagedOutput/Public/*.ps1" + "$_stagedOutput/Private/*.ps1" ) $PSBPreference.Test.CodeCoverage.Threshold = 0 # Threshold enforced by Codecov $PSBPreference.Test.CodeCoverage.OutputFile = [IO.Path]::Combine($PSScriptRoot, 'out', 'codeCoverage.xml') From 385c33ea92f05bbed654286dd45306ac14ac4b34 Mon Sep 17 00:00:00 2001 From: Trent Blackburn Date: Sun, 3 May 2026 23:17:44 -0400 Subject: [PATCH 2/3] refactor(build): drop $_ prefix from helper variable names MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rename $_moduleVersion → $moduleVersion and $_stagedOutput → $stagedOutput to match the upstream template change in tablackburn/PowerShellModuleTemplate. Pure rename, no behavior change. Co-Authored-By: Claude Opus 4.7 (1M context) --- build.psake.ps1 | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/build.psake.ps1 b/build.psake.ps1 index 5eb9b16..defdc08 100644 --- a/build.psake.ps1 +++ b/build.psake.ps1 @@ -29,11 +29,11 @@ properties { if (-not $Env:BHPSModuleManifest -or -not $Env:BHProjectName) { throw 'Coverage configuration requires BuildHelpers env vars. Run via ./build.ps1 or call Set-BuildEnvironment first.' } - $_moduleVersion = (Import-PowerShellDataFile -Path $Env:BHPSModuleManifest).ModuleVersion - $_stagedOutput = [IO.Path]::Combine($PSScriptRoot, 'Output', $Env:BHProjectName, $_moduleVersion) + $moduleVersion = (Import-PowerShellDataFile -Path $Env:BHPSModuleManifest).ModuleVersion + $stagedOutput = [IO.Path]::Combine($PSScriptRoot, 'Output', $Env:BHProjectName, $moduleVersion) $PSBPreference.Test.CodeCoverage.Files = @( - "$_stagedOutput/Public/*.ps1" - "$_stagedOutput/Private/*.ps1" + "$stagedOutput/Public/*.ps1" + "$stagedOutput/Private/*.ps1" ) $PSBPreference.Test.CodeCoverage.Threshold = 0 # Threshold enforced by Codecov $PSBPreference.Test.CodeCoverage.OutputFile = [IO.Path]::Combine($PSScriptRoot, 'out', 'codeCoverage.xml') From 87127e478e37221ceebe35ef735634b05788da37 Mon Sep 17 00:00:00 2001 From: Trent Blackburn Date: Mon, 4 May 2026 20:32:58 -0400 Subject: [PATCH 3/3] fix(tests): bootstrap BuildHelpers env before Invoke-psake in test files --- tests/Help.tests.ps1 | 10 ++++++++++ tests/Manifest.tests.ps1 | 10 ++++++++++ 2 files changed, 20 insertions(+) diff --git a/tests/Help.tests.ps1 b/tests/Help.tests.ps1 index 6e60762..cf7c16c 100644 --- a/tests/Help.tests.ps1 +++ b/tests/Help.tests.ps1 @@ -69,6 +69,11 @@ BeforeDiscovery { If the BHBuildOutput environment variable exists, it is running in a psake build, so do not build the module. #> if ($null -eq $Env:BHBuildOutput) { + # Populate BuildHelpers env vars so build.psake.ps1's properties block has + # the values it needs (BHPSModuleManifest, BHProjectName) — when running + # via ./build.ps1 this happens before psake; running tests in isolation + # bypasses that, so we do it here. + Set-BuildEnvironment -Path (Split-Path -Parent $PSScriptRoot) -Force $buildFilePath = Join-Path -Path $PSScriptRoot -ChildPath '..\build.psake.ps1' $invokePsakeParameters = @{ TaskList = 'Build' @@ -122,6 +127,11 @@ BeforeAll { If the BHBuildOutput environment variable exists, it is running in a psake build, so do not build the module. #> if ($null -eq $Env:BHBuildOutput) { + # Populate BuildHelpers env vars so build.psake.ps1's properties block has + # the values it needs (BHPSModuleManifest, BHProjectName) — when running + # via ./build.ps1 this happens before psake; running tests in isolation + # bypasses that, so we do it here. + Set-BuildEnvironment -Path (Split-Path -Parent $PSScriptRoot) -Force $buildFilePath = Join-Path -Path $PSScriptRoot -ChildPath '..\build.psake.ps1' $invokePsakeParameters = @{ TaskList = 'Build' diff --git a/tests/Manifest.tests.ps1 b/tests/Manifest.tests.ps1 index ed18010..10687fe 100644 --- a/tests/Manifest.tests.ps1 +++ b/tests/Manifest.tests.ps1 @@ -32,6 +32,11 @@ BeforeDiscovery { If the BHBuildOutput environment variable exists, it is running in a psake build, so do not build the module. #> if ($null -eq $Env:BHBuildOutput) { + # Populate BuildHelpers env vars so build.psake.ps1's properties block has + # the values it needs (BHPSModuleManifest, BHProjectName) — when running + # via ./build.ps1 this happens before psake; running tests in isolation + # bypasses that, so we do it here. + Set-BuildEnvironment -Path (Split-Path -Parent $PSScriptRoot) -Force $buildFilePath = Join-Path -Path $PSScriptRoot -ChildPath '..\build.psake.ps1' $invokePsakeParameters = @{ TaskList = 'Build' @@ -65,6 +70,11 @@ BeforeAll { If the BHBuildOutput environment variable exists, it is running in a psake build, so do not build the module. #> if ($null -eq $Env:BHBuildOutput) { + # Populate BuildHelpers env vars so build.psake.ps1's properties block has + # the values it needs (BHPSModuleManifest, BHProjectName) — when running + # via ./build.ps1 this happens before psake; running tests in isolation + # bypasses that, so we do it here. + Set-BuildEnvironment -Path (Split-Path -Parent $PSScriptRoot) -Force $buildFilePath = Join-Path -Path $PSScriptRoot -ChildPath '..\build.psake.ps1' $invokePsakeParameters = @{ TaskList = 'Build'