drills/README.md — the standing runner-probe venue, and why the drill disposal rule does not apply to it (#202) #207

Merged
andres merged 14 commits from build/202-runner-probe-venue into main 2026-08-05 17:18:59 +00:00
2 changed files with 46 additions and 8 deletions
Showing only changes of commit 6874e76c04 - Show all commits

View file

@ -37,8 +37,19 @@
distinguishes ceremony's internal self-checkouts from the consumer checkouts distinguishes ceremony's internal self-checkouts from the consumer checkouts
that must stay `${{ github.repository }}` (#202). that must stay `${{ github.repository }}` (#202).
- Both published snippets parse, lint clean and were driven against a - Both published snippets are ShellCheck-clean when extracted and linted
constructed armed/probe pair: deletion, both role swaps, wrong owner, wrong directly, not merely as part of the repository sweep (#202).
- The checker validates the MANIFEST against the target it was given, so a
manifest that describes a wrong arming consistently — wrong fork, or the
armed SHA where the candidate belongs — refuses instead of matching a tree
rewritten to the same wrong value (#202).
- The manifest is generated from the PRE-arming tree, which is the only order
that enumerates the carriers that must change (#202).
- Both published snippets were driven against a constructed candidate/probe
pair: deletion, both role swaps, wrong owner, wrong
SHA, wrong path, a deleted caller class and an extra carrier all refuse, and SHA, wrong path, a deleted caller class and an extra carrier all refuse, and
the armed control passes (#202). the armed control passes (#202).

View file

@ -113,7 +113,11 @@ So:
the **candidate code SHA**. Never create a branch on the **candidate code SHA**. Never create a branch on
`heavy-duty/ceremony` named like a tag: it shadows that tag for every `heavy-duty/ceremony` named like a tag: it shadows that tag for every
consumer until somebody remembers to delete it. consumer until somebody remembers to delete it.
2. **Commit the arming on top of it, and write the manifest.** In that same 2. **Write the manifest FIRST, from the pre-arming tree, then commit the
arming.** The manifest enumerates the carriers *that must change*, so it is
generated before they do — running it afterwards would enumerate
already-rewritten rows and lose the canonical internal-checkout ones
entirely (@codex-reviewer-andresmgsl, #202 review). In that same
fork branch rewrite, for **every** carrier the manifest below enumerates: fork branch rewrite, for **every** carrier the manifest below enumerates:
ceremony's own internal `repository:` checkouts → `<identity>/ceremony`, and ceremony's own internal `repository:` checkouts → `<identity>/ceremony`, and
**every** `CEREMONY_SELF_REF` value → the **candidate code SHA** from step 1. **every** `CEREMONY_SELF_REF` value → the **candidate code SHA** from step 1.
@ -152,7 +156,10 @@ So:
```sh ```sh
#!/usr/bin/env bash #!/usr/bin/env bash
# write-manifest <armed-checkout> <probe-checkout> <fork> <code-sha> <armed-sha> # write-manifest <candidate-checkout> <probe-checkout> <fork> <code-sha> <armed-sha>
#
# Run against the PRE-ARMING tree and the UNPINNED probe: this records what
# each carrier must BECOME, so it has to see them before they change.
# #
# `|| true` on every extraction, for the same reason the checker needs it: # `|| true` on every extraction, for the same reason the checker needs it:
# git grep exits 1 on no-match and `set -e` would abort BEFORE the manifest # git grep exits 1 on no-match and `set -e` would abort BEFORE the manifest
@ -160,7 +167,8 @@ So:
# produced no file and no diagnostic when a probe exercised only one layer # produced no file and no diagnostic when a probe exercised only one layer
# (@codex-reviewer-andresmgsl). A probe need not use both. # (@codex-reviewer-andresmgsl). A probe need not use both.
set -euo pipefail set -euo pipefail
armed="$1"; probe="$2"; fork="$3"; code_sha="$4"; armed_sha="$5" armed="$1"; probe="$2"; fork="$3"; code_sha="$4"; armed_sha="$5" # $1 = pre-arming
# shellcheck disable=SC2016 # `${{ github.repository }}` is literal YAML, not a shell expansion
{ {
git -C "$armed" grep -n 'CEREMONY_SELF_REF:' -- .github/workflows \ git -C "$armed" grep -n 'CEREMONY_SELF_REF:' -- .github/workflows \
| cut -d: -f1,2 | sed "s|$|\tself_ref\t$code_sha|" || true | cut -d: -f1,2 | sed "s|$|\tself_ref\t$code_sha|" || true
@ -182,8 +190,7 @@ So:
[ "$callers" -gt 0 ] || { echo "manifest: no ceremony callers found in $probe" >&2; exit 1; } [ "$callers" -gt 0 ] || { echo "manifest: no ceremony callers found in $probe" >&2; exit 1; }
``` ```
Run it against the **pre-arming** tree — that is what enumerates the Then arm — rewrite and commit — and check the result against it:
carriers that must change — then arm, then check:
```sh ```sh
#!/usr/bin/env bash #!/usr/bin/env bash
@ -200,7 +207,27 @@ So:
[ "$(grep -cE '(workflow|action)_caller' "$manifest" || true)" -gt 0 ] \ [ "$(grep -cE '(workflow|action)_caller' "$manifest" || true)" -gt 0 ] \
|| fail "manifest names no ceremony callers — it cannot prove an arming" || fail "manifest names no ceremony callers — it cannot prove an arming"
actual="$(mktemp)" # THE MANIFEST ITSELF IS CHECKED AGAINST THE TARGET, not trusted. Comparing
# only tree-vs-manifest proves consistency, and a manifest generated with the
# armed SHA where the candidate SHA belonged — or with the wrong fork —
# describes a WRONG arming perfectly. The tree would then match it and the
# gate would pass (@codex-reviewer-andresmgsl, #202 review).
# shellcheck disable=SC2016 # `${{ github.repository }}` below is literal YAML
while IFS=$'\t' read -r loc kind want; do
case "$kind" in
self_ref) [ "$want" = "$code_sha" ] || fail "manifest $loc: self_ref should be the CANDIDATE sha" ;;
internal_repo) [ "$want" = "$fork" ] || fail "manifest $loc: internal repo should be $fork" ;;
consumer_repo) [ "$want" = '${{ github.repository }}' ] \
|| fail "manifest $loc: consumer checkout must stay dynamic" ;;
workflow_caller) [ "$want" = "$fork/${want#*/ceremony/}" ] || fail "manifest $loc: caller owner"
[ "${want##*@}" = "$armed_sha" ] || fail "manifest $loc: workflow caller should be the ARMED sha" ;;
action_caller) [ "$want" = "$fork/${want#*/ceremony/}" ] || fail "manifest $loc: caller owner"
[ "${want##*@}" = "$code_sha" ] || fail "manifest $loc: action caller should be the CANDIDATE sha" ;;
*) fail "manifest $loc: unknown kind '$kind'" ;;
esac
done <"$manifest"
actual="$(mktemp)"; trap 'rm -f "$actual"' EXIT
{ {
git -C "$armed" grep -nP '(?<=CEREMONY_SELF_REF: ")[^"]+' -- .github/workflows \ git -C "$armed" grep -nP '(?<=CEREMONY_SELF_REF: ")[^"]+' -- .github/workflows \
| sed -E 's/^([^:]+):([0-9]+):.*CEREMONY_SELF_REF: "([^"]*)".*/\1:\2\tself_ref\t\3/' || true | sed -E 's/^([^:]+):([0-9]+):.*CEREMONY_SELF_REF: "([^"]*)".*/\1:\2\tself_ref\t\3/' || true