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
42 changes: 42 additions & 0 deletions .github/workflows/validate-powershell.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
name: Validate PowerShell

on:
push:
paths:
- '**/*.ps1'
- 'PSScriptAnalyzerSettings.psd1'
- '.github/workflows/validate-powershell.yml'
pull_request:
paths:
- '**/*.ps1'
- 'PSScriptAnalyzerSettings.psd1'
- '.github/workflows/validate-powershell.yml'

jobs:
lint:
name: PSScriptAnalyzer
runs-on: ubuntu-latest
permissions:
contents: read

steps:
- uses: actions/checkout@v4

- name: Install PSScriptAnalyzer
shell: pwsh
run: |
if (-not (Get-Module -ListAvailable -Name PSScriptAnalyzer)) {
Install-Module -Name PSScriptAnalyzer -Force -SkipPublisherCheck -Scope CurrentUser
}
Import-Module PSScriptAnalyzer

- name: Run PSScriptAnalyzer on all PowerShell scripts
shell: pwsh
run: |
$results = Invoke-ScriptAnalyzer -Path . -Recurse -Settings PSScriptAnalyzerSettings.psd1
if ($results) {
$results | Format-Table -AutoSize
Write-Error "PSScriptAnalyzer found $($results.Count) issue(s). Please fix them before merging."
exit 1
}
Write-Host "PSScriptAnalyzer: No issues found." -ForegroundColor Green
44 changes: 44 additions & 0 deletions PSScriptAnalyzerSettings.psd1
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
@{
ExcludeRules = @(
# Cosmetic only - trailing whitespace does not affect script behaviour
'PSAvoidTrailingWhitespace',

# Write-Host is appropriate in interactive console/profile scripts
'PSAvoidUsingWriteHost',

# Private helper functions in personal scripts are not exported module
# cmdlets, so approved-verb and singular-noun requirements do not apply
'PSUseApprovedVerbs',
'PSUseSingularNouns',

# Invoke-Expression is used for standard install patterns such as the
# Chocolatey bootstrap and oh-my-posh shell initialisation
'PSAvoidUsingInvokeExpression',

# UTF-8 without BOM is the preferred encoding for cross-platform scripts
'PSUseBOMForUnicodeEncodedFile',

# These are standalone scripts and git hooks, not reusable pipeline cmdlets
'PSUseShouldProcessForStateChangingFunctions',
'PSUseProcessBlockForPipelineCommand',

# Script-level variables ($UserBucket etc.) are intentionally shared
# across dot-sourced scripts and are not accidental globals
'PSAvoidGlobalVars',

# False positive: $Filter is used inside a pipeline Where-Object block
# that PSScriptAnalyzer cannot statically trace
'PSReviewUnusedParameter',

# Information level only; [OutputType] declarations are documentation
'PSUseOutputTypeCorrectly',

# Profile.ps1 uses intentionally empty catch blocks for TLS setup and
# mutex cleanup that must not interrupt an interactive shell session
'PSAvoidUsingEmptyCatchBlock',

# Third-party CLI wrappers (choco, scoop) use positional parameters
# by convention; enforcing named params here would be incorrect
'PSAvoidUsingPositionalParameters'
)
}