#!/usr/bin/env python3 """Sync the canon classification allowed-values into the chart (CUST-WP-0067-T09). The State Hub validates repository classification against ``the-custodian/canon/standards/repo-classification.allowed.yaml``. That file is canon and must stay authoritative, but a container has no the-custodian checkout, so a copy has to travel with the release. A copy that nobody checks is a copy that silently drifts. This script owns the copy: ``--check`` fails when it diverges from canon, so the release can refuse to ship a stale vocabulary rather than validate against yesterday's rules. Usage: python scripts/sync_classification_allowed.py # write the copy python scripts/sync_classification_allowed.py --check # verify, exit 1 on drift """ from __future__ import annotations import argparse import difflib import sys from pathlib import Path REPO_ROOT = Path(__file__).resolve().parent.parent CHART_COPY = ( REPO_ROOT / "deploy/railiance/apps/charts/state-hub/files/repo-classification.allowed.yaml" ) CANON_CANDIDATES = ( Path("/home/worsch/the-custodian/canon/standards/repo-classification.allowed.yaml"), Path("/home/tegwick/the-custodian/canon/standards/repo-classification.allowed.yaml"), REPO_ROOT.parent / "the-custodian/canon/standards/repo-classification.allowed.yaml", ) HEADER = ( "# GENERATED — do not edit.\n" "# Synced from the-custodian/canon/standards/repo-classification.allowed.yaml\n" "# by scripts/sync_classification_allowed.py (CUST-WP-0067-T09).\n" "# Canon is authoritative; this copy exists only so the container has one.\n" ) def find_canon() -> Path: for candidate in CANON_CANDIDATES: if candidate.is_file(): return candidate raise SystemExit( "ERROR: canon allowed-values not found. Looked in:\n " + "\n ".join(str(c) for c in CANON_CANDIDATES) ) def main() -> int: parser = argparse.ArgumentParser(description=__doc__) parser.add_argument( "--check", action="store_true", help="Verify the chart copy matches canon; exit 1 on drift", ) args = parser.parse_args() canon = find_canon() desired = HEADER + canon.read_text(encoding="utf-8") if args.check: if not CHART_COPY.is_file(): print(f"DRIFT: {CHART_COPY} is missing; run without --check to create it") return 1 current = CHART_COPY.read_text(encoding="utf-8") if current != desired: print(f"DRIFT: chart copy differs from canon ({canon})") sys.stdout.writelines( difflib.unified_diff( current.splitlines(keepends=True), desired.splitlines(keepends=True), fromfile="chart copy", tofile="canon", ) ) return 1 print(f"OK: chart copy matches canon ({canon})") return 0 CHART_COPY.parent.mkdir(parents=True, exist_ok=True) CHART_COPY.write_text(desired, encoding="utf-8") print(f"Synced {canon} -> {CHART_COPY}") return 0 if __name__ == "__main__": raise SystemExit(main())