The API validates repo classification against the-custodian canon allowed values. A container has no such checkout, so every classification write failed with a 500 and classification could only ever be written from a workstation. Mounts the vocabulary as a ConfigMap and points REPO_CLASSIFICATION_ALLOWED_PATH at it. The copy is the risk, so it is owned rather than trusted: scripts/sync_classification_allowed.py regenerates it from canon and --check fails on drift. make check-classification-allowed and make railiance-state-hub-render both refuse to proceed when the copy diverges, so a release cannot silently validate against a stale vocabulary. The container volumeMounts and env blocks are merged rather than appended — a second pair would have produced duplicate YAML keys as soon as sweep was re-enabled. Refs CUST-WP-0067-T09 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Assistant: claude-code Assistant-Model: opus Assistant-Process: 2583210@bnt-lap001 Assistant-Session: f2bff2d5-e9b2-4338-92ca-10282a927006
91 lines
3.1 KiB
Python
Executable file
91 lines
3.1 KiB
Python
Executable file
#!/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())
|