Skip to content

πŸš€ [Feature]: Install the pinned Pester version β€” support #Requires-style version constraints on the Version inputΒ #68

Description

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions