Skip to content

Commit 3002d6f

Browse files
committed
ci: fail CI gates when their exemption entries go stale
A moved or renamed file silently disarms the entry that named it, letting new violations through instead of being caught. Both check_authorized_dispatch.py and check_reconstructed_sql.py now scan their exemption tables for entries that no longer match any file or occurrence and fail the gate if any are found, and the now-dead sql_loop.rs reference is dropped.
1 parent 894586c commit 3002d6f

2 files changed

Lines changed: 71 additions & 1 deletion

File tree

‎scripts/ci/check_authorized_dispatch.py‎

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,6 @@
103103
("control/array_sync/inbound.rs", "into_scope"),
104104
("control/array_sync/inbound_propose.rs", "into_scope"),
105105
("control/array_sync/snapshot_assembly.rs", "into_scope"),
106-
("control/server/native/dispatch/sql_loop.rs", "into_physical_task"),
107106
("control/server/native/dispatch/sql_dispatch_task.rs", "into_physical_task"),
108107
("control/server/sync/raft_dispatch/response.rs", "propose_sync_write"),
109108
("control/server/sync/raft_dispatch/write.rs", "propose_sync_write"),
@@ -266,6 +265,35 @@ def public_raw_api_violations(rel: str, source: str) -> list[tuple[int, str]]:
266265
return found
267266

268267

268+
def stale_exemptions() -> list[str]:
269+
"""Report exemptions that no longer name a live occurrence.
270+
271+
An exemption is keyed on (path, symbol). Move the file or rename the
272+
symbol and the entry stops matching anything — it does not fail, it
273+
silently stops being an exemption, and the next occurrence added to
274+
that path is waved through instead of being caught. Both halves of
275+
this gate have already been disarmed that way by an ordinary file
276+
move, so a dead entry is treated as a gate failure, not as tidiness.
277+
278+
The symbol is looked for in masked source, so an entry kept alive only
279+
by a comment or a string literal still reports as dead.
280+
"""
281+
stale: list[str] = []
282+
for label, exemptions in (
283+
("ALLOWED_DEFINITIONS", ALLOWED_DEFINITIONS),
284+
("ALLOWED_REFERENCES", ALLOWED_REFERENCES),
285+
):
286+
for rel, name in sorted(exemptions):
287+
path = SRC / rel
288+
if not path.is_file():
289+
stale.append(f"{label}: ({rel!r}, {name!r}) names a file that does not exist")
290+
continue
291+
masked = mask_rust(path.read_text(encoding="utf-8"))
292+
if not re.search(rf"\b{re.escape(name)}\b", masked):
293+
stale.append(f"{label}: ({rel!r}, {name!r}) matches no occurrence in that file")
294+
return stale
295+
296+
269297
def main() -> int:
270298
parser = argparse.ArgumentParser()
271299
parser.add_argument("--self-test", action="store_true")
@@ -274,6 +302,17 @@ def main() -> int:
274302
self_test()
275303
return 0
276304

305+
stale = stale_exemptions()
306+
if stale:
307+
print("ERROR: stale exemptions — the gate is disarmed where they point:", file=sys.stderr)
308+
for entry in stale:
309+
print(f" {entry}", file=sys.stderr)
310+
print(
311+
"Repoint each entry at the code's current location, or drop it if the seam is gone.",
312+
file=sys.stderr,
313+
)
314+
return 1
315+
277316
errors: list[str] = []
278317
for path in SRC.rglob("*.rs"):
279318
rel = path.relative_to(SRC).as_posix()

‎scripts/ci/check_reconstructed_sql.py‎

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -871,12 +871,43 @@ def self_test() -> int:
871871
return 1 if failed else 0
872872

873873

874+
def stale_canonical_helpers() -> list[str]:
875+
"""Report PATH_CANONICAL_HELPERS entries that no longer name live code.
876+
877+
Each entry widens the gate for one file: the named helpers are read as
878+
canonical there, so a bare call to one stops counting as unquoted
879+
interpolation. The key is a path. Move the file and the entry keeps
880+
widening nothing, while the helpers at their new home silently lose
881+
their canonical status and the file starts reporting false violations —
882+
which is how this gate came to fail on every pull request. A dead entry
883+
is therefore a gate failure, not tidiness.
884+
"""
885+
stale: list[str] = []
886+
for rel, helpers in sorted(PATH_CANONICAL_HELPERS.items()):
887+
path = RUST_ROOT / rel
888+
if not path.is_file():
889+
stale.append(f"{rel!r} names a file that does not exist")
890+
continue
891+
source = path.read_text(encoding="utf-8")
892+
for helper in sorted(helpers):
893+
if not re.search(rf"\b{re.escape(helper)}\b", source):
894+
stale.append(f"{rel!r} exempts {helper!r}, which does not appear in that file")
895+
return stale
896+
897+
874898
def main() -> int:
875899
parser = argparse.ArgumentParser()
876900
parser.add_argument("--self-test", action="store_true")
877901
args = parser.parse_args()
878902
if args.self_test:
879903
return self_test()
904+
stale = stale_canonical_helpers()
905+
if stale:
906+
print("FAIL: stale canonical-helper exemptions — the gate is misaimed where they point:")
907+
for entry in stale:
908+
print(f" {entry}")
909+
print("\nRepoint each entry at the code's current location, or drop it if the helper is gone.")
910+
return 1
880911
findings = scan_paths(path for root in SCAN_ROOTS for path in root.rglob("*.rs"))
881912
if findings:
882913
print(f"FAIL: {len(findings)} reconstructed-SQL gate violation(s):")

0 commit comments

Comments
 (0)