Files
felhom-controller/controller/scripts/test_controller_gates.py
T
admin 8cb3d7af91 gates: one entry point (controller/scripts/controller_gates.py) + pre-push hook
A census of all thirteen gate scripts across the four felhom repos on 2026-08-02 found that
every check a CLAUDE.md names was passing and two of the four nobody is told to run were
failing. This repo had seven gates and CLAUDE.md named two; four more were reachable only via
a line in REUSE.md, and docker_run_volume_path_gate.py — RED at census time — through one line
in REUSE.md and nothing else.

controller_gates.py runs all seven plus reuse_refs_check on the repo root, streams each gate's
own output, and exits worst-wins non-zero. The shared reuse checker stays in felhom.eu/scripts/
and is invoked across the workspace — never copied here, which would recreate the drift it
detects; an absent sibling clone FAILS the gate and prints the path tried.

.githooks/pre-push runs it with --fast and refuses the push. Per-clone and --no-verify-able,
both stated in the hook itself; a manual run WARNS when the clone is unarmed.

test_controller_gates.py is a SEAM test — it asserts each member gate's own distinctive stdout,
not the runner's summary line. Red-proofed: an inert run_gate still prints 'all controller
gates OK' and exits 0, and turns the seam test red.

Tooling only: no Go change, no image build, no deploy, no version bump.
2026-08-02 15:22:53 +02:00

69 lines
2.8 KiB
Python

# -*- coding: utf-8 -*-
"""Seam test for scripts/controller_gates.py.
Run from controller/: python3 scripts/test_controller_gates.py
WHY THIS EXISTS. An entry point is a seam by definition: a runner that LISTS a gate but never
executes it is inert and fully green, and this project has shipped an inert seam four times. So
the assertion is on each member gate's OWN distinctive stdout — never on the runner's summary
line, which the runner can print without ever calling anything — plus the exit code, which is a
runner's actual effect.
Red-proofed 2026-08-02: replacing run_gate's body with `return 0` (the inert runner) turns
test_every_member_gate_actually_ran red while the summary still prints "all controller gates OK".
"""
import os
import subprocess
import sys
import unittest
SCRIPTS = os.path.dirname(os.path.abspath(__file__))
CTRL = os.path.dirname(SCRIPTS)
ENTRY = os.path.join(SCRIPTS, "controller_gates.py")
# (label, a substring only THAT gate can print)
FINGERPRINTS = [
("template-id", "integrity gate OK — every JS element-ID reference"),
("emoji", "emoji gate OK"),
("native-confirm", "native-confirm gate OK"),
("offbox-rename", "offbox rename gate OK"),
("app-row-dedup", "app_row_dedup_gate: OK"),
("mojibake", "mojibake_gate: OK"),
("docker-v", "docker -v gate OK"),
("reuse-refs", "cited paths — exact"),
]
class ControllerGatesTest(unittest.TestCase):
@classmethod
def setUpClass(cls):
p = subprocess.run([sys.executable, ENTRY, "--fast"], cwd=CTRL,
stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
cls.rc = p.returncode
cls.out = p.stdout.decode("utf-8", "replace")
def test_exit_code_is_zero(self):
self.assertEqual(self.rc, 0, self.out)
def test_every_member_gate_actually_ran(self):
for label, fingerprint in FINGERPRINTS:
self.assertIn(fingerprint, self.out,
"gate %r is listed but its own output never appeared — an inert runner "
"prints the summary without calling anything:\n%s" % (label, self.out))
def test_shared_reuse_checker_is_not_copied_into_this_repo(self):
"""It lives in felhom.eu/scripts/ and is invoked across the workspace. A copy here would
recreate exactly the drift it exists to detect."""
self.assertFalse(os.path.exists(os.path.join(SCRIPTS, "reuse_refs_check.py")),
"reuse_refs_check.py must NOT be copied into this repo")
def test_unknown_argument_is_rejected(self):
p = subprocess.run([sys.executable, ENTRY, "--nope"], cwd=CTRL,
stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
self.assertEqual(p.returncode, 2, p.stdout.decode("utf-8", "replace"))
if __name__ == "__main__":
unittest.main(verbosity=2)