From 642a5f7d96fc4593a39694cd06509f5fed0d63fd Mon Sep 17 00:00:00 2001 From: atlas Date: Wed, 16 Sep 2026 00:03:47 +0200 Subject: [PATCH 1/2] ci: add shellcheck step for raw shell scripts Discovers files by shebang under scripts/ rather than a *.sh glob, so extensionless scripts (scripts/pre-push) and any future additions are covered without editing the workflow. Runs at -S warning: the repo's one existing finding (SC2016 on an intentionally single-quoted awk program) is info-level and correct as written, so it's excluded by severity rather than silenced with a disable comment. Refs #4429 --- .forgejo/workflows/ci.yml | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/.forgejo/workflows/ci.yml b/.forgejo/workflows/ci.yml index ee038c41..57577b3b 100644 --- a/.forgejo/workflows/ci.yml +++ b/.forgejo/workflows/ci.yml @@ -56,6 +56,26 @@ jobs: - name: lint run: sh scripts/check-attribution-trailers.sh + shellcheck: + name: shellcheck + runs-on: [hive-ci] + # shellcheck itself is fast; nix shell's first pull of the closure is + # the slow part on a cold cache. + timeout-minutes: 10 + steps: + - uses: actions/checkout@v3 + - name: lint + # Discovers raw shell files by shebang rather than by extension — + # scripts/pre-push ships with no `.sh` suffix, so a `*.sh` glob + # would silently skip it (and any future extensionless script). + # -S warning drops info-level notes: the repo's one SC2016 hit is + # an intentionally single-quoted awk program, not a bug, and this + # keeps the gate free of a disable-comment for it while still + # failing on anything warning-or-worse. + run: | + files=$(grep -lE '^#!.*/(env[[:space:]]+)?(ba)?sh([[:space:]]|$)' scripts/* 2>/dev/null) + echo "$files" | xargs nix develop -c shellcheck -S warning + prose-lint: name: prose lint (vale) runs-on: [hive-ci] From f4cabd117b2fb4f0b66ec02ea2f22217bddbdc1f Mon Sep 17 00:00:00 2001 From: atlas Date: Wed, 16 Sep 2026 00:06:01 +0200 Subject: [PATCH 2/2] ci: trim shellcheck step comment, fail loudly on empty discovery MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move the SC2016 / -S warning rationale to the PR body — a decision justification, not something that needs to live inline forever. Keep only the one line that explains the non-obvious part of the code itself: shebang-based discovery over a *.sh glob. Also make the no-files case explicit: an empty match previously fell through to shellcheck with no arguments (a confusing usage error, but still non-zero); now it prints a clear message and exits 1. --- .forgejo/workflows/ci.yml | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/.forgejo/workflows/ci.yml b/.forgejo/workflows/ci.yml index 57577b3b..fc4ec447 100644 --- a/.forgejo/workflows/ci.yml +++ b/.forgejo/workflows/ci.yml @@ -59,21 +59,17 @@ jobs: shellcheck: name: shellcheck runs-on: [hive-ci] - # shellcheck itself is fast; nix shell's first pull of the closure is - # the slow part on a cold cache. timeout-minutes: 10 steps: - uses: actions/checkout@v3 - name: lint - # Discovers raw shell files by shebang rather than by extension — - # scripts/pre-push ships with no `.sh` suffix, so a `*.sh` glob - # would silently skip it (and any future extensionless script). - # -S warning drops info-level notes: the repo's one SC2016 hit is - # an intentionally single-quoted awk program, not a bug, and this - # keeps the gate free of a disable-comment for it while still - # failing on anything warning-or-worse. + # By shebang, not a `*.sh` glob — scripts/pre-push has no suffix. run: | files=$(grep -lE '^#!.*/(env[[:space:]]+)?(ba)?sh([[:space:]]|$)' scripts/* 2>/dev/null) + if [ -z "$files" ]; then + echo "no shell files discovered under scripts/ — check the shebang pattern" >&2 + exit 1 + fi echo "$files" | xargs nix develop -c shellcheck -S warning prose-lint: