Files
app-catalog-felhom.eu/.githooks/pre-push
T
admin c3e4bb18c7 gates: catalog_gates --fast + pre-push hook
--fast selects only gates that touch no network and no container runtime: gate 1
(check-image-pins) runs, image-resolvable and volume-persistence do NOT. Default behaviour with
no flag is unchanged. The skip is ANNOUNCED with the reason and with what still owes a periodic
run — a silently narrowed run reads as 'covered everything' when it did not.

Why the runtime gates are never in a hook: a push that pulls images and starts containers gets
bypassed within a week, and the bypass becomes the habit. They stay deliberate periodic runs at
the start of a catalog campaign, before a publish train, and when a template's volumes: block or
image tag changes — on a scratch host, never a customer box.

.githooks/pre-push runs catalog_gates.py --fast and refuses the push. Per-clone and
--no-verify-able, both stated in the hook itself.

test_catalog_gates.py pins --fast's CONTENT, not just its exit code: the runtime gates must not
run, the skip must be announced, and the no-flag path must still select all three. Red-proofed:
an inert run_gate turns it red.
2026-08-02 15:23:08 +02:00

48 lines
2.4 KiB
Bash
Executable File

#!/bin/sh
# pre-push — refuse a push that carries a broken gate. (2026-08-02, R-29 leg (b) first half.)
#
# Runs this repo's ONE gate entry point in --fast mode: only checks that touch no network and no
# container runtime, so a push stays a push and never pulls images or starts containers. The slow
# gates stay deliberate periodic runs; a hook that takes minutes gets bypassed within a week and
# the bypass becomes the habit.
#
# BOTH LINES BELOW ARE DELIBERATE. An absent log line is not evidence a hook ran — a silent pass is
# equally consistent with "gates green" and "hook never fired", so a passing push says so out loud.
#
# HONEST LIMITS, stated so this is not mistaken for enforcement it cannot provide:
# * per-clone — core.hooksPath is local config and a clone does not carry it. Arm a clone once:
# git config core.hooksPath .githooks
# Any manual entry-point run WARNS when the clone is unarmed.
# * skippable — `git push --no-verify` bypasses this entirely. That is on purpose: an escape
# hatch that cannot be reached is one that gets removed the first time it is
# inconvenient. USING IT MUST BE STATED IN THE SESSION REPORT.
# The half that is neither per-clone nor skippable is CI — felhom.eu OPEN-ITEMS.md R-168.
#
# Measured 2026-08-02 (git 2.47.3): a relative core.hooksPath resolves correctly and the hook's cwd
# is the repo root whether `git push` is issued from the root or from any subdirectory. The
# explicit rev-parse below does not depend on that.
set -u
root=$(git rev-parse --show-toplevel 2>/dev/null) || {
echo "pre-push: FAIL - cannot resolve the repo root (git rev-parse --show-toplevel)." >&2
exit 1
}
cd "$root" || exit 1
if ! command -v python3 >/dev/null 2>&1; then
echo "pre-push: FAIL - python3 not found, so the gates CANNOT run. This is a failure, never a" >&2
echo " pass by default. Install python3, or push with --no-verify and say so." >&2
exit 1
fi
echo "pre-push [app-catalog-felhom.eu]: running scripts/catalog_gates.py --fast ..."
python3 "scripts/catalog_gates.py" --fast
rc=$?
if [ "$rc" -ne 0 ]; then
echo "pre-push [app-catalog-felhom.eu]: PUSH REFUSED - gates exited $rc. Fix the finding above, or bypass with" >&2
echo " 'git push --no-verify' and state that you did in the session report." >&2
else
echo "pre-push [app-catalog-felhom.eu]: gates OK - push proceeding."
fi
exit $rc