#!/usr/bin/env bash # Pre-commit checks for the PowerShell scripts. Run from the repo root. # Needs pwsh on PATH (see the project notes for how it was installed). set -uo pipefail cd "$(dirname "$0")" fail=0 echo "== ASCII only ==" # Windows PowerShell 5.1 reads a BOM-less .ps1 in the system codepage, which # turns any multi-byte character into mojibake - including quote characters # that break string literals mid-script. for f in *.ps1; do if LC_ALL=C grep -nP '[^\x00-\x7F]' "$f" >/dev/null; then echo " FAIL $f contains non-ASCII:" LC_ALL=C grep -nP '[^\x00-\x7F]' "$f" | head -5 fail=1 else echo " ok $f" fi done echo echo "== \$var? in a string ==" # ? is a legal character in an unbraced PowerShell variable name, so "$name?" # looks up a variable called name? and silently renders empty. Use ${name}?. if grep -nP '\$\w+\?' ./*.ps1; then echo " FAIL - wrap those as \${name}? or the text disappears at runtime" fail=1 else echo " ok none found" fi echo echo "== parse + Windows PowerShell 5.1 compatibility ==" pwsh -NoProfile -Command ' $bad = 0 foreach ($f in Get-ChildItem -Filter *.ps1) { $e = $null [System.Management.Automation.Language.Parser]::ParseFile($f.FullName, [ref]$null, [ref]$e) | Out-Null if ($e.Count) { $bad++ Write-Host " FAIL $($f.Name)" $e | ForEach-Object { " line $($_.Extent.StartLineNumber): $($_.Message)" } } else { Write-Host " ok $($f.Name)" } } if (Get-Module -ListAvailable PSScriptAnalyzer) { Import-Module PSScriptAnalyzer $s = @{ Rules = @{ PSUseCompatibleSyntax = @{ Enable = $true; TargetVersions = @("5.1","7.0") } } } $c = Invoke-ScriptAnalyzer -Path . -Recurse -Settings $s -IncludeRule PSUseCompatibleSyntax if ($c) { $bad++; $c | ForEach-Object { " FAIL 5.1: $($_.ScriptName):$($_.Line) $($_.Message)" } } else { Write-Host " ok 5.1 syntax clean" } } else { Write-Host " skip PSScriptAnalyzer not installed" } exit $bad ' || fail=1 echo echo "== JSON templates ==" python3 - <<'PY' || fail=1 import glob, json, sys bad = 0 for f in glob.glob("Entities/**/*.json", recursive=True) + ["settings.json"]: try: json.load(open(f)) print(" ok %s" % f) except Exception as e: print(" FAIL %s: %s" % (f, e)); bad = 1 sys.exit(bad) PY echo if [ "$fail" -eq 0 ]; then echo "ALL CHECKS PASSED"; else echo "CHECKS FAILED"; fi exit $fail