From ae62818bce1fd7ee73fb6d12e7bbb4d30c9198e5 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 10 Jan 2026 23:44:22 +0000 Subject: [PATCH 1/3] Initial plan From d79e67ca18fbdda619d859c8da46eb57e0ade51a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 10 Jan 2026 23:48:32 +0000 Subject: [PATCH 2/3] fix: pin Pester to specific version 5.7.1 for supply-chain security Co-authored-by: blindzero <13959569+blindzero@users.noreply.github.com> --- tools/Invoke-IdlePesterTests.ps1 | 35 +++++++++++++++++--------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/tools/Invoke-IdlePesterTests.ps1 b/tools/Invoke-IdlePesterTests.ps1 index 7028639..3e71bd1 100644 --- a/tools/Invoke-IdlePesterTests.ps1 +++ b/tools/Invoke-IdlePesterTests.ps1 @@ -38,9 +38,8 @@ Coverage output format supported by Pester. One or more paths to include for coverage (e.g. 'src'). Defaults to 'src' relative to the repository root. -.PARAMETER MinimumPesterVersion -Minimum supported Pester version. The script will install Pester in CurrentUser scope -when missing or below the minimum version. +.PARAMETER PesterVersion +Pinned Pester version to use. Defaults to 5.7.1. .EXAMPLE pwsh -NoProfile -File ./tools/Invoke-IdlePesterTests.ps1 @@ -85,7 +84,7 @@ param( [Parameter()] [ValidateNotNullOrEmpty()] - [version] $MinimumPesterVersion = '5.0.0' + [version] $PesterVersion = '5.7.1' ) Set-StrictMode -Version Latest @@ -146,32 +145,36 @@ function Ensure-Directory { function Ensure-Pester { <# .SYNOPSIS - Ensures a compatible Pester module is installed and imported. + Ensures Pester is installed (pinned version) and imported. .DESCRIPTION - CI runners are ephemeral. If Pester is missing, the script installs it - in CurrentUser scope. Local users can also benefit from auto-install. + CI runners are ephemeral. When missing, we install Pester in CurrentUser scope. + We explicitly pin versions for determinism. + + IMPORTANT: + - We keep this logic self-contained and consistent across local + CI runs. + - We avoid auto-upgrading to newer versions unless the pinned version is changed in code. #> [CmdletBinding()] param( [Parameter(Mandatory)] - [version] $MinimumVersion + [version] $RequiredVersion ) - $pester = Get-Module -ListAvailable -Name Pester | - Sort-Object Version -Descending | + $installed = Get-Module -ListAvailable -Name Pester | + Where-Object { $_.Version -eq $RequiredVersion } | Select-Object -First 1 - if (-not $pester -or $pester.Version -lt $MinimumVersion) { + if (-not $installed) { if (-not (Get-Command -Name Install-Module -ErrorAction SilentlyContinue)) { - throw "Pester >= $MinimumVersion is required, but Install-Module is not available. Install Pester manually and retry." + throw "Pester ($RequiredVersion) is required, but Install-Module is not available. Install Pester manually and retry." } - Write-Host "Installing Pester >= $MinimumVersion (CurrentUser scope)..." - Install-Module -Name Pester -Scope CurrentUser -Force -MinimumVersion $MinimumVersion | Out-Null + Write-Host "Installing Pester ($RequiredVersion) in CurrentUser scope..." + Install-Module -Name Pester -Scope CurrentUser -Force -RequiredVersion $RequiredVersion -AllowClobber | Out-Null } - Import-Module -Name Pester -MinimumVersion $MinimumVersion -Force + Import-Module -Name Pester -RequiredVersion $RequiredVersion -Force } $repoRoot = Resolve-IdleRepoRoot @@ -202,7 +205,7 @@ if ($coverageEnabled) { } } -Ensure-Pester -MinimumVersion $MinimumPesterVersion +Ensure-Pester -RequiredVersion $PesterVersion $config = New-PesterConfiguration $config.Run.Path = $resolvedTestPath From 7818a342290d8e377aaf7f92a3dc9cf6ed0add54 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 10 Jan 2026 23:53:56 +0000 Subject: [PATCH 3/3] refactor: rename Ensure-* functions to Initialize-* to use approved verbs Co-authored-by: blindzero <13959569+blindzero@users.noreply.github.com> --- tools/Invoke-IdlePesterTests.ps1 | 12 ++++++------ tools/Invoke-IdleScriptAnalyzer.ps1 | 14 +++++++------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/tools/Invoke-IdlePesterTests.ps1 b/tools/Invoke-IdlePesterTests.ps1 index 3e71bd1..d37a7a1 100644 --- a/tools/Invoke-IdlePesterTests.ps1 +++ b/tools/Invoke-IdlePesterTests.ps1 @@ -130,7 +130,7 @@ function Get-IdleFullPath { return [System.IO.Path]::GetFullPath((Join-Path -Path $RepoRootPath -ChildPath $Path)) } -function Ensure-Directory { +function Initialize-Directory { [CmdletBinding()] param( [Parameter(Mandatory)] @@ -142,10 +142,10 @@ function Ensure-Directory { } } -function Ensure-Pester { +function Initialize-Pester { <# .SYNOPSIS - Ensures Pester is installed (pinned version) and imported. + Initializes Pester by ensuring it is installed (pinned version) and imported. .DESCRIPTION CI runners are ephemeral. When missing, we install Pester in CurrentUser scope. @@ -190,7 +190,7 @@ $coverageEnabled = $CI.IsPresent -or $EnableCoverage.IsPresent $resolvedTestResultsPath = $null if ($emitTestResults) { $resolvedTestResultsPath = Get-IdleFullPath -RepoRootPath $repoRoot -Path $TestResultsPath - Ensure-Directory -Path (Split-Path -Path $resolvedTestResultsPath -Parent) + Initialize-Directory -Path (Split-Path -Path $resolvedTestResultsPath -Parent) } $resolvedCoverageOutputPath = $null @@ -198,14 +198,14 @@ $resolvedCoveragePaths = @() if ($coverageEnabled) { $resolvedCoverageOutputPath = Get-IdleFullPath -RepoRootPath $repoRoot -Path $CoverageOutputPath - Ensure-Directory -Path (Split-Path -Path $resolvedCoverageOutputPath -Parent) + Initialize-Directory -Path (Split-Path -Path $resolvedCoverageOutputPath -Parent) foreach ($p in $CoveragePath) { $resolvedCoveragePaths += (Get-IdleFullPath -RepoRootPath $repoRoot -Path $p) } } -Ensure-Pester -RequiredVersion $PesterVersion +Initialize-Pester -RequiredVersion $PesterVersion $config = New-PesterConfiguration $config.Run.Path = $resolvedTestPath diff --git a/tools/Invoke-IdleScriptAnalyzer.ps1 b/tools/Invoke-IdleScriptAnalyzer.ps1 index 0b29d1b..b066495 100644 --- a/tools/Invoke-IdleScriptAnalyzer.ps1 +++ b/tools/Invoke-IdleScriptAnalyzer.ps1 @@ -136,7 +136,7 @@ function Get-IdleFullPath { return [System.IO.Path]::GetFullPath((Join-Path -Path $RepoRootPath -ChildPath $Path)) } -function Ensure-Directory { +function Initialize-Directory { [CmdletBinding()] param( [Parameter(Mandatory)] @@ -148,10 +148,10 @@ function Ensure-Directory { } } -function Ensure-Module { +function Initialize-Module { <# .SYNOPSIS - Ensures a module is installed (pinned version) and imported. + Initializes a module by ensuring it is installed (pinned version) and imported. .DESCRIPTION CI runners are ephemeral. When missing, we install the module in CurrentUser scope. @@ -232,7 +232,7 @@ foreach ($p in $Paths) { $resolvedJsonOutputPath = $null if ($CI) { $resolvedJsonOutputPath = Get-IdleFullPath -RepoRootPath $repoRoot -Path $JsonOutputPath - Ensure-Directory -Path (Split-Path -Path $resolvedJsonOutputPath -Parent) + Initialize-Directory -Path (Split-Path -Path $resolvedJsonOutputPath -Parent) } # SARIF is optional: only generate when CI is on (or user explicitly wants it later) @@ -241,12 +241,12 @@ $resolvedSarifOutputPath = $null $emitSarif = $false if ($CI -and $SarifOutputPath) { $resolvedSarifOutputPath = Get-IdleFullPath -RepoRootPath $repoRoot -Path $SarifOutputPath - Ensure-Directory -Path (Split-Path -Path $resolvedSarifOutputPath -Parent) + Initialize-Directory -Path (Split-Path -Path $resolvedSarifOutputPath -Parent) $emitSarif = $true } # Ensure analyzer module is present (pinned). -Ensure-Module -Name 'PSScriptAnalyzer' -RequiredVersion $PSScriptAnalyzerVersion +Initialize-Module -Name 'PSScriptAnalyzer' -RequiredVersion $PSScriptAnalyzerVersion # Run analysis using the repo settings file. # We rely on the settings file for rule selection and severities. @@ -281,7 +281,7 @@ if ($CI -and $resolvedJsonOutputPath) { if ($emitSarif -and $resolvedSarifOutputPath) { # ConvertToSARIF provides the ConvertTo-SARIF cmdlet which accepts -FilePath. # We install it only when SARIF output is requested. - Ensure-Module -Name 'ConvertToSARIF' -RequiredVersion $ConvertToSarifVersion + Initialize-Module -Name 'ConvertToSARIF' -RequiredVersion $ConvertToSarifVersion $convertCommand = Get-Command -Name 'ConvertTo-SARIF' -ErrorAction SilentlyContinue if (-not $convertCommand) {