Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,12 @@ customize rule selection, severity filtering, and custom rule inclusion.
| `SettingsFilePath` | The path to the settings file. | false | `.github/linters/.powershell-psscriptanalyzer.psd1` |
| `Debug` | Enable debug output. | false | `'false'` |
| `Verbose` | Enable verbose output. | false | `'false'` |
| `Version` | Specifies the exact version of the GitHub module to install. | false | |
| `Prerelease` | Allow prerelease versions if available. | false | `'false'` |
| `Version` | Specifies the version of the PSScriptAnalyzer module to install (NuGet range). | false | |
| `Prerelease` | Allow prerelease versions of the PSScriptAnalyzer module if available. | false | `'false'` |
| `PesterVersion` | Specifies the version of the Pester module to install (NuGet range). | false | |
| `PesterPrerelease` | Allow prerelease versions of the Pester module if available. | false | `'false'` |
| `GitHubVersion` | Specifies the version of the GitHub module to install (NuGet range). | false | |
| `GitHubPrerelease` | Allow prerelease versions of the GitHub module if available. | false | `'false'` |
| `WorkingDirectory` | The working directory where the script runs. | false | `'.'` |
| `ReportAsJson` | Output generated reports in JSON format in addition to the configured format. | false | `'true'` |
| `Notice_Mode` | Controls when to show notices for test completion. | false | `'Failed'` |
Expand Down
39 changes: 32 additions & 7 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,30 @@ inputs:
required: false
default: 'false'
Version:
description: Specifies the version of the GitHub module to be installed. The value must be an exact version.
description: |
Specifies the version of the PSScriptAnalyzer module to install, using NuGet version-range syntax (for example '[1.0.0, 2.0.0)').
When empty, the latest available version is installed.
required: false
Prerelease:
description: Allow prerelease versions if available.
description: Allow prerelease versions of the PSScriptAnalyzer module if available.
required: false
default: 'false'
PesterVersion:
description: |
Specifies the version of the Pester module to install, using NuGet version-range syntax (for example '[6.0.0,7.0.0)').
When empty, the latest available version is installed.
required: false
PesterPrerelease:
description: Allow prerelease versions of the Pester module if available.
required: false
default: 'false'
GitHubVersion:
description: |
Specifies the version of the GitHub module to install, using NuGet version-range syntax (for example '[1.2.0, 2.0.0)').
When empty, the latest available version is installed.
required: false
GitHubPrerelease:
description: Allow prerelease versions of the GitHub module if available.
required: false
default: 'false'
WorkingDirectory:
Expand Down Expand Up @@ -255,24 +275,29 @@ runs:
PSMODULE_INVOKE_SCRIPTANALYZER_INPUT_SettingsFilePath: ${{ inputs.SettingsFilePath }}
with:
Debug: ${{ inputs.Debug }}
Prerelease: ${{ inputs.Prerelease }}
Prerelease: ${{ inputs.GitHubPrerelease }}
Verbose: ${{ inputs.Verbose }}
Version: ${{ inputs.Version }}
Version: ${{ inputs.GitHubVersion }}
WorkingDirectory: ${{ inputs.WorkingDirectory }}
Script: ${{ github.action_path }}/src/main.ps1

- name: Invoke-Pester
uses: PSModule/Invoke-Pester@abddf7bef0d0614d7ca322036af6a06ee0fb4d44 # v4.2.4
uses: PSModule/Invoke-Pester@4ff33199141fdf22568990b6107fe3148ae93a1c # v5.1.0
id: test
env:
SettingsFilePath: ${{ fromJson(steps.paths.outputs.result).SettingsFilePath }}
PSMODULE_INVOKE_SCRIPTANALYZER_INPUT_Version: ${{ inputs.Version }}
PSMODULE_INVOKE_SCRIPTANALYZER_INPUT_Prerelease: ${{ inputs.Prerelease }}
with:
Debug: ${{ inputs.Debug }}
Prerelease: ${{ inputs.Prerelease }}
GitHubPrerelease: ${{ inputs.GitHubPrerelease }}
GitHubVersion: ${{ inputs.GitHubVersion }}
Prerelease: ${{ inputs.PesterPrerelease }}
Verbose: ${{ inputs.Verbose }}
Version: ${{ inputs.Version }}
Version: ${{ inputs.PesterVersion }}
WorkingDirectory: ${{ inputs.WorkingDirectory }}
TestResult_TestSuiteName: ${{ inputs.TestResult_TestSuiteName }}
Prescript: ${{ github.action_path }}/src/Install-PSScriptAnalyzer.ps1
Path: ${{ github.action_path }}/src/tests/PSScriptAnalyzer
Run_Path: ${{ fromJson(steps.paths.outputs.result).CodePath }}
ReportAsJson: ${{ inputs.ReportAsJson }}
Expand Down
75 changes: 75 additions & 0 deletions src/Install-PSScriptAnalyzer.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
ο»Ώ<#
.SYNOPSIS
Ensures the requested PSScriptAnalyzer version is the only one installed and loaded.

.DESCRIPTION
Runs as the Invoke-Pester prescript, in the same process as the analyzer test run. It installs the
PSScriptAnalyzer version selected through the action's Version/Prerelease inputs (retrying transient
PSGallery failures), removes any other PSScriptAnalyzer version from the session, and imports the chosen
version into the global session state. This guarantees the tests use the selected version instead of
PowerShell auto-loading whatever copy happens to be preinstalled on the runner.
#>

[CmdletBinding()]
param()

$moduleName = 'PSScriptAnalyzer'
$version = $env:PSMODULE_INVOKE_SCRIPTANALYZER_INPUT_Version
$prerelease = $env:PSMODULE_INVOKE_SCRIPTANALYZER_INPUT_Prerelease -eq 'true'

$installParams = @{
Name = $moduleName
Repository = 'PSGallery'
TrustRepository = $true
PassThru = $true
WarningAction = 'SilentlyContinue'
}
if (-not [string]::IsNullOrWhiteSpace($version)) {
$installParams['Version'] = $version
}
if ($prerelease) {
$installParams['Prerelease'] = $true
}

$label = [string]::IsNullOrWhiteSpace($version) ? $moduleName : "$moduleName $version"
Write-Host "Installing module: $label"

$installed = $null
$retryCount = 5
$retryDelay = 10
for ($i = 0; $i -lt $retryCount; $i++) {
try {
$installed = Install-PSResource @installParams
break
} catch {
Write-Warning "Installation of $moduleName failed with error: $_"
if ($i -eq $retryCount - 1) {
throw
}
Write-Warning "Retrying in $retryDelay seconds..."
Start-Sleep -Seconds $retryDelay
}
}

# Resolve the exact version to load. Prefer what was just installed; if the resource was already
# present, Install-PSResource returns nothing, so fall back to the newest installed version that
# satisfies the requested constraint.
$resolved = $installed | Where-Object { $_.Name -eq $moduleName } | Sort-Object Version -Descending | Select-Object -First 1
if (-not $resolved) {
$getParams = @{ Name = $moduleName; Verbose = $false; ErrorAction = 'SilentlyContinue' }
if (-not [string]::IsNullOrWhiteSpace($version)) {
$getParams['Version'] = $version
}
$resolved = Get-InstalledPSResource @getParams | Sort-Object Version -Descending | Select-Object -First 1
}
if (-not $resolved) {
throw "No installed '$moduleName' version satisfies constraint '$version'."
}

# Remove any already-loaded versions so only the chosen one remains, then import that exact version
# into the global session state used by the Pester run.
Write-Host "Removing any loaded '$moduleName' module from the session"
Remove-Module -Name $moduleName -Force -ErrorAction SilentlyContinue

Write-Host "Importing module: $moduleName $($resolved.Version)"
Import-Module -Name $moduleName -RequiredVersion $resolved.Version -Force -Global
Loading