Public/Linting.ps1
|
# PSSnips — Snippet linting via PSScriptAnalyzer (Invoke-SnipLint, Test-SnipLint). function Invoke-SnipLint { <# .SYNOPSIS Runs PSScriptAnalyzer on a snippet and displays diagnostics. .DESCRIPTION Invokes PSScriptAnalyzer against the snippet file identified by Name. Only applicable to PowerShell snippets (.ps1, .psm1, .psd1). Results are displayed as a formatted table showing Line, Column, Severity, RuleName, and Message. Returns the diagnostic objects for pipeline use. .PARAMETER Name The snippet name to analyse. .PARAMETER Severity Filter diagnostics by severity. Defaults to Error, Warning, Information. .PARAMETER IncludeRule Pass-through to Invoke-ScriptAnalyzer. Specifies rules to include. .PARAMETER ExcludeRule Pass-through to Invoke-ScriptAnalyzer. Specifies rules to exclude. .EXAMPLE Invoke-SnipLint deploy-app Runs all default PSScriptAnalyzer rules against the 'deploy-app' snippet. .EXAMPLE Invoke-SnipLint deploy-app -Severity Error,Warning Reports only Error and Warning findings. .INPUTS None. .OUTPUTS Microsoft.Windows.PowerShell.ScriptAnalyzer.Generic.DiagnosticRecord #> [CmdletBinding()] [OutputType('Microsoft.Windows.PowerShell.ScriptAnalyzer.Generic.DiagnosticRecord')] param( [Parameter(Mandatory, Position=0)] [ValidateNotNullOrEmpty()] [string]$Name, [Parameter()] [ValidateSet('Error','Warning','Information','ParseError')] [string[]]$Severity = @('Error','Warning','Information'), [Parameter()] [string[]]$IncludeRule = @(), [Parameter()] [string[]]$ExcludeRule = @() ) script:InitEnv $path = script:FindFile -Name $Name if (-not $path -or -not (Test-Path $path)) { Write-Error "Snippet '$Name' not found." -ErrorAction Continue; return } $ext = [System.IO.Path]::GetExtension($path).TrimStart('.').ToLower() if ($ext -notin @('ps1','psm1','psd1')) { script:Out-Warn "Lint is only available for PowerShell snippets (.ps1, .psm1, .psd1). Got .$ext." return } if (-not (Get-Command Invoke-ScriptAnalyzer -ErrorAction SilentlyContinue)) { script:Out-Warn 'PSScriptAnalyzer is not installed. Install it with: Install-Module PSScriptAnalyzer' return } $saParams = @{ Path = $path; Severity = $Severity } if ($IncludeRule.Count -gt 0) { $saParams['IncludeRule'] = $IncludeRule } if ($ExcludeRule.Count -gt 0) { $saParams['ExcludeRule'] = $ExcludeRule } $results = Invoke-ScriptAnalyzer @saParams if (-not $results -or $results.Count -eq 0) { script:Out-OK "No issues found in '$Name'." return } script:Out-Warn ("Found {0} issue(s) in '{1}':" -f $results.Count, $Name) $results | Select-Object Line,Column,Severity,RuleName,Message | Format-Table -AutoSize | Out-String | Write-Host return $results } function Test-SnipLint { <# .SYNOPSIS Tests a snippet with PSScriptAnalyzer and returns pass/fail. .DESCRIPTION Runs PSScriptAnalyzer on the named snippet. Returns $true if no issues at or above the specified severity are found, $false otherwise. Only applicable to PowerShell snippets (.ps1, .psm1, .psd1). .PARAMETER Name The snippet name to test. .PARAMETER Severity Severity levels to treat as failures. Defaults to Error, Warning. .EXAMPLE if (-not (Test-SnipLint deploy-app)) { throw 'Snippet has PSSA violations' } .EXAMPLE Test-SnipLint deploy-app -Severity Error Returns $true only if no Error-severity findings exist. .INPUTS None. .OUTPUTS System.Boolean #> [CmdletBinding()] [OutputType([bool])] param( [Parameter(Mandatory, Position=0)] [ValidateNotNullOrEmpty()] [string]$Name, [Parameter()] [ValidateSet('Error','Warning','Information','ParseError')] [string[]]$Severity = @('Error','Warning') ) script:InitEnv $path = script:FindFile -Name $Name if (-not $path -or -not (Test-Path $path)) { Write-Error "Snippet '$Name' not found." -ErrorAction Continue; return $false } $ext = [System.IO.Path]::GetExtension($path).TrimStart('.').ToLower() if ($ext -notin @('ps1','psm1','psd1')) { script:Out-Warn "Lint is only available for PowerShell snippets (.ps1, .psm1, .psd1). Got .$ext." return $false } if (-not (Get-Command Invoke-ScriptAnalyzer -ErrorAction SilentlyContinue)) { script:Out-Warn 'PSScriptAnalyzer is not installed. Install it with: Install-Module PSScriptAnalyzer' return $false } $saParams = @{ Path = $path; Severity = $Severity } $results = Invoke-ScriptAnalyzer @saParams $passed = (-not $results -or $results.Count -eq 0) if ($passed) { script:Out-OK "Test-SnipLint '$Name': PASSED" } else { script:Out-Warn ("Test-SnipLint '$Name': {0} issue(s) found (Severity: {1})" -f $results.Count, ($Severity -join ',')) } return $passed } |