#!/usr/bin/env bash # ci/tests/approval-override.test.sh — proves ci/approval-override.py selects the override it # claims to select, and REJECTS the ones it claims to reject. # # This parser decides whether a human review requirement gets waived. Every rule in it exists # because the obvious implementation ("does the body contain the directive?") is wrong in a way # that is invisible until abused: a quoted directive would re-arm an override, a bare directive # would waive review with no stated reason, and an override posted against commit A would go on # covering commit B forever. A guard is worth nothing until somebody has watched it refuse, which # is the same reasoning as ci/tests/decisions-log.test.sh one layer up. # # The parser is pure and offline BY DESIGN — authorisation (the live permission lookup) lives in # ci/approval-policy.sh, which cannot be tested without Gitea. That split is what makes this file # possible, and it is also why a green run here does NOT prove the stage authorises correctly. set -uo pipefail CI_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" SUT="${CI_DIR}/approval-override.py" PASS=0 FAIL=0 ok() { printf ' ok %s\n' "$*"; PASS=$((PASS+1)); } bad() { printf ' FAIL %s\n' "$*"; FAIL=$((FAIL+1)); } HEAD_TIME="2026-10-01T12:00:00Z" AFTER="2026-10-01T12:30:00Z" BEFORE="2026-10-01T11:30:00Z" # run -> stdout of the parser (stderr is diagnostic only) run() { COMMENTS_JSON="$1" HEAD_TIME="${2:-$HEAD_TIME}" DIRECTIVE="${3:-/approve-override}" \ python3 "$SUT" 2>/dev/null } # comment comment() { python3 -c ' import json, sys print(json.dumps([{"user": {"login": sys.argv[1]}, "created_at": sys.argv[2], "body": sys.argv[3]}])) ' "$1" "$2" "$3" } expect_none() { local label="$1" out out="$(run "$2")" if [ -z "$out" ]; then ok "$label"; else bad "$label (got: ${out})"; fi } expect_user() { local label="$1" json="$2" want="$3" out got out="$(run "$json")" got="$(cut -f1 <<<"$out")" if [ "$got" = "$want" ]; then ok "$label"; else bad "$label (wanted ${want}, got '${got}')"; fi } expect_reason() { local label="$1" json="$2" want="$3" out got out="$(run "$json")" got="$(cut -f3- <<<"$out")" if [ "$got" = "$want" ]; then ok "$label"; else bad "$label (wanted '${want}', got '${got}')"; fi } echo "== ci/approval-override.py" # --- the happy path ------------------------------------------------------------------- expect_user "a directive with a reason, posted after the head commit, is selected" \ "$(comment jakman85 "$AFTER" '/approve-override sole admin, gate is green')" jakman85 expect_reason "the reason is returned verbatim" \ "$(comment jakman85 "$AFTER" '/approve-override sole admin, gate is green')" \ 'sole admin, gate is green' # --- absence is a normal answer, not an error ----------------------------------------- expect_none "no comments at all" '[]' expect_none "an ordinary comment" "$(comment jakman85 "$AFTER" 'looks good to me')" # --- a reason is MANDATORY ------------------------------------------------------------ expect_none "a bare directive (no reason) is refused" \ "$(comment jakman85 "$AFTER" '/approve-override')" expect_none "a directive followed by only whitespace is refused" \ "$(comment jakman85 "$AFTER" '/approve-override ')" # --- the directive must START a line -------------------------------------------------- expect_none "the directive mid-sentence does not count" \ "$(comment jakman85 "$AFTER" 'you could just /approve-override this one')" expect_none "a QUOTED directive does not re-arm an override" \ "$(comment jakman85 "$AFTER" '> /approve-override quoting someone else')" expect_user "leading whitespace before the directive is fine" \ "$(comment jakman85 "$AFTER" ' /approve-override indented but mine')" jakman85 expect_user "the directive on a later line of a longer comment counts" \ "$(comment jakman85 "$AFTER" 'some preamble /approve-override the real reason here')" jakman85 # --- staleness: an override must post-date the commit it waives review on ------------- expect_none "an override OLDER than the head commit is dropped as stale" \ "$(comment jakman85 "$BEFORE" '/approve-override stale, predates the push')" expect_none "an override exactly AT the head commit time is dropped (strictly newer)" \ "$(comment jakman85 "$HEAD_TIME" '/approve-override same instant')" # --- malformed input is never a free pass -------------------------------------------- expect_none "an unreadable timestamp drops the candidate" \ "$(comment jakman85 'not-a-date' '/approve-override bad clock')" expect_none "a comment with no author is dropped" \ '[{"user": {}, "created_at": "2026-10-01T12:30:00Z", "body": "/approve-override no login"}]' expect_none "invalid JSON yields no override (and never a traceback into stdout)" \ 'this is not json' expect_none "a JSON object instead of a list yields no override" \ '{"user": "nope"}' # --- latest wins ---------------------------------------------------------------------- TWO='[ {"user": {"login": "early"}, "created_at": "2026-10-01T12:10:00Z", "body": "/approve-override first"}, {"user": {"login": "latest"}, "created_at": "2026-10-01T12:40:00Z", "body": "/approve-override second"} ]' expect_user "the LATEST override supersedes an earlier one" "$TWO" latest expect_reason "and brings its own reason" "$TWO" second # --- offsets, not just Z -------------------------------------------------------------- # Gitea emits RFC3339 WITH AN OFFSET (measured: 2026-10-01T23:09:08-05:00), not a trailing Z. # A parser that only handles 'Z' silently drops every real override, so this case is load-bearing. expect_user "an RFC3339 offset timestamp (-05:00), as Gitea actually emits, parses" \ '[{"user": {"login": "jakman85"}, "created_at": "2026-10-01T08:30:00-05:00", "body": "/approve-override offset form"}]' \ jakman85 expect_none "and an offset timestamp that is genuinely earlier is still stale" \ '[{"user": {"login": "jakman85"}, "created_at": "2026-10-01T06:00:00-05:00", "body": "/approve-override offset, stale"}]' # --- the directive is configurable ---------------------------------------------------- out="$(run "$(comment jakman85 "$AFTER" '/admin-waive because policy says so')" "$HEAD_TIME" '/admin-waive')" if [ "$(cut -f1 <<<"$out")" = "jakman85" ]; then ok "a custom directive from the declaration is honoured" else bad "a custom directive from the declaration is honoured (got '${out}')" fi expect_none "the default directive does not match a custom-directive comment" \ "$(comment jakman85 "$AFTER" '/admin-waive because policy says so')" # --- no staleness anchor: do not invent one ------------------------------------------- out="$(COMMENTS_JSON="$(comment jakman85 "$BEFORE" '/approve-override no anchor')" \ HEAD_TIME="" DIRECTIVE=/approve-override python3 "$SUT" 2>/dev/null)" if [ "$(cut -f1 <<<"$out")" = "jakman85" ]; then ok "with no HEAD_TIME the staleness test is skipped, not faked (caller blocks instead)" else bad "with no HEAD_TIME the candidate should still be returned (got '${out}')" fi printf '\n %d passed, %d failed\n' "$PASS" "$FAIL" [ "$FAIL" -eq 0 ] || exit 1