Context
Invoke-Pester installs the latest Pester regardless of what a module or its tests pin:
# src/init.ps1 and src/exec.ps1
'Pester' | Install-PSResourceWithRetry # no version -> latest
$pesterModule = Get-PSResource -Name Pester | Sort-Object Version -Descending | Select-Object -First 1
The Version and Prerelease inputs exist in action.yml but are not wired into the install β Install-PSResourceWithRetry has no -Version parameter, so the inputs are effectively dead.
Because the installed version is decoupled from any pin, exact pins in tests cannot hold. This caused the 2026-07-05 breakage: test files pinned Pester 5.7.1 via #Requires, the runner installed 5.8.0, and discovery failed with System.IO.FileLoadException: Could not load file or assembly 'Pester, Version=5.7.1.0'. Hard-pinning tests to an exact version does not fix it either β the next Pester release becomes "latest" and the exact pin no longer matches what is installed.
Request
Make the Version input drive the install, supporting the same version limits as a #Requires -Modules hashtable. No auto-resolution from test files.
Version accepts the same constraints as #Requires -Modules @{ ... }:
- exact β
5.8.0 -> RequiredVersion
- minimum β
ModuleVersion-style floor
- range β floor + ceiling (
ModuleVersion + MaximumVersion)
- optional
GUID to pin module identity
- The install uses the spec (
Install-PSResource -Version <nuget-range>), so exactly the specified version(s) are installed and imported β not "latest".
- No auto-resolve: the action does not parse
#Requires from test files to infer a version. The spec is provided explicitly (single source of truth = the workflow / settings input), keeping behavior predictable.
Prerelease is honored.
- Backward compatible: if no
Version is supplied, keep installing latest.
Acceptance criteria
Version: '5.8.0' installs and runs exactly Pester 5.8.0, even when a newer version exists on the Gallery.
- Minimum/range specs install the newest version satisfying the spec.
GUID, when supplied, is validated against the installed module.
Install-PSResourceWithRetry gains -Version (and passes -Prerelease); init.ps1/exec.ps1 pass the resolved spec.
- Consumers that do not set
Version are unaffected.
Why
This is the linchpin of the hard-lock dependency model (PSModule/Process-PSModule#356): a pin only holds if the pinned version is what actually gets installed. Together with Dependabot bumping the pin (pending PowerShell support in Dependabot), it gives reproducible, supply-chain-safe test runs without staleness from over-locking.
Related: the 8 repos hard-locking Pester to 5.8.0 by GUID β PSModule/GitHub#636, PSModule/Context#118, PSModule/Ast#41, PSModule/Dns#18, PSModule/Json#20, PSModule/NerdFonts#83, PSModule/Net#14, PSModule/PSCustomObject#15.
Context
Invoke-Pesterinstalls the latest Pester regardless of what a module or its tests pin:The
VersionandPrereleaseinputs exist inaction.ymlbut are not wired into the install βInstall-PSResourceWithRetryhas no-Versionparameter, so the inputs are effectively dead.Because the installed version is decoupled from any pin, exact pins in tests cannot hold. This caused the 2026-07-05 breakage: test files pinned Pester
5.7.1via#Requires, the runner installed5.8.0, and discovery failed withSystem.IO.FileLoadException: Could not load file or assembly 'Pester, Version=5.7.1.0'. Hard-pinning tests to an exact version does not fix it either β the next Pester release becomes "latest" and the exact pin no longer matches what is installed.Request
Make the
Versioninput drive the install, supporting the same version limits as a#Requires -Moduleshashtable. No auto-resolution from test files.Versionaccepts the same constraints as#Requires -Modules @{ ... }:5.8.0->RequiredVersionModuleVersion-style floorModuleVersion+MaximumVersion)GUIDto pin module identityInstall-PSResource -Version <nuget-range>), so exactly the specified version(s) are installed and imported β not "latest".#Requiresfrom test files to infer a version. The spec is provided explicitly (single source of truth = the workflow / settings input), keeping behavior predictable.Prereleaseis honored.Versionis supplied, keep installing latest.Acceptance criteria
Version: '5.8.0'installs and runs exactly Pester 5.8.0, even when a newer version exists on the Gallery.GUID, when supplied, is validated against the installed module.Install-PSResourceWithRetrygains-Version(and passes-Prerelease);init.ps1/exec.ps1pass the resolved spec.Versionare unaffected.Why
This is the linchpin of the hard-lock dependency model (PSModule/Process-PSModule#356): a pin only holds if the pinned version is what actually gets installed. Together with Dependabot bumping the pin (pending PowerShell support in Dependabot), it gives reproducible, supply-chain-safe test runs without staleness from over-locking.
Related: the 8 repos hard-locking Pester to 5.8.0 by GUID β PSModule/GitHub#636, PSModule/Context#118, PSModule/Ast#41, PSModule/Dns#18, PSModule/Json#20, PSModule/NerdFonts#83, PSModule/Net#14, PSModule/PSCustomObject#15.