mirror of
https://github.com/harvard-edge/cs249r_book.git
synced 2026-05-06 17:49:07 -05:00
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
66 lines
2.0 KiB
Python
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())
|