PR Pipeline — Authorize → Validate → Review → Merge / auth (pull_request) Successful in 6s
PR Pipeline — Authorize → Validate → Review → Merge / validate (pull_request) Successful in 4s
PR Pipeline — Authorize → Validate → Review → Merge / lint (pull_request) Failing after 6s
PR Pipeline — Authorize → Validate → Review → Merge / ai-review (pull_request) Successful in 2s
PR Pipeline — Authorize → Validate → Review → Merge / gate (pull_request) Skipped
A contract verdict is only meaningful if it came from the merged copy. The fleet has been bitten three times on 2026-09-25 (a clone parked on a merged feature branch while executing from another clone; a script copied into the runner clone by hand; a stale local origin/master making an ancestry check report unlanded work). The control for this existed as an untracked draft and protected nobody, because it was entirely fail-open. Defect in the draft, preserved verbatim as tests/fixtures/revision-preflight.prefix.sh: git -C "$CLONE" show "origin/master:$(basename "$SCRIPT")" basename drops the scripts/ prefix, so for any script under scripts/ it queried the repo root, failed, took the "warn but don't block" branch and exited 0 - passing a script that exists in no revision at all. Reproduced: pre-fix + scripts/demo.sh under scripts/ -> 'could not resolve', EXIT=0 pre-fix + a script in no revision -> EXIT=0 Fixed guard (scripts/revision-preflight.sh): * resolves the repo-relative path inside the clone, so scripts/ paths resolve; * FAILS CLOSED - a path absent from the ref, an unresolvable ref, or a failed fetch is a failure, never a warning; * fetches the remote by default, because a stale local ref would otherwise pass a stale script as current; --no-fetch states the assumption instead of hiding it. Wiring (scripts/contract-run.sh): before executing, the wrapper runs the guard against the clone it lives in. Default CONTRACT_REVISION_PREFLIGHT=enforce withholds the verdict, alerts and exits 2 on mismatch; =warn logs and continues; =off skips. Verified live: match -> contract proceeds and PASSes; mismatch -> 'VERDICT WITHHELD', exit 2; =warn -> continues. Pinning (docs/contract-execution-pinning.md): every contract pins the clone contract-run.sh lives in - the deployed runner being /opt/contract-runner on CT 100. Documented that daily-health-digest has no contract file at all, which is why its execution copy was silently operator-chosen. Tests: tests/test_revision_preflight.sh, 15 assertions over a throwaway clone with a real bare remote. It runs the pre-fix draft against the same cases and shows it passing a ghost script, so the tests provably bite. shellcheck: scripts/revision-preflight.sh and the new test are clean. The three findings remaining in contract-run.sh (SC2086 x2, SC2034) are pre-existing and byte-identical on master.
41 lines
1.6 KiB
Bash
Executable File
41 lines
1.6 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Revision preflight guard: verify the script being executed matches origin/master
|
|
# Usage: revision-preflight.sh <script-path> <clone-path>
|
|
# Returns 0 if match, 1 if mismatch (prints both revisions)
|
|
|
|
set -euo pipefail
|
|
|
|
SCRIPT="${1:?Usage: revision-preflight.sh <script-path> <clone-path>}"
|
|
CLONE="${2:?Usage: revision-preflight.sh <script-path> <clone-path>}"
|
|
|
|
# Compute sha256 of the script being executed
|
|
EXEC_SHA=$(sha256sum "$SCRIPT" | cut -d' ' -f1)
|
|
|
|
# Compute sha256 of the merged origin/master version
|
|
# Extract to a temp file to avoid pipe issues
|
|
TMPFILE=$(mktemp)
|
|
trap 'rm -f "$TMPFILE"' EXIT
|
|
|
|
# Try to extract the file from origin/master
|
|
if git -C "$CLONE" show "origin/master:$(basename "$SCRIPT")" > "$TMPFILE" 2>/dev/null; then
|
|
MASTER_SHA=$(sha256sum "$TMPFILE" | cut -d' ' -f1)
|
|
else
|
|
echo "⚠️ revision-preflight: could not resolve origin/master revision for $(basename "$SCRIPT")" >&2
|
|
exit 0 # Warn but don't block if git show fails
|
|
fi
|
|
|
|
if [[ -z "$MASTER_SHA" || "$MASTER_SHA" == "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" ]]; then
|
|
echo "⚠️ revision-preflight: could not resolve origin/master revision for $(basename "$SCRIPT")" >&2
|
|
exit 0 # Warn but don't block if git show fails
|
|
fi
|
|
|
|
if [[ "$EXEC_SHA" != "$MASTER_SHA" ]]; then
|
|
echo "⚠️ revision-preflight: MISMATCH detected" >&2
|
|
echo " Executed: $EXEC_SHA ($(basename "$SCRIPT"))" >&2
|
|
echo " Merged: $MASTER_SHA (origin/master:$(basename "$SCRIPT"))" >&2
|
|
exit 1
|
|
else
|
|
echo "✅ revision-preflight: $SCRIPT matches origin/master ($EXEC_SHA)" >&2
|
|
exit 0
|
|
fi
|