Files
cs249r_book/interviews/vault-cli/scripts/check_registry_append_only.py
Vijay Janapa Reddi 3f9b044b31 chore(ci): rename vault-ci.yml → staffml-validate-vault.yml
Brings the last outlier workflow file into the repo-wide
<cluster>-<verb>-<scope>.yml naming convention. Every other cluster
(book, tinytorch, kits, labs, instructors, mlsysim, slides, site,
staffml) uses this pattern; vault-ci.yml was the only one that didn't.

  vault-ci.yml  →  staffml-validate-vault.yml
  name: '🎯 StaffML · 🔎 Vault CI'  →  '🎯 StaffML ·  Validate (Vault)'

Now staffml-validate-vault.yml is a direct sibling of
staffml-validate-dev.yml — the former validates the vault data + CLI
+ worker, the latter validates the site build. Same verb, different
scope, easy to reason about.

Updated references:
  .github/workflows/staffml-validate-vault.yml — self-reference in
    the paths trigger (so the workflow still fires when it's edited)
  interviews/vault/ARCHITECTURE.md §19.3 and §51 — both path refs
  interviews/vault/TESTING.md §4.1 — workflow name + display name
  interviews/vault-cli/scripts/check_registry_append_only.py — docstring

No branch-protection settings change needed — GitHub matches required
checks on the workflow's 'name:' field, not the filename. Anyone with
a bookmark to the old Actions-tab URL will get a 404 (harmless).

Other workflow naming I surveyed but deliberately LEFT alone
(all consistent with existing conventions):
  staffml-update-paper.yml      matches tinytorch-update-pdfs pattern
  staffml-auto-pr.yml           matches bot-workflow convention
  staffml-welcome.yml           single-word verb, standard
  auto-label / update-contributors / infra-* / publish-all-live
    are cross-cutting (no cluster prefix) by design
2026-04-22 11:27:37 -04:00

66 lines
2.0 KiB
Python

#!/usr/bin/env python3
"""CI check: ``id-registry.yaml`` is append-only.
Rejects PRs that remove or reorder lines from ``interviews/vault/id-registry.yaml``
— the registry is the C-5 load-bearing structure. Compares the file's lines
between the PR base and HEAD; ensures every base-line is still present and
in the same relative order.
Invoked from ``.github/workflows/staffml-validate-vault.yml``.
"""
from __future__ import annotations
import subprocess
import sys
from pathlib import Path
REGISTRY_PATH = "interviews/vault/id-registry.yaml"
def main() -> int:
base = "origin/main"
# Prefer origin/main; fall back to HEAD~1 for local testing.
try:
subprocess.run(
["git", "rev-parse", "--verify", base], check=True, capture_output=True
)
except subprocess.CalledProcessError:
base = "HEAD~1"
try:
result = subprocess.run(
["git", "show", f"{base}:{REGISTRY_PATH}"],
check=True,
capture_output=True,
text=True,
)
except subprocess.CalledProcessError:
# File didn't exist at base — first commit landing it is fine.
return 0
base_lines = result.stdout.splitlines()
head = Path(REGISTRY_PATH).read_text(encoding="utf-8").splitlines()
# Every base-line must be present in head, in the same order.
# We allow ONLY appending new lines after the existing ones.
j = 0
for i, line in enumerate(base_lines):
while j < len(head) and head[j] != line:
j += 1
if j >= len(head):
sys.stderr.write(
f"[error] {REGISTRY_PATH}: line {i+1} from base is missing or reordered "
f"at HEAD.\n base line: {line!r}\n"
)
return 1
j += 1
print(f"[ok] {REGISTRY_PATH}: append-only invariant holds "
f"({len(base_lines)} base lines preserved; "
f"{len(head) - len(base_lines)} new lines appended)")
return 0
if __name__ == "__main__":
raise SystemExit(main())