Skip to content

fix(maintenance): the sweep ran under bash -e and could not report a finding - #176

Merged
rldyourmnd merged 1 commit into
mainfrom
fix/maintenance-shell-e
Aug 14, 2026
Merged

fix(maintenance): the sweep ran under bash -e and could not report a finding#176
rldyourmnd merged 1 commit into
mainfrom
fix/maintenance-shell-e

Conversation

@rldyourmnd

Copy link
Copy Markdown
Contributor

Found by running it

PR #172 made maintenance.yml able to fetch tags and file an issue. I then dispatched
it — the first execution in its life. It failed, and the log shows why:

advisory sweep  Run the advisory sweep  shell: /usr/bin/bash -e {0}
advisory sweep  Run the advisory sweep  check_python_syntax: OK
advisory sweep  Run the advisory sweep  ##[error]Process completed with exit code 1.

Note what is missing: no cat sweep.txt, no status=. The step died at the sweep
line itself.

The defect

GitHub runs run: steps as bash -e {0}. -e arrives on the shell's own command
line
, where no set inside the script can reach it. The step said:

set -uo pipefail
...
# Deliberately not `set -e`: a finding is the expected outcome and
# must be reported, not abort the job before it can be filed.

That comment was false. set -uo pipefail does not remove an -e that the shell was
invoked with. So on the first finding — the only time this job matters — bash aborted
before status=$?, $GITHUB_OUTPUT never received a status, and the report step had
nothing to act on. No if: on that step either, so a failed sweep skipped reporting
altogether.

Three layers of the same shape: the reporting mechanism was unreachable in exactly
the case it exists for.

Fix

  • shell: bash {0} on the sweep step — the documented way to get a bash without -e.
  • if: always() on the report step.
  • An empty status is treated as a finding, not as silence. An advisory lane whose
    findings vanish looks identical to one with nothing to say.

Proof

The contract now resolves the effective shell the way GitHub does — step, then job
defaults.run.shell, then workflow defaults, then bash -e {0} — and executes the
sweep step under it
with a stub interpreter, asserting the exit code reaches
$GITHUB_OUTPUT for both a clean sweep and a finding.

Mutation Result
shell reverts to the GitHub default (bash -e) RED (caught)
shell declared as plain bash (expands to -eo pipefail) RED (caught)
report step stops running unconditionally RED (caught)

The second case matters: shell: bash looks like a fix and is not — it expands to
bash --noprofile --norc -eo pipefail {0}.

Still unknown

What the sweep actually found on the runner is still unknown, because the step died
before printing sweep.txt. Locally all three tiers are green. I will re-run
maintenance.yml after this merges and report what it says.

Verification

  • validate_all — all three tiers OK with GH_TOKEN
  • actionlint — clean · zizmor@1.26.1 --persona pedantic --min-severity low — no findings

…a finding

The first real run of maintenance.yml failed, and only the run could show why.
GitHub runs `run:` steps as `bash -e {0}`. `-e` arrives on the shell's own
command line, where no `set` inside the script can reach it -- so the step's
`set -uo pipefail`, and its comment stating that `-e` was deliberately absent,
were both wrong. On the first finding bash aborted at the sweep line: `$?` was
never read, sweep.txt was never printed, and $GITHUB_OUTPUT never received a
status. The report step then had nothing to act on.

The mechanism was unreachable in exactly the case it exists for.

`shell: bash {0}` fixes it. The report step becomes `if: always()` so a sweep
that dies for another reason is still reported, and an empty status is treated
as a finding rather than as silence.

The contract now resolves the shell the way GitHub does -- step, job defaults,
workflow defaults, then `bash -e {0}` -- and executes the sweep step under it
with a stub interpreter, asserting the exit code is recorded for a clean sweep
and for a finding. Reverting to the default is caught, and so is declaring
plain `bash`, which expands to `--noprofile --norc -eo pipefail`.
@github-actions github-actions Bot added ci Continuous integration and removed ci Continuous integration labels Aug 14, 2026
@rldyourmnd
rldyourmnd merged commit a2e9fe9 into main Aug 14, 2026
29 checks passed
@rldyourmnd
rldyourmnd deleted the fix/maintenance-shell-e branch August 14, 2026 23:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant