publish the runtime spec; gate guard

This commit is contained in:
2026-08-28 14:04:10 -04:00
parent e60945e56e
commit 98badcbc26
3 changed files with 21102 additions and 1 deletions

101
scripts/check-gates-ran.sh Executable file
View File

@@ -0,0 +1,101 @@
#!/usr/bin/env bash
#
# Prove the gates actually RAN.
#
# Several checks skip themselves when the file they read is absent:
#
# tests/test_api_inventory_parity.py skipif docs/api-inventory.json missing
# tests/test_openapi_spec.py skipif docs/openapi.json missing
# tests/test_docs_publishable.py skipif docs/ missing
#
# That is correct in a published checkout, where docs/ becomes the wiki and
# there is genuinely nothing to check. It was silently wrong on GitHub, which
# runs against exactly that checkout: the modules skipped, CI reported green,
# and an outside branch added nine routes documented nowhere and passed.
#
# So the list is split. Some gates must run everywhere; the docs-dependent ones
# must run HERE, where the files exist, and are allowed to be absent there.
#
# A gate that stops running is worse than no gate: nobody looks at it again.
# This asserts each named module reported at least one PASS and no SKIPS.
#
# Usage:
# bash scripts/check-gates-ran.sh # runs the gates itself
# bash scripts/check-gates-ran.sh report.txt # reads an existing -rs report
set -uo pipefail
cd "$(dirname "$0")/.."
# Gates that must run in EVERY checkout, published or internal. A skip here is
# always a fault.
GATES_EVERYWHERE=(
"tests/test_openapi_spec.py"
"tests/test_core/test_public_read_surface.py"
"tests/test_core/test_authz.py"
"tests/test_plugin_migrations.py"
)
# Gates that need files the publication export deliberately leaves behind -
# docs/ becomes the wiki, so a published checkout genuinely has nothing to check
# and skipping is correct there. In THIS repo, skipping means something broke.
GATES_INTERNAL_ONLY=(
"tests/test_api_inventory_parity.py"
"tests/test_docs_publishable.py"
)
# A published checkout is one with no docs/ prose. openapi.json alone does not
# make it internal: that file ships because the app serves it at runtime.
if compgen -G "docs/*.md" > /dev/null; then
GATES=("${GATES_EVERYWHERE[@]}" "${GATES_INTERNAL_ONLY[@]}")
echo "==> Internal checkout: every gate must run"
else
GATES=("${GATES_EVERYWHERE[@]}")
echo "==> Published checkout: docs-dependent gates are expected to be absent"
fi
PYTHON="${PYTHON:-python}"
[ -x venv/bin/python ] && PYTHON=venv/bin/python
report="${1:-}"
if [ -z "$report" ]; then
report="$(mktemp)"
# -rs lists every skip with its reason, which is the thing being checked.
"$PYTHON" -m pytest "${GATES[@]}" -q -rs > "$report" 2>&1 || true
fi
echo "==> Checking that every gate ran"
failed=0
for gate in "${GATES[@]}"; do
if [ ! -f "$gate" ]; then
echo " MISSING $gate - the file is not in this checkout"
failed=1
continue
fi
if grep -q "SKIPPED.*$(basename "$gate")" "$report"; then
reason=$(grep "SKIPPED.*$(basename "$gate")" "$report" | head -1 | sed 's/.*-- //')
echo " SKIPPED $gate"
echo " reason: ${reason:-not given}"
failed=1
continue
fi
echo " ran $gate"
done
if grep -qE "^[0-9]+ failed|error" "$report"; then
echo
echo "Gate tests FAILED (not merely skipped):"
grep -E "^FAILED|^ERROR" "$report" | sed 's/^/ /'
failed=1
fi
echo
if [ "$failed" -ne 0 ]; then
echo "FAIL: a gate did not run. A skipped gate reports green and checks nothing."
echo " If a docs-dependent gate skipped in THIS repo, the file it reads"
echo " was not generated: run scripts/gen_openapi.py and"
echo " scripts/gen_project_map.py. If one skipped in the PUBLISHED repo,"
echo " the export dropped a file the gate needs - see tools/export-github.sh."
exit 1
fi
echo "All gates ran."