From 06c85f47b7526d1b5f993de67b930f7b322b1c95 Mon Sep 17 00:00:00 2001 From: dmang-dev Date: Wed, 1 Jul 2026 09:24:09 -0700 Subject: [PATCH 1/3] ci: add fast build-free lint gate for PRs and pushes to main The only existing workflow (build-libraries.yml) is manual-dispatch-only, so PRs and merges got zero automated checks. Add a CI workflow that lints the file types that actually change here and have broken the pipeline before: - shellcheck on tracked *.sh - actionlint on .github/workflows (also shellchecks run: blocks) - PSScriptAnalyzer on *.ps1 (fails on Error-level findings) Runs in ~1-2 min on ubuntu, read-only token, cancels superseded runs. The heavy ~90-min toolchain build stays on manual dispatch by design. Co-Authored-By: Claude Opus 4.8 --- .github/workflows/ci.yml | 76 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 .github/workflows/ci.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..1f50c56 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,76 @@ +name: CI + +# Fast, build-free gate for every PR and every push to main. +# +# The heavy toolchain build lives in build-libraries.yml (manual dispatch, +# ~90 min) and is deliberately NOT run per-commit. This workflow only lints +# the file types that actually change in this repo and that have historically +# broken the release pipeline — workflow YAML, shell scripts, and the +# PowerShell bootstrap — so a PR gets real signal in ~1-2 min without building +# anything. No secrets, read-only token. + +on: + pull_request: + push: + branches: [main] + workflow_dispatch: + +permissions: + contents: read + +# A newer push to the same ref cancels an in-flight run — no point linting a +# commit that's already been superseded. +concurrency: + group: ci-${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + lint: + name: workflows + shell + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v6 + + # shellcheck ships preinstalled on the ubuntu-24.04 image. Lint every + # tracked *.sh (the vendored upstream clones are gitignored and absent in + # a fresh checkout, so this only hits our own scripts). --severity=warning + # skips pure style nits but still catches real bugs (unquoted expansions, + # missing `cd ||`, etc.). + - name: shellcheck (tracked *.sh) + run: | + shellcheck --version + mapfile -t scripts < <(git ls-files '*.sh') + printf 'linting: %s\n' "${scripts[@]}" + shellcheck --severity=warning "${scripts[@]}" + + # actionlint validates workflow YAML: expression syntax, bad `if:`, + # deprecated runner/label usage, matrix mistakes — the class of bug that + # silently broke this pipeline before. With shellcheck on PATH it also + # lints every `run:` block. Installed via `go install` (Go is preinstalled + # on the image) pinned to a tag and checksum-verified through the Go + # module proxy — no `curl | bash`. + - name: actionlint (.github/workflows) + run: | + go install github.com/rhysd/actionlint/cmd/actionlint@v1.7.12 + "$(go env GOPATH)/bin/actionlint" -color + + powershell: + name: powershell + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v6 + + # PowerShell Core is preinstalled on the ubuntu image. Gate on Error-level + # findings (parse errors, real defects); report Warnings without failing + # so a first run doesn't wall on style. Ratchet to include Warning later + # once bootstrap-windows.ps1 is warning-clean. + - name: PSScriptAnalyzer (*.ps1) + shell: pwsh + run: | + Set-PSRepository PSGallery -InstallationPolicy Trusted + Install-Module PSScriptAnalyzer -Scope CurrentUser -Force + $issues = @(Invoke-ScriptAnalyzer -Path . -Recurse -Severity Error,Warning) + if ($issues.Count) { $issues | Format-Table -AutoSize | Out-String | Write-Host } + $errors = @($issues | Where-Object { $_.Severity -eq 'Error' }) + Write-Host "PSScriptAnalyzer: $($errors.Count) error(s), $($issues.Count) total finding(s)" + if ($errors.Count -gt 0) { exit 1 } From f289ffc681a3ab6173033e50a8dd3cf1f194d17e Mon Sep 17 00:00:00 2001 From: dmang-dev Date: Wed, 1 Jul 2026 09:28:17 -0700 Subject: [PATCH 2/3] ci: split lint into independent jobs; fix shellcheck findings First run of the new gate flagged 3 shellcheck warnings in tools/build-library-bundle.sh: SC2209 (quote the pkg_for[] string values) and two SC2154 false positives (source[]/sha256sums[] come from the sourced PSPBUILD). Quote the package-name map and annotate the two PKGBUILD-derived arrays with disable directives. Split ci.yml into three independent jobs (shellcheck / actionlint / powershell) so each linter reports even when another fails, instead of fail-fast hiding actionlint behind a shellcheck failure. Co-Authored-By: Claude Opus 4.8 --- .github/workflows/ci.yml | 13 +++++++++---- tools/build-library-bundle.sh | 26 +++++++++++++++----------- 2 files changed, 24 insertions(+), 15 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1f50c56..f82d6e0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -8,6 +8,8 @@ name: CI # broken the release pipeline — workflow YAML, shell scripts, and the # PowerShell bootstrap — so a PR gets real signal in ~1-2 min without building # anything. No secrets, read-only token. +# +# Three independent jobs so each linter reports even if another fails. on: pull_request: @@ -25,12 +27,11 @@ concurrency: cancel-in-progress: true jobs: - lint: - name: workflows + shell + shellcheck: + name: shellcheck runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v6 - # shellcheck ships preinstalled on the ubuntu-24.04 image. Lint every # tracked *.sh (the vendored upstream clones are gitignored and absent in # a fresh checkout, so this only hits our own scripts). --severity=warning @@ -43,6 +44,11 @@ jobs: printf 'linting: %s\n' "${scripts[@]}" shellcheck --severity=warning "${scripts[@]}" + actionlint: + name: actionlint + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v6 # actionlint validates workflow YAML: expression syntax, bad `if:`, # deprecated runner/label usage, matrix mistakes — the class of bug that # silently broke this pipeline before. With shellcheck on PATH it also @@ -59,7 +65,6 @@ jobs: runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v6 - # PowerShell Core is preinstalled on the ubuntu image. Gate on Error-level # findings (parse errors, real defects); report Warnings without failing # so a first run doesn't wall on style. Ratchet to include Warning later diff --git a/tools/build-library-bundle.sh b/tools/build-library-bundle.sh index 9e782a4..49ef412 100644 --- a/tools/build-library-bundle.sh +++ b/tools/build-library-bundle.sh @@ -102,16 +102,16 @@ preflight() { fi # Map tool name -> MSYS2 package name (identity except where noted). declare -A pkg_for - pkg_for[cmake]=cmake - pkg_for[make]=make - pkg_for[curl]=curl - pkg_for[sha256sum]=coreutils - pkg_for[tar]=tar - pkg_for[unzip]=unzip - pkg_for[zip]=zip - pkg_for[git]=git - pkg_for[python3]=python - pkg_for[dos2unix]=dos2unix + pkg_for[cmake]="cmake" + pkg_for[make]="make" + pkg_for[curl]="curl" + pkg_for[sha256sum]="coreutils" + pkg_for[tar]="tar" + pkg_for[unzip]="unzip" + pkg_for[zip]="zip" + pkg_for[git]="git" + pkg_for[python3]="python" + pkg_for[dos2unix]="dos2unix" local missing=() missing_pkgs=() for tool in psp-gcc psp-pkg-config cmake make curl sha256sum tar unzip zip git python3 dos2unix; do @@ -508,10 +508,14 @@ with open(renames_path, "w") as fh: source ./PSPBUILD set -u - # Walk source[] / sha256sums[] in parallel. + # Walk source[] / sha256sums[] in parallel. Both arrays are defined by + # the PSPBUILD sourced just above (Arch PKGBUILD convention), so + # shellcheck can't see their assignment — SC2154 is a false positive. local i=0 + # shellcheck disable=SC2154 for src_url in "${source[@]}"; do local sha="SKIP" + # shellcheck disable=SC2154 if [ "${#sha256sums[@]}" -gt "$i" ]; then sha="${sha256sums[$i]}" fi From 338e8231698f24aac57298805a2e44915e84a801 Mon Sep 17 00:00:00 2001 From: dmang-dev Date: Wed, 1 Jul 2026 09:31:06 -0700 Subject: [PATCH 3/3] ci: reword shellcheck directive comment so it isn't misparsed The explanatory comment above the SC2154 disable started a line with '# shellcheck can't see...', which shellcheck parsed as a malformed directive (SC1072/SC1073). Reword so no comment line begins with the directive token. --- tools/build-library-bundle.sh | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tools/build-library-bundle.sh b/tools/build-library-bundle.sh index 49ef412..bb68926 100644 --- a/tools/build-library-bundle.sh +++ b/tools/build-library-bundle.sh @@ -508,9 +508,10 @@ with open(renames_path, "w") as fh: source ./PSPBUILD set -u - # Walk source[] / sha256sums[] in parallel. Both arrays are defined by - # the PSPBUILD sourced just above (Arch PKGBUILD convention), so - # shellcheck can't see their assignment — SC2154 is a false positive. + # Walk source[] / sha256sums[] in parallel. Both arrays are populated + # by the PSPBUILD sourced just above (Arch PKGBUILD convention), which + # static analysis cannot see — so the SC2154 warnings below are false + # positives (do not start these comment lines with the directive token). local i=0 # shellcheck disable=SC2154 for src_url in "${source[@]}"; do