diff --git a/.github/workflows/status_check.yml b/.github/workflows/status_check.yml index d555764..1c95fff 100644 --- a/.github/workflows/status_check.yml +++ b/.github/workflows/status_check.yml @@ -160,16 +160,27 @@ jobs: # entry point itself -- and nothing was checking it. `git ls-files` rather than a # fixed list, so a script added later is covered without editing this workflow. # - # Full severity, `info` included. The two findings it raises today are answered - # with targeted `disable` directives carrying their reason, the same way + # Full severity, `info` included. The findings it raises today are answered with + # targeted `disable` directives carrying their reason, the same way # config/detekt/detekt.yml carries only the rules this codebase legitimately # breaks. A blanket --severity=warning would have hidden them and the next real - # one alike. shellcheck is preinstalled on the ubuntu runner image; the version is - # printed so a finding that appears out of nowhere can be pinned to an upgrade. + # one alike. + # + # PINNED BY DIGEST, for the reason CLAUDE.md already gives for pinning ktlint, + # detekt and JaCoCo: a new rule in a linter makes files nobody touched stop + # passing, so CI goes red on a PR whose diff cannot explain it. That is not + # hypothetical here. The first cut of this step used the runner's ambient + # shellcheck, which is 0.9.0, and 0.9.0 reports a trap handler as seven + # unreachable commands (SC2317) where 0.11.0 reports it once on the declaration + # (SC2329) -- same script, same directive, different answer, and a red build on + # the PR that introduced the step. The version is printed so a finding that + # appears out of nowhere can be tied to a bump of this line. - name: shellcheck + env: + SHELLCHECK: koalaman/shellcheck@sha256:61862eba1fcf09a484ebcc6feea46f1782532571a34ed51fedf90dd25f925a8d run: | - shellcheck --version - git ls-files -z '*.sh' | xargs -0 -r shellcheck + docker run --rm "$SHELLCHECK" --version + git ls-files -z '*.sh' | xargs -0 -r docker run --rm -v "$PWD:/mnt" "$SHELLCHECK" # `!cancelled()` rather than a plain sequence: a shellcheck failure above must not # cost the ktlint/detekt/lint lists. Same reason this step passes --continue -- one diff --git a/CLAUDE.md b/CLAUDE.md index efe7fc1..33d0ff9 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -142,8 +142,16 @@ install for code that can never run — and on API 37 the full APK does not fit two findings that raises today are answered with targeted `disable` directives carrying their reason, exactly as `config/detekt/detekt.yml` carries only the rules this codebase legitimately breaks. Do not silence it with `--severity=warning` — that hides the next real finding too. - Locally there is no shellcheck package installed; `podman run --rm -v "$PWD:/mnt:z" - docker.io/koalaman/shellcheck:stable ` is what was used. + **It is pinned by image digest, and joins ktlint/detekt/JaCoCo in the "Dependency versions" + rule above** — for exactly the reason stated there, demonstrated the day it was added. The first + cut used the runner's ambient shellcheck. That is **0.9.0**, while the container used to check + locally was 0.11.0, and the two disagree about how to report a trap handler: 0.11.0 says + `SC2329` once on the declaration, 0.9.0 says `SC2317` on each of seven lines in the body. Same + script, same directive, one green and one red. Directives that must survive both name both codes. + + Locally, use the same pin rather than whatever is installed: + `podman run --rm -v "$PWD:/mnt:z" docker.io/koalaman/shellcheck@sha256:61862eba... ` + (the digest is in `status_check.yml`; there is no shellcheck system package on this host). **It does not cover inline `run:` blocks in the workflows**, and a good deal of this repo's bash lives there. `actionlint` does cover them — it runs shellcheck over each `run:` — and reports one diff --git a/tools/local-emulator/run-e2e.sh b/tools/local-emulator/run-e2e.sh index 5e13dc8..ed34159 100755 --- a/tools/local-emulator/run-e2e.sh +++ b/tools/local-emulator/run-e2e.sh @@ -456,7 +456,10 @@ cleanup() { # bash runs a trap only between commands, so this starts when whatever was in the foreground # returns -- which for Ctrl-C is immediately, because the same interrupt reached that command # too. `kill -INT` aimed at this script alone waits for the foreground command to finish. -# shellcheck disable=SC2329 # invoked indirectly -- installed as the INT and TERM trap a few lines below. +# Invoked indirectly -- installed as the INT and TERM trap a few lines below. Both codes, +# because shellcheck 0.9.0 reports this as unreachable commands (SC2317) and 0.11.0 as an +# uninvoked function (SC2329); CI pins 0.11.0 but a local install may be either. +# shellcheck disable=SC2317,SC2329 on_signal() { echo echo "interrupted (SIG$1) -- stopping the emulator and removing the AVDs this run created"