Skip to content

Commit 9351b67

Browse files
tablackburnclaude
andcommitted
fix: drop flaky profile-based compatibility analyzer rules
PSUseCompatibleCommands and PSUseCompatibleTypes intermittently threw a NullReferenceException inside Invoke-ScriptAnalyzer on the macOS CI runner, aborting the Analyze task (it passed on the first run, then failed on a re-run with identical settings; ubuntu and windows passed both times). They also produced false positives that required per-function suppressions (Get-ChildItem -CodeSigningCert provider dynamic parameter; Invoke-Pester -Configuration from the required Pester 5+). Keep only PSUseCompatibleSyntax, which catches the actual regression class (PowerShell 7+-only syntax such as the ternary operator), performs no compatibility-profile deserialization, and is not subject to that NRE. The two suppressions are removed as no longer needed. Core-only cmdlet/type usage remains covered by the Windows PowerShell 5.1 import-smoke CI job. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent f7b4878 commit 9351b67

5 files changed

Lines changed: 24 additions & 40 deletions

File tree

CHANGELOG.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,12 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
2424

2525
- Cross-version compatibility guardrails so a PowerShell 7+-only construct cannot
2626
silently break the lowest supported engine again:
27-
- The `PSUseCompatibleSyntax`, `PSUseCompatibleCommands`, and
28-
`PSUseCompatibleTypes` rules are enabled in
27+
- The `PSUseCompatibleSyntax` rule is enabled in
2928
`PowerShellBuild/ScriptAnalyzerSettings.psd1` (targeting Windows PowerShell 5.1
30-
and PowerShell 7), and the `Analyze` build task now fails on any compatibility
31-
violation.
29+
and PowerShell 7), and the `Analyze` build task now fails on a compatibility
30+
violation. It checks the target language version regardless of the engine it
31+
runs under, so a ternary (or other PowerShell 7+-only syntax) is caught even
32+
from `pwsh`.
3233
- A new `Import smoke (Windows PowerShell 5.1)` CI job parses and imports the
3334
module on the real lowest-supported engine.
3435

PowerShellBuild/Public/Get-PSBuildCertificate.ps1

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -88,11 +88,6 @@ function Get-PSBuildCertificate {
8888
'CertificatePasswordEnvVar',
8989
Justification = 'This is not a password in plain text. It is the name of an environment variable that contains the password, which is a common pattern for CI/CD pipelines and secrets management.'
9090
)]
91-
[Diagnostics.CodeAnalysis.SuppressMessageAttribute(
92-
'PSUseCompatibleCommands',
93-
'',
94-
Justification = 'Get-ChildItem -CodeSigningCert is a dynamic parameter supplied by the Certificate (Cert:) provider, not a static parameter of Get-ChildItem, so the static command data used by PSUseCompatibleCommands cannot see it. It is available on both Windows PowerShell 5.1 and PowerShell 7+.'
95-
)]
9691
param(
9792
[ValidateSet('Auto', 'Store', 'Thumbprint', 'EnvVar', 'PfxFile')]
9893
[string]$CertificateSource = 'Auto',

PowerShellBuild/Public/Test-PSBuildPester.ps1

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,6 @@ function Test-PSBuildPester {
3636
Run Pester tests in ./tests and save results to ./out/testResults.xml
3737
#>
3838
[CmdletBinding()]
39-
[Diagnostics.CodeAnalysis.SuppressMessageAttribute(
40-
'PSUseCompatibleCommands',
41-
'',
42-
Justification = 'Invoke-Pester -Configuration is a Pester 5+ parameter. This module requires Pester >= 5.6.1 (see RequiredModules in the manifest) and imports Pester with -MinimumVersion 5.0.0 before use, so the parameter is always available at runtime. The bundled PSUseCompatibleCommands profiles captured an older Pester, producing a false positive on both Windows PowerShell 5.1 and PowerShell 7.'
43-
)]
4439
param(
4540
[parameter(Mandatory)]
4641
[string]$Path,

PowerShellBuild/ScriptAnalyzerSettings.psd1

Lines changed: 13 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -10,29 +10,22 @@
1010
Whitelist = @('task')
1111
}
1212

13-
# Cross-version compatibility guardrails. PowerShellBuild still supports
14-
# Windows PowerShell 5.1 (Desktop) per the manifest, so these rules flag any
15-
# syntax, command, or type that would not work on the lowest supported engine.
16-
# PSUseCompatibleSyntax checks against the target language versions regardless
17-
# of the engine the analyzer runs under, so a PowerShell 7+-only construct (for
18-
# example the ternary operator) is caught even when the analyzer runs from pwsh.
13+
# Cross-version compatibility guardrail. PowerShellBuild still supports Windows
14+
# PowerShell 5.1 (Desktop) per the manifest, so this flags syntax that would not
15+
# parse on the lowest supported engine. PSUseCompatibleSyntax checks against the
16+
# target language versions regardless of the engine the analyzer runs under, so a
17+
# PowerShell 7+-only construct (for example the ternary operator) is caught even
18+
# when the analyzer runs from pwsh.
19+
#
20+
# The profile-based PSUseCompatibleCommands / PSUseCompatibleTypes rules are
21+
# intentionally NOT enabled here: they produced false positives on this codebase
22+
# (provider dynamic parameters and required-module commands) and intermittently
23+
# threw a NullReferenceException inside Invoke-ScriptAnalyzer on some platforms,
24+
# which aborts the whole analysis. Core-only cmdlet/type usage is instead covered
25+
# by the Windows PowerShell 5.1 import-smoke CI job.
1926
PSUseCompatibleSyntax = @{
2027
Enable = $true
2128
TargetVersions = @('5.1', '7.0')
2229
}
23-
PSUseCompatibleCommands = @{
24-
Enable = $true
25-
TargetProfiles = @(
26-
'win-8_x64_10.0.17763.0_5.1.17763.316_x64_4.0.30319.42000_framework'
27-
'win-8_x64_10.0.17763.0_7.0.0_x64_3.1.2_core'
28-
)
29-
}
30-
PSUseCompatibleTypes = @{
31-
Enable = $true
32-
TargetProfiles = @(
33-
'win-8_x64_10.0.17763.0_5.1.17763.316_x64_4.0.30319.42000_framework'
34-
'win-8_x64_10.0.17763.0_7.0.0_x64_3.1.2_core'
35-
)
36-
}
3730
}
3831
}

psakeFile.ps1

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,12 @@ task Analyze -depends Build {
2020
$analysis = Invoke-ScriptAnalyzer -Path $settings.ModuleOutDir -Recurse -Verbose:$false -Settings $analyzerSettings
2121
$errors = $analysis | Where-Object { $_.Severity -eq 'Error' }
2222

23-
# Cross-version compatibility violations (PSUseCompatibleSyntax/Commands/Types) are reported at
24-
# Warning severity, but must always fail the build. A PowerShell 7+-only construct such as the
25-
# ternary operator parses fine under pwsh yet breaks module import on Windows PowerShell 5.1,
26-
# which the manifest still supports. PSUseCompatibleSyntax checks the target language versions
27-
# regardless of the engine the analyzer runs under, so this gate catches such a regression even
28-
# though CI runs the analysis from pwsh.
23+
# Cross-version compatibility violations (PSUseCompatibleSyntax) are reported at Warning
24+
# severity, but must always fail the build. A PowerShell 7+-only construct such as the ternary
25+
# operator parses fine under pwsh yet breaks module import on Windows PowerShell 5.1, which the
26+
# manifest still supports. PSUseCompatibleSyntax checks the target language versions regardless
27+
# of the engine the analyzer runs under, so this gate catches such a regression even though CI
28+
# runs the analysis from pwsh.
2929
$compatibilityIssues = $analysis | Where-Object { $_.RuleName -like 'PSUseCompatible*' }
3030

3131
# Remaining warnings are reported but, per project policy, do not fail the build.

0 commit comments

Comments
 (0)