diff --git a/src/PSModuleUtils.psd1 b/src/PSModuleUtils.psd1 index 87e4826..d2946a0 100644 --- a/src/PSModuleUtils.psd1 +++ b/src/PSModuleUtils.psd1 @@ -1,6 +1,6 @@ @{ RootModule = 'PSModuleUtils.psm1' - ModuleVersion = '3.1.0' + ModuleVersion = '4.0.0' GUID = '3c63c38f-c32c-4837-a6fa-0b456f4099ce' Author = '' CompanyName = '' diff --git a/src/Public/Invoke-PSModuleAnalyzer.ps1 b/src/Public/Invoke-PSModuleAnalyzer.ps1 index 952d484..dc4c7d7 100644 --- a/src/Public/Invoke-PSModuleAnalyzer.ps1 +++ b/src/Public/Invoke-PSModuleAnalyzer.ps1 @@ -3,7 +3,12 @@ Invokes PSScriptAnalyzer on a directory using a more strict set of rules than default. .DESCRIPTION -Invokes PSScriptAnalyzer on a directory using a more strict set of rules than default. +Invokes PSScriptAnalyzer on a directory using a more strict set of rules than default, and works +around its recursive PSUseCorrectCasing crash by applying that one rule a file at a time. + +Returns diagnostics, like Invoke-ScriptAnalyzer does. Decide what a finding means at the call site: +throw to gate a build, pipe to ConvertTo-SARIF to report one, or pass -EnableExit for a CI step that +should fail on its exit code. .PARAMETER SourceDirectory The directory to analyze. Also accepts a file path or a wildcard such as scripts/*.ps1, which pairs @@ -16,14 +21,15 @@ source checkout and a built module layout. .PARAMETER Fix Whether to fix the issues found. -.PARAMETER NoExit -Returns analyzer diagnostics without exiting the caller when violations are found. Use this when another -command needs to process the diagnostics, such as converting them to SARIF. - .PARAMETER NoRecurse Analyzes only what SourceDirectory itself matches instead of descending into subdirectories. Use with a wildcard to keep a subtree with different rules, such as a tests folder, out of the run. +.PARAMETER EnableExit +Passed through to Invoke-ScriptAnalyzer: asks the host to exit with the diagnostic count once the run +finishes. Suits a CI step that is one analyzer call. It does not stop the caller and the code is +last-writer-wins, so a script analyzing several paths should test the returned diagnostics instead. + .OUTPUTS Microsoft.Windows.PowerShell.ScriptAnalyzer.Generic.DiagnosticRecord @@ -33,6 +39,15 @@ Invoke-PSModuleAnalyzer -SourceDirectory $PWD/src -Fix .EXAMPLE Invoke-PSModuleAnalyzer -SourceDirectory $PWD/scripts/*.ps1 -NoRecurse +.EXAMPLE +$findings = Invoke-PSModuleAnalyzer -SourceDirectory $PWD/tests +if ($findings) { + throw "$($findings.Count) rule violation(s) in tests." +} + +.EXAMPLE +Invoke-PSModuleAnalyzer -SourceDirectory $PWD/src -EnableExit + .NOTES N/A #> @@ -43,8 +58,8 @@ function Invoke-PSModuleAnalyzer { [String]$SourceDirectory = "$PWD/src", [String]$Settings = (Get-PSModuleAnalyzerSettingsPath -CallerScriptRoot $PSScriptRoot), [Switch]$Fix, - [Switch]$NoExit, - [Switch]$NoRecurse + [Switch]$NoRecurse, + [Switch]$EnableExit ) $scriptAnalyzerArgs = @{ @@ -52,7 +67,7 @@ function Invoke-PSModuleAnalyzer { Settings = $Settings Recurse = (-not $NoRecurse) Severity = 'Error', 'Warning', 'Information' - EnableExit = (-not $Fix -and -not $NoExit) + EnableExit = $EnableExit ReportSummary = $true ErrorAction = 'Stop' } diff --git a/tests/Invoke-PSModuleAnalyzer.Tests.ps1 b/tests/Invoke-PSModuleAnalyzer.Tests.ps1 index 71317e0..8304701 100644 --- a/tests/Invoke-PSModuleAnalyzer.Tests.ps1 +++ b/tests/Invoke-PSModuleAnalyzer.Tests.ps1 @@ -52,7 +52,7 @@ Describe 'Unit Tests' -Tag 'Unit' { Invoke-PSModuleAnalyzer -SourceDirectory $TestDrive Should -Invoke Invoke-PSModuleAnalyzerCasingWorkaround -Exactly -Times 1 -ParameterFilter { -not $PSBoundParameters.ContainsKey('Fix') -and - $EnableExit -eq $true -and + $EnableExit -eq $false -and $ReportSummary -eq $true -and $Severity -contains 'Error' -and $Severity -contains 'Warning' -and @@ -71,10 +71,10 @@ Describe 'Unit Tests' -Tag 'Unit' { $ErrorAction -eq 'Stop' } - Invoke-PSModuleAnalyzer -SourceDirectory $TestDrive -NoExit + Invoke-PSModuleAnalyzer -SourceDirectory $TestDrive -EnableExit Should -Invoke Invoke-PSModuleAnalyzerCasingWorkaround -Exactly -Times 1 -ParameterFilter { -not $Fix -and - $EnableExit -eq $false -and + $EnableExit -eq $true -and $ReportSummary -eq $true -and $Severity -contains 'Error' -and $Severity -contains 'Warning' -and @@ -104,14 +104,24 @@ Describe 'Unit Tests' -Tag 'Unit' { "function Get-Top { 'ok' }" | Set-Content -Path "$fixtureDir/Top.ps1" -Encoding utf8 'function Get-Nested { gci }' | Set-Content -Path "$nestedDir/Alias.ps1" -Encoding utf8 - $recursiveFindings = Invoke-PSModuleAnalyzer -SourceDirectory $fixtureDir -NoExit - $topOnlyFindings = Invoke-PSModuleAnalyzer -SourceDirectory "$fixtureDir/*.ps1" -NoRecurse -NoExit + $recursiveFindings = Invoke-PSModuleAnalyzer -SourceDirectory $fixtureDir + $topOnlyFindings = Invoke-PSModuleAnalyzer -SourceDirectory "$fixtureDir/*.ps1" -NoRecurse $recursiveFindings.ScriptName | Should -Contain 'Alias.ps1' $topOnlyFindings.ScriptName | Should -Contain 'Top.ps1' $topOnlyFindings.ScriptName | Should -Not -Contain 'Alias.ps1' } + It 'should hand a finding back to the caller rather than exiting on it' { + $fixtureDir = Join-Path -Path $TestDrive -ChildPath 'DefaultReturnFixture' + New-Item -ItemType Directory -Path $fixtureDir -Force | Out-Null + 'function Get-Aliased { gci }' | Set-Content -Path "$fixtureDir/Aliased.ps1" -Encoding utf8 + + $findings = Invoke-PSModuleAnalyzer -SourceDirectory $fixtureDir + + $findings.RuleName | Should -Contain 'PSAvoidUsingCmdletAliases' + } + It 'should preserve nested parentheses containing function definitions in fix mode' { $fixtureDir = Join-Path -Path $TestDrive -ChildPath 'IndentationFixture' New-Item -ItemType Directory -Path $fixtureDir -Force | Out-Null