ci: eliminate the sh-vs-bash footgun class (defaults + lint guard)
Lint workflows / actionlint (push) Failing after 34s

Root cause of the recurring 'Illegal option -o pipefail' failures
(ed49b8d resolve-versions; b7197e8 promote-base-latest, run 418):
docker-publish.yml had no workflow-level default shell, so Gitea's
sh/dash default applied and every bash-syntax step had to individually
remember 'shell: bash'.

- docker-publish.yml: add 'defaults: run: shell: bash' — fixes the whole
  class; all pre-existing dash steps are POSIX so bash runs them unchanged.
- lint.yml: new workflow, runs on every push/PR (not just release tags):
    * scripts/check-workflow-shell.sh — Gitea-accurate guard: fails if any
      run: step doesn't resolve to bash. Catches the omit-shell+bash-syntax
      case that actionlint MISSES (actionlint models GitHub, where the
      default shell is bash, so a shell-less step is assumed bash).
    * actionlint + shellcheck — catches explicit 'shell: sh' + bash syntax
      (SC3040) and general workflow errors.
  Verified locally: guard + actionlint pass current workflows; guard fails
  a synthetic omit-shell+pipefail workflow; shellcheck clean.
This commit is contained in:
pi
2026-07-01 22:05:04 +02:00
parent b33e9dc592
commit 26384fe9f1
4 changed files with 164 additions and 0 deletions
+25
View File
@@ -13,6 +13,31 @@ Pre-v1.0.0 tags followed the pi npm version (`v{pi_version}[letter]`).
## Unreleased
### Added (CI)
- **Workflow lint (`.gitea/workflows/lint.yml`) running on every push and PR.**
Two complementary checks, so CI-workflow bugs are caught before an expensive
build runs:
- **`scripts/check-workflow-shell.sh`** — a Gitea-accurate guard that fails
if any `run:` step doesn't resolve to `bash` under Gitea's real defaults.
This catches the exact recurrence class (omit `shell:`, use bash syntax),
which **actionlint alone does not** — actionlint models GitHub Actions
(default shell = bash) and so assumes a shell-less step is bash, whereas
Gitea's default is `sh`/dash.
- **`actionlint` + `shellcheck`** — catches explicit `shell: sh` + bash
syntax (SC3040 etc.), expression errors, and general workflow mistakes.
Style-only shellcheck codes are excluded; the SC3xxx "wrong shell" family
is kept.
### Changed (CI)
- **Workflow-level `defaults: run: shell: bash` in `docker-publish.yml`.**
Gitea Actions defaults each `run:` step to `sh` (dash), so every bash-syntax
step had to individually remember `shell: bash` — a discipline requirement
that failed twice (ed49b8d, b7197e8). Setting the default workflow-wide
eliminates the whole class. All pre-existing dash steps use only POSIX
syntax, so bash (a superset) runs them unchanged.
### Fixed (CI)
- **`promote-base-latest` now sets `shell: bash` on the base-latest re-tag