-
Notifications
You must be signed in to change notification settings - Fork 125
Closed
Labels
good first issueGood for newcomersGood for newcomers
Description
Summary
Wrap main execution logic in all production scripts with consistent try/catch blocks to ensure proper error reporting and exit codes in CI pipelines.
Problem
Most scripts lack top-level error handling, causing:
- Unhandled exceptions to produce verbose stack traces instead of actionable messages
- Inconsistent exit codes when errors occur
- CI pipelines failing without clear indication of what went wrong
Current state audit:
| Script | Has try/catch wrapper | Exit code handling |
|---|---|---|
linting/Invoke-PSScriptAnalyzer.ps1 |
❌ | Partial (exits on specific conditions) |
linting/Invoke-YamlLint.ps1 |
❌ | Partial |
linting/Invoke-LinkLanguageCheck.ps1 |
❌ | ❌ |
linting/Link-Lang-Check.ps1 |
❌ | ❌ |
linting/Validate-MarkdownFrontmatter.ps1 |
❌ | Partial |
linting/Markdown-Link-Check.ps1 |
❌ | Partial |
security/Test-DependencyPinning.ps1 |
❌ | Partial (line 860+) |
security/Test-SHAStaleness.ps1 |
❌ | Partial |
security/Update-ActionSHAPinning.ps1 |
❌ | ❌ |
extension/Package-Extension.ps1 |
❌ | Partial |
extension/Prepare-Extension.ps1 |
❌ | ❌ |
lib/Get-VerifiedDownload.ps1 |
❌ | ❌ |
dev-tools/Generate-PrReference.ps1 |
❌ | ❌ |
Solution
Add a standardized try/catch wrapper pattern to each script's main execution block.
Pattern Template
#region Main Execution
try {
# Existing script logic here
# ...
# Success exit
exit 0
}
catch {
Write-Error "Script failed: $($_.Exception.Message)"
Write-Error "Stack trace: $($_.ScriptStackTrace)"
exit 1
}
#endregionExample: Before (Invoke-LinkLanguageCheck.ps1)
# Run the language check script
$scriptArgs = @{}
if ($ExcludePaths.Count -gt 0) {
$scriptArgs['ExcludePaths'] = $ExcludePaths
}
$jsonOutput = & (Join-Path $PSScriptRoot "Link-Lang-Check.ps1") @scriptArgs 2>&1
try {
$results = $jsonOutput | ConvertFrom-Json
# ... rest of logic
}
catch {
Write-Warning "Could not parse output as JSON: $jsonOutput"
}
# Script ends without explicit exitExample: After (Invoke-LinkLanguageCheck.ps1)
#region Main Execution
try {
# Run the language check script
$scriptArgs = @{}
if ($ExcludePaths.Count -gt 0) {
$scriptArgs['ExcludePaths'] = $ExcludePaths
}
$jsonOutput = & (Join-Path $PSScriptRoot "Link-Lang-Check.ps1") @scriptArgs 2>&1
try {
$results = $jsonOutput | ConvertFrom-Json
# ... rest of logic
}
catch {
Write-Warning "Could not parse output as JSON: $jsonOutput"
}
exit 0
}
catch {
Write-Error "Link language check failed: $($_.Exception.Message)"
if ($env:GITHUB_ACTIONS -eq 'true') {
Write-Output "::error::$($_.Exception.Message)"
}
exit 1
}
#endregionImplementation Tasks
For each of the 13 scripts:
- Identify the main execution block (code after function definitions and module imports)
- Wrap in
try { } catch { }block - Add
#region Main Execution/#endregionmarkers - Ensure explicit
exit 0on success path - Add
exit 1in catch block - Include CI-friendly error output in catch block
Scripts requiring significant refactoring:
scripts/security/Test-DependencyPinning.ps1- Main logic starts around line 825scripts/security/Test-SHAStaleness.ps1- Main logic starts around line 720scripts/security/Update-ActionSHAPinning.ps1- Main logic starts around line 450
Scripts with simpler main blocks:
scripts/linting/Invoke-*.ps1- Main logic is most of the file after importsscripts/extension/*.ps1- Clearly delineated main sections
Validation
Test error handling by introducing intentional failures:
# Test that errors produce exit code 1
./scripts/linting/Invoke-PSScriptAnalyzer.ps1 -ConfigPath "nonexistent.psd1"
$LASTEXITCODE # Should be 1
# Test that success produces exit code 0
./scripts/linting/Invoke-PSScriptAnalyzer.ps1
$LASTEXITCODE # Should be 0Acceptance Criteria
- All 13 production scripts have try/catch wrappers around main execution
- All scripts use
exit 0for success andexit 1for failure - Error messages are concise and actionable (not full stack traces)
- CI-specific error annotations are included where appropriate
-
#region Main Executionmarkers delineate the wrapped code - Existing functionality is preserved (no behavior changes on success path)
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
good first issueGood for newcomersGood for newcomers