drills/README.md — the standing runner-probe venue, and why the drill disposal rule does not apply to it (#202) #207
2 changed files with 44 additions and 22 deletions
|
|
@ -29,7 +29,7 @@
|
|||
checkout points at the fork (#202).
|
||||
|
||||
- The arming gate asserts what each carrier IS, not only that the old literal
|
||||
is gone: every `repository:` equals the fork, both `CEREMONY_SELF_REF` values
|
||||
is gone: every `repository:` equals the fork, every `CEREMONY_SELF_REF` value
|
||||
equal the candidate code SHA, and callers match the layer they belong to
|
||||
(#202).
|
||||
|
||||
|
|
@ -38,8 +38,15 @@
|
|||
that must stay `${{ github.repository }}` (#202).
|
||||
|
||||
- Both published snippets parse, lint clean and were driven against a
|
||||
constructed armed/probe pair: all six failure classes refuse and the armed
|
||||
control passes (#202).
|
||||
constructed armed/probe pair: deletion, both role swaps, wrong owner, wrong
|
||||
SHA, wrong path, a deleted caller class and an extra carrier all refuse, and
|
||||
the armed control passes (#202).
|
||||
|
||||
- The manifest records complete caller coordinates, so a path swapped under the
|
||||
right owner and SHA is caught (#202).
|
||||
|
||||
- Generator and checker share one domain — ceremony callers — so a third-party
|
||||
`actions/checkout` is neither manifested nor reported as unrecognised (#202).
|
||||
|
||||
- Probe results are written to an issue in the probe repo and carried to the
|
||||
ceremony issue by a human, so the probe holds no path that can write to the
|
||||
|
|
|
|||
|
|
@ -153,20 +153,33 @@ So:
|
|||
```sh
|
||||
#!/usr/bin/env bash
|
||||
# write-manifest <armed-checkout> <probe-checkout> <fork> <code-sha> <armed-sha>
|
||||
#
|
||||
# `|| 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
|
||||
# is written — silently, which is how the first version of this generator
|
||||
# produced no file and no diagnostic when a probe exercised only one layer
|
||||
# (@codex-reviewer-andresmgsl). A probe need not use both.
|
||||
set -euo pipefail
|
||||
armed="$1"; probe="$2"; fork="$3"; code_sha="$4"; armed_sha="$5"
|
||||
{
|
||||
git -C "$armed" grep -n 'CEREMONY_SELF_REF:' -- .github/workflows \
|
||||
| cut -d: -f1,2 | sed "s|\$|\tself_ref\t$code_sha|"
|
||||
| cut -d: -f1,2 | sed "s|$|\tself_ref\t$code_sha|" || true
|
||||
git -C "$armed" grep -n 'repository: heavy-duty/ceremony' -- .github/workflows \
|
||||
| cut -d: -f1,2 | sed "s|\$|\tinternal_repo\t$fork|"
|
||||
| cut -d: -f1,2 | sed "s|$|\tinternal_repo\t$fork|" || true
|
||||
git -C "$armed" grep -n 'repository: ${{ github.repository }}' -- .github/workflows \
|
||||
| cut -d: -f1,2 | sed 's|$|\tconsumer_repo\t${{ github.repository }}|'
|
||||
git -C "$probe" grep -n 'uses: .*/.github/workflows/' -- .github \
|
||||
| cut -d: -f1,2 | sed "s|\$|\tworkflow_caller\t$armed_sha|"
|
||||
git -C "$probe" grep -n 'uses: .*/actions/' -- .github \
|
||||
| cut -d: -f1,2 | sed "s|\$|\taction_caller\t$code_sha|"
|
||||
| cut -d: -f1,2 | sed 's|$|\tconsumer_repo\t${{ github.repository }}|' || true
|
||||
# Callers record the COMPLETE expected coordinate, not just the sha: the
|
||||
# path is as rewritable as the owner, and a manifest that stores only the
|
||||
# suffix cannot notice `…/actions/wrong-one@<right-sha>`.
|
||||
git -C "$probe" grep -nE 'uses:[[:space:]]*[^[:space:]]*/ceremony/\.github/workflows/' -- .github \
|
||||
| sed -E "s|^([^:]+):([0-9]+):.*/ceremony/(\.github/workflows/[^@[:space:]]+)@.*|\\1:\\2\\tworkflow_caller\\t$fork/\\3@$armed_sha|" || true
|
||||
git -C "$probe" grep -nE 'uses:[[:space:]]*[^[:space:]]*/ceremony/actions/' -- .github \
|
||||
| sed -E "s|^([^:]+):([0-9]+):.*/ceremony/(actions/[^@[:space:]]+)@.*|\\1:\\2\\taction_caller\\t$fork/\\3@$code_sha|" || true
|
||||
} | sort >manifest.tsv
|
||||
|
||||
# Zero ceremony callers is a refusal by name; one layer only is fine.
|
||||
callers="$(grep -cE '(workflow|action)_caller' manifest.tsv || true)"
|
||||
[ "$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
|
||||
|
|
@ -184,13 +197,21 @@ So:
|
|||
# carrier class that vanished ENTIRELY produced silence instead of a
|
||||
# refusal. Silence is the worst of the three outcomes; the comparison below
|
||||
# is what must report it.
|
||||
[ "$(grep -cE '(workflow|action)_caller' "$manifest" || true)" -gt 0 ] \
|
||||
|| fail "manifest names no ceremony callers — it cannot prove an arming"
|
||||
|
||||
actual="$(mktemp)"
|
||||
{
|
||||
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
|
||||
git -C "$armed" grep -nE 'repository: .+' -- .github/workflows \
|
||||
| sed -E 's|^([^:]+):([0-9]+):[[:space:]]*repository:[[:space:]]*(.*)$|\1:\2\t__repo__\t\3|' || true
|
||||
git -C "$probe" grep -nE 'uses: .+' -- .github \
|
||||
# Only CEREMONY callers, matching the generator's domain exactly — a
|
||||
# third-party `actions/checkout` is not this gate's business, and
|
||||
# extracting it here while the generator ignores it made every probe fail
|
||||
# as an "unrecognised carrier" (@codex-reviewer-andresmgsl). A wrong OWNER
|
||||
# is still caught: `wrong-owner/ceremony/...` matches this pattern.
|
||||
git -C "$probe" grep -nE 'uses:[[:space:]]*[^[:space:]]*/ceremony/' -- .github \
|
||||
| sed -E 's|^([^:]+):([0-9]+):[[:space:]]*-?[[:space:]]*uses:[[:space:]]*(.*)$|\1:\2\t__uses__\t\3|' || true
|
||||
} | sort >"$actual"
|
||||
|
||||
|
|
@ -205,17 +226,11 @@ So:
|
|||
have="$(awk -F'\t' -v l="$loc" '$1==l && $2=="__uses__"{print $3}' "$actual")" ;;
|
||||
esac
|
||||
[ -n "$have" ] || fail "carrier vanished: $loc ($kind)"
|
||||
case "$kind" in
|
||||
self_ref|internal_repo|consumer_repo)
|
||||
[ "$have" = "$want" ] || fail "$loc ($kind): expected '$want', found '$have'" ;;
|
||||
workflow_caller)
|
||||
[ "$have" = "$fork/.github/workflows/${have##*/.github/workflows/}" ] \
|
||||
|| fail "$loc: caller owner is not $fork — '$have'"
|
||||
[ "${have##*@}" = "$armed_sha" ] || fail "$loc: workflow caller not armed sha" ;;
|
||||
action_caller)
|
||||
case "$have" in "$fork/actions/"*) ;; *) fail "$loc: caller owner is not $fork — '$have'" ;; esac
|
||||
[ "${have##*@}" = "$code_sha" ] || fail "$loc: action caller not code sha" ;;
|
||||
esac
|
||||
# ONE comparison for every kind: the manifest already carries the complete
|
||||
# expected value, so owner, path AND sha are checked at once. Checking the
|
||||
# owner and the sha separately let `…/actions/wrong-one@<right-sha>`
|
||||
# through (@codex-reviewer-andresmgsl).
|
||||
[ "$have" = "$want" ] || fail "$loc ($kind): expected '$want', found '$have'"
|
||||
done <"$manifest"
|
||||
|
||||
# and nothing UNRECOGNISED: every uses:/repository: in the trees must appear
|
||||
|
|
|
|||
Loading…
Reference in a new issue