Skip to content

Commit d02aa78

Browse files
authored
Enforce Pester version range and improve error handling (#262)
* chore: prepare develop for next prerelease * fix: update project description for clarity and consistency * fix: update MaximumVersion for Pester module in project.json * Bug/260 setting max pester version below 6 (#261) * fix(#260): enforce supported Pester version range and improve error handling - `Invoke-NovaTest`, `Test-NovaBuild`, and `% nova test` now only use Pester versions from `5.7.1` to `5.10.0`, failing with a clear error for unsupported `Pester 6.x`. - Updated documentation to reflect the new Pester version requirements. * fix(#260): improve Pester version handling in Nova test workflows - Reuse already loaded supported Pester 5.x version before switching - Ensure early failure with clear error when unsupported Pester 6.x is present * fix(#260): enhance Nova module validation commands and logging - Introduced new functions for command generation and execution - Improved error handling for validation command failures - Updated logging to capture command execution details * fix(#260): improve run.ps1 script content handling in tests - resolve script path and load content once for efficiency - update test assertions to use loaded script content * fix(#260): improve run.ps1 script content handling in tests - resolve script path and load content once for efficiency - update test assertions to use loaded script content * fix(#260): enhance output handling in integration tests - replace output joining with Get-NovaPublicCommandIntegrationOutputText for better formatting - normalize whitespace in output assertions for consistency * fix(#260): add tests for Get-NovaPesterVersionText and Test-NovaPesterModuleVersionSupported - implement default value handling in Get-NovaPesterVersionText - validate null candidate version in Test-NovaPesterModuleVersionSupported
1 parent aa0a31b commit d02aa78

18 files changed

Lines changed: 776 additions & 134 deletions

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
1515

1616
### Fixed
1717

18+
- `Invoke-NovaTest`, `Test-NovaBuild`, and `% nova test` now resolve and import a supported installed `Pester` version from `5.7.1` through `5.10.0` instead of using an unsupported `Pester 6.x` installation automatically.
19+
- Nova test workflows now fail early with a clear dependency error when only unsupported `Pester 6.x` versions are available.
20+
- Nova test workflows now reuse an already loaded supported `Pester 5.x` version in the current PowerShell session before selecting a different installed version.
21+
- Repository CI no longer trips the `Pester` assembly loader by importing a gallery-installed `NovaModuleTools` module, building the local module, and then switching to another supported `Pester` version in the same session.
22+
1823
### Security
1924

2025
## [3.3.0] - 2026-06-16

README.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
![WorkFlow Status][WorkFlowStatus]
55
[![Keep a Changelog][changelog-badge]][changelog]
66

7-
NovaModuleTools is an enterprise-focused build tool for Agentic Copilot PowerShell module development, repository automation, and maintainable Nova workflows.
7+
NovaModuleTools is an enterprise-focused build tool for PowerShell module development, repository automation, and maintainable Nova workflows.
88

99
This README is the single developer-documentation entry point for the repository.
1010

@@ -298,8 +298,9 @@ Notes:
298298
- if `project.json` sets `Pester.CodeCoverage.CoveragePercentTarget`, `Invoke-NovaTest` fails when the measured coverage percentage is lower than that configured target
299299
- this repository currently enables coverage with a `99` percent target; the template and packaged example
300300
`project.json` files ship the same JaCoCo configuration shape with `Enabled=false` and a `90` percent opt-in target
301-
- make sure `Pester 5.7.1` is available before running `Invoke-NovaTest` or `Test-NovaBuild`
302-
- the published `NovaModuleTools` manifest also declares `Pester 5.7.1`, so installed end-user workflows can still resolve that dependency automatically
301+
- make sure a supported `Pester` version from `5.7.1` through `5.10.0` is available before running `Invoke-NovaTest` or `Test-NovaBuild`
302+
- Nova resolves and imports a compatible installed `Pester 5.x` version for the managed test workflow and does not run tests with `Pester 6.x`
303+
- the published `NovaModuleTools` manifest declares `Pester` with `ModuleVersion = 5.7.1` and `MaximumVersion = 5.10.0`, so installed end-user workflows can still resolve that supported dependency range automatically
303304

304305
### Create a package artifact
305306

@@ -640,7 +641,7 @@ Responsibilities currently covered by the release pipeline include:
640641
- publishing to PowerShell Gallery
641642
- preparing the next prerelease version on `develop`
642643

643-
The workflow now uses `KeepAChangelog` for changelog release moves, creates annotated git tags named directly from the release version, and bootstraps the local PSResourceGet repository store before calling `Publish-NovaModule`. The shared CI installer also installs `Pester 5.7.1` explicitly before it installs prerelease gallery modules so test workflows do not rely on transitive manifest dependency resolution.
644+
The workflow now uses `KeepAChangelog` for changelog release moves, creates annotated git tags named directly from the release version, and bootstraps the local PSResourceGet repository store before calling `Publish-NovaModule`. The shared CI installer also installs `Pester 5.7.1` explicitly before it installs prerelease gallery modules so test workflows stay on Nova's supported `Pester 5.x` range and do not rely on transitive manifest dependency resolution.
644645

645646
### Where NovaModuleTools cmdlets fit
646647

RELEASE_NOTE.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ This file summarizes the release notes for NovaModuleTools. **UNRELEASED** chang
1414

1515
### Fixed
1616

17+
- `Invoke-NovaTest`, `Test-NovaBuild`, and `% nova test` now stay on Nova's supported `Pester 5.x` range and stop with a clear error instead of trying to run with an installed `Pester 6.x` version.
18+
1719
### Security
1820

1921
## [3.3.0] - 2026-06-16

docs/NovaModuleTools/en-US/Invoke-NovaTest.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ PS> Invoke-NovaTest [[-TagFilter] <string[]>] [[-ExcludeTagFilter] <string[]>]
3232

3333
`Invoke-NovaTest` reads the Pester configuration from `project.json`, discovers the repository unit-test files, and runs the managed Nova test workflow without rebuilding the project first.
3434

35+
Nova resolves a supported installed `Pester` version from `5.7.1` through `5.10.0` for the managed test workflow and stops with a clear dependency error when only unsupported `Pester 6.x` versions are available.
36+
3537
The unit-test workflow writes NUnit XML to `artifacts/UnitTestResults.xml`.
3638

3739
When `Pester.CodeCoverage.Enabled` is `true`, Nova also writes JaCoCo coverage to `artifacts/coverage.xml` and fails the run when the measured percentage is lower than `Pester.CodeCoverage.CoveragePercentTarget`.

docs/NovaModuleTools/en-US/Test-NovaBuild.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,13 @@ PS> Test-NovaBuild [[-TagFilter] <string[]>] [[-ExcludeTagFilter] <string[]>]
3131

3232
`Test-NovaBuild` reads the Pester configuration from `project.json`, discovers the build-validation integration tests for the current project, and runs the managed Nova test workflow against the built-module validation surface.
3333

34+
Nova resolves a supported installed `Pester` version from `5.7.1` through `5.10.0` for the managed test workflow and stops with a clear dependency error when only unsupported `Pester 6.x` versions are available.
35+
3436
This build-validation flow writes NUnit XML to `artifacts/TestResults.xml`.
3537

3638
Unlike `Invoke-NovaTest`, this command does not enforce source-coverage targets. Use `Invoke-NovaTest` for the unit-test and code-coverage workflow, and use `Test-NovaBuild` when you need build-validation integration coverage that reflects the built module path.
3739

38-
If the current project does not contain any `*.Integration.Tests.ps1` files, `Test-NovaBuild` stops with a Nova-native error that explains the expected naming and reminds you to use `Invoke-NovaTest` for unit tests.
40+
If the current project does not contain any `*.Integration.Tests.ps1` files, `Test-NovaBuild` writes an actionable warning that explains the expected naming and reminds you to use `Invoke-NovaTest` for unit tests.
3941

4042
`-OverrideWarning` lets the nested build-validation flow continue even if the `src/public` layout guard reports zero or multiple top-level functions in a public file.
4143

@@ -271,5 +273,5 @@ Returns the Pester result object from the managed build-validation run.
271273

272274
## RELATED LINKS
273275

274-
[Invoke-NovaTest](Invoke-NovaTest.md)
275-
[Invoke-NovaBuild](Invoke-NovaBuild.md)
276+
- [Invoke-NovaTest](./Invoke-NovaTest.md)
277+
- [Invoke-NovaBuild](./Invoke-NovaBuild.md)

project.json

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"ProjectName": "NovaModuleTools",
3-
"Description": "NovaModuleTools is an enterprise-focused build tool for Agentic Copilot PowerShell module development, with a strong emphasis on structure, maintainability, and automated CI/CD pipelines.",
4-
"Version": "3.3.0",
3+
"Description": "NovaModuleTools is an enterprise-focused build tool for PowerShell module development, with a strong emphasis on structure, maintainability, and build for automated CI/CD pipelines.",
4+
"Version": "3.3.1-preview",
55
"Preamble": [
66
"Set-StrictMode -Version Latest",
77
"$ErrorActionPreference = 'Stop'"
@@ -14,7 +14,8 @@
1414
"RequiredModules": [
1515
{
1616
"ModuleName": "Pester",
17-
"ModuleVersion": "5.7.1"
17+
"ModuleVersion": "5.7.1",
18+
"MaximumVersion": "5.10.0"
1819
},
1920
{
2021
"ModuleName": "Microsoft.PowerShell.PlatyPS",

scripts/build/ci/Install-CiPowerShellModules.ps1

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ function Get-CiModuleInstallOption {
1616
if ($Name -eq 'Pester') {
1717
return [pscustomobject]@{
1818
RequiredVersion = '5.7.1'
19+
MaximumVersion = '5.10.0'
1920
AllowPrerelease = $false
2021
}
2122
}

scripts/build/ci/Invoke-NovaModuleToolsCI.ps1

Lines changed: 42 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -16,29 +16,58 @@ function Copy-NovaModuleToolsArtifactIfPresent {
1616
}
1717
}
1818

19+
function ConvertTo-NovaSingleQuotedPowerShellLiteral {
20+
param(
21+
[Parameter(Mandatory)][string]$Value
22+
)
23+
24+
return "'$($Value.Replace("'", "''") )'"
25+
}
26+
27+
function Get-NovaModuleToolsValidationCommand {
28+
param(
29+
[Parameter(Mandatory)][string]$BuiltModulePath,
30+
[Parameter(Mandatory)][string]$CommandName,
31+
[string[]]$ExcludeTag = @()
32+
)
33+
34+
$commandLine = $CommandName
35+
if (@($ExcludeTag).Count -gt 0) {
36+
$excludeTagLiteral = @($ExcludeTag | ForEach-Object {ConvertTo-NovaSingleQuotedPowerShellLiteral -Value ([string]$_)}) -join ', '
37+
$commandLine += " -ExcludeTagFilter @($excludeTagLiteral)"
38+
}
39+
40+
return "Import-Module $( ConvertTo-NovaSingleQuotedPowerShellLiteral -Value $BuiltModulePath ) -Force -ErrorAction Stop; $commandLine"
41+
}
42+
43+
function Invoke-NovaModuleToolsFreshValidationCommand {
44+
param(
45+
[Parameter(Mandatory)][string]$Command
46+
)
47+
48+
& pwsh -NoLogo -NoProfile -Command $Command
49+
if ($LASTEXITCODE -ne 0) {
50+
throw "Validation command failed: $Command"
51+
}
52+
}
53+
1954
$repoRoot = (Resolve-Path -LiteralPath (Join-Path $PSScriptRoot '..' '..' '..')).Path
2055
Set-Location $repoRoot
2156
New-Item -ItemType Directory -Path $OutputDirectory -Force | Out-Null
2257

2358
Import-Module NovaModuleTools -ErrorAction Stop
2459

25-
Invoke-NovaBuild
26-
27-
$projectInfo = Get-NovaProjectInfo
28-
$builtModulePath = $projectInfo.OutputModuleDir
29-
Remove-Module $projectInfo.ProjectName -ErrorAction SilentlyContinue
30-
Import-Module $builtModulePath -Force
3160
$projectInfo = Get-NovaProjectInfo
61+
Invoke-NovaBuild
62+
$builtModulePath = Join-Path $projectInfo.OutputModuleDir "$( $projectInfo.ProjectName ).psd1"
3263

3364
$novaModuleToolsTestFailed = $false
3465
try {
35-
if (@($ExcludeTag).Count -gt 0) {
36-
Invoke-NovaTest -ExcludeTagFilter $ExcludeTag
37-
Test-NovaBuild -ExcludeTagFilter $ExcludeTag
38-
} else {
39-
Invoke-NovaTest
40-
Test-NovaBuild
41-
}
66+
$unitTestCommand = Get-NovaModuleToolsValidationCommand -BuiltModulePath $builtModulePath -CommandName 'Invoke-NovaTest' -ExcludeTag $ExcludeTag
67+
Invoke-NovaModuleToolsFreshValidationCommand -Command $unitTestCommand
68+
69+
$buildValidationCommand = Get-NovaModuleToolsValidationCommand -BuiltModulePath $builtModulePath -CommandName 'Test-NovaBuild' -ExcludeTag $ExcludeTag
70+
Invoke-NovaModuleToolsFreshValidationCommand -Command $buildValidationCommand
4271
} catch {
4372
$novaModuleToolsTestFailed = $true
4473
Write-Warning "Nova test workflow failed: $( $_.Exception.Message )"

0 commit comments

Comments
 (0)