Severity: medium. Found by a platform-engineer user test who hit it during a real 12-repo rollout. Pre-existing.
The script in "The script that survives a real rollout" appends every processed repo to done.txt, including the exit-2 ones it just filed under needs-human:
case $code in
0) ;;
2) echo "$repo" >> needs-human ;;
*) exit "$code" ;;
esac
echo "$repo" >> done.txt # <- runs for exit 2 as well
The resume guard at the top is grep -qxF "$repo" done.txt && continue. So once a repo needs a human, the rollout skips it forever — including after the human fixes it.
Repro
--- run 1 (repo is broken) ---
error: refusing: rule "infra/" also governs paths outside scope "**/*.tf" ...
needs-human: acme/infra-terraform
done.txt: acme/infra-terraform
--- human fixes the repo, re-runs ---
SKIPPED (already in done.txt): acme/infra-terraform
--- still unconverged: refused
One line of output, exit 0, and the repo silently never gets its baseline. The reporter had to abandon the documented loop and drive remediation off needs-human instead. At 100 repos with a dozen exceptions, this is how a rollout is believed complete and isn't.
Fix
Move echo "$repo" >> done.txt into the 0) arm.
Severity: medium. Found by a platform-engineer user test who hit it during a real 12-repo rollout. Pre-existing.
The script in "The script that survives a real rollout" appends every processed repo to
done.txt, including the exit-2 ones it just filed underneeds-human:The resume guard at the top is
grep -qxF "$repo" done.txt && continue. So once a repo needs a human, the rollout skips it forever — including after the human fixes it.Repro
One line of output, exit 0, and the repo silently never gets its baseline. The reporter had to abandon the documented loop and drive remediation off
needs-humaninstead. At 100 repos with a dozen exceptions, this is how a rollout is believed complete and isn't.Fix
Move
echo "$repo" >> done.txtinto the0)arm.