ci: check_protocol.sh -- a commit carries passing protocol evidence for its tree (#135)
scripts/check_protocol.sh [<rev>]: refused (exit 1) unless <rev> carries a logs/<TS>/PROTOCOL.md naming a commit whose protocol passed on a clean tree, and that commit differs from <rev> only in the evidence (logs/ and experiments/bare_metal/runs/, committed after the run). Any other change since makes the evidence stale: the protocol is run again. scripts/test_check_protocol.sh, written first and seen to fail (8 of 8, and tightened so a missing script is not taken for a refusal): no protocol, stale, failed, dirty, unknown commit -- refused; fresh, fresh among stale ones, other files in logs/ -- passes. 8 of 8 pass. Not yet wired into acceptance.yml: that comes with nightly.sh protocol. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017RzZgrf7V7Zk2iczBXDRbm
This commit is contained in:
Executable
+50
@@ -0,0 +1,50 @@
|
||||
#!/usr/bin/env bash
|
||||
# SPDX-License-Identifier: LicenseRef-Starship-1.0
|
||||
# Copyright (c) 2023-2026 Robert A. James
|
||||
# check_protocol.sh [<rev>] -- does <rev> (default HEAD) carry the developer protocol's evidence
|
||||
# for its own tree? (#135; Captain Bob, 2026-11-07: "the protocol evidence can be submitted in
|
||||
# the PR"). Run by .gitea/workflows/acceptance.yml on the pull request's head, in the repository
|
||||
# the current directory is in. Tests: scripts/test_check_protocol.sh.
|
||||
#
|
||||
# The evidence is a logs/<TS>/PROTOCOL.md, as `scripts/nightly.sh protocol` writes it, naming
|
||||
# - Commit: <the commit the stages ran on>
|
||||
# - Tree: clean
|
||||
# - Result: PASS
|
||||
# It is for <rev>'s tree when that commit differs from <rev> only in the evidence itself --
|
||||
# logs/ and experiments/bare_metal/runs/, which a developer commits after the run. Any other
|
||||
# change since is a change the protocol did not see: the evidence is stale, and the protocol is run
|
||||
# again (a repair means rerunning from the top).
|
||||
#
|
||||
# Exit 0 with the protocol that counts; 1 "refused", with why; 2 on a usage error.
|
||||
set -uo pipefail
|
||||
rev=${1:-HEAD}
|
||||
EVIDENCE=(':(exclude)logs' ':(exclude)experiments/bare_metal/runs')
|
||||
|
||||
refuse() { echo "check_protocol: refused -- $*" >&2; exit 1; }
|
||||
git rev-parse --verify -q "$rev^{commit}" >/dev/null || { echo "check_protocol: no commit $rev" >&2; exit 2; }
|
||||
head=$(git rev-parse "$rev^{commit}")
|
||||
|
||||
mapfile -t protocols < <(git ls-tree -r --name-only "$head" -- logs | grep -E '^logs/[^/]+/PROTOCOL\.md$' | sort -r)
|
||||
[ ${#protocols[@]} -gt 0 ] || refuse "${head:0:8} carries no logs/<TS>/PROTOCOL.md: run scripts/nightly.sh protocol and commit its logs"
|
||||
|
||||
why=()
|
||||
for p in "${protocols[@]}"; do
|
||||
body=$(git show "$head:$p")
|
||||
commit=$(sed -n 's/^- Commit: *\([0-9a-f]\{40\}\) *$/\1/p' <<<"$body" | head -1)
|
||||
tree=$(sed -n 's/^- Tree: *\([a-z]*\) *$/\1/p' <<<"$body" | head -1)
|
||||
result=$(sed -n 's/^- Result: *\([A-Z]*\) *$/\1/p' <<<"$body" | head -1)
|
||||
if [ -z "$commit" ] || ! git cat-file -e "$commit^{commit}" 2>/dev/null; then
|
||||
why+=("$p: names no commit this repository has (${commit:-none}).")
|
||||
elif [ "$result" != PASS ]; then
|
||||
why+=("$p: the protocol for ${commit:0:8} did not pass (${result:-no result}).")
|
||||
elif [ "$tree" != clean ]; then
|
||||
why+=("$p: the protocol for ${commit:0:8} ran on a tree that was ${tree:-not said to be clean}.")
|
||||
elif ! git diff --quiet "$commit" "$head" -- . "${EVIDENCE[@]}"; then
|
||||
why+=("$p: stale -- ${head:0:8} differs from ${commit:0:8} outside logs/ and experiments/bare_metal/runs/: $(git diff --name-only "$commit" "$head" -- . "${EVIDENCE[@]}" | head -3 | tr '\n' ' ')")
|
||||
else
|
||||
echo "check_protocol: ${head:0:8} carries $p -- the protocol passed on ${commit:0:8}, the same tree but for its evidence"
|
||||
exit 0
|
||||
fi
|
||||
done
|
||||
printf ' %s\n' "${why[@]}" >&2
|
||||
refuse "no PROTOCOL.md in ${head:0:8} is a passing protocol for its tree"
|
||||
Reference in New Issue
Block a user