#!/usr/bin/env bash # # check-frozen-rules.sh [] # # Runs scripts/check-frozen-rules.py twice over head: as it first reached head's first-parent # history, and as head holds it. The check reads the history, so what it finds does not depend # on any one run; the first copy means a change that weakens the script, or removes it, # together with a rule file does not hide the rule's change, and neither does a change to the # script made earlier than the rule's, in a push whose run was cancelled. The copy as head # holds it is the one that later rules and later record layouts can extend. # # A branch made before the check reached main holds no copy of it: with a base, both copies are # then the base's. # # Exit 0 when both pass, 1 when either fails or a copy cannot be read, 2 on a wrong command line. set -uo pipefail if [ $# -lt 1 ] || [ $# -gt 2 ] || [ -z "$1" ]; then echo "usage: check-frozen-rules.sh []" exit 2 fi py=scripts/check-frozen-rules.py first_add() { git log --first-parent -m --diff-filter=A --format=%H "$1" -- "$py" | tail -n 1; } tmp=$(mktemp -d) trap 'rm -rf "$tmp"' EXIT holder=$1 first=$(first_add "$holder") if [ -z "$first" ] && [ $# -eq 2 ]; then holder=$2 first=$(first_add "$holder") fi if [ -z "$first" ] || ! git show "$first:$py" > "$tmp/first.py"; then echo "::error::frozen rules: no commit of the first-parent history of $* adds $py, so the check cannot run from it" exit 1 fi rc=0 echo "frozen rules: the check as it first reached this history, in ${first:0:12}" python3 -I "$tmp/first.py" "$@" || rc=1 echo "frozen rules: the check as ${holder:0:12} holds it" if git show "$holder:$py" > "$tmp/head.py"; then python3 -I "$tmp/head.py" "$@" || rc=1 else echo "::error::frozen rules: $holder holds no $py" rc=1 fi exit $rc