#!/usr/bin/env python3 """Fail-closed freshness checks for the local AUTO_GEN product-pack mirror.""" from __future__ import annotations import json import subprocess from datetime import datetime, timezone from pathlib import Path from typing import Any REPO_ROOT = Path(__file__).resolve().parents[2] PRODUCT_PACK_ROOT = REPO_ROOT / "packs" / "AUTO_GEN_Product-pack" LOCAL_LAST_GENERATED = PRODUCT_PACK_ROOT / ".last-generated.json" LIVE_BRANCH = "origin/product-pack-live" LIVE_LAST_GENERATED_PATH = "packs/AUTO_GEN_Product-pack/.last-generated.json" def _load_json(path: Path) -> dict[str, Any]: return json.loads(path.read_text(encoding="utf-8")) def _parse_generated_at(payload: dict[str, Any], source: str) -> datetime: raw = str(payload.get("generatedAt") or "").strip() if not raw: raise RuntimeError(f"missing generatedAt in {source}") try: return datetime.fromisoformat(raw.replace("Z", "+00:00")).astimezone(timezone.utc) except ValueError as exc: raise RuntimeError(f"invalid generatedAt in {source}: {raw}") from exc def _git_show(ref_and_path: str) -> str | None: result = subprocess.run( ["git", "show", ref_and_path], cwd=REPO_ROOT, text=True, capture_output=True, check=False, ) if result.returncode != 0: return None return result.stdout def ensure_local_mirror_is_fresh() -> None: if not LOCAL_LAST_GENERATED.exists(): raise RuntimeError(f"missing local mirror freshness marker: {LOCAL_LAST_GENERATED}") local_payload = _load_json(LOCAL_LAST_GENERATED) local_generated_at = _parse_generated_at(local_payload, str(LOCAL_LAST_GENERATED)) remote_raw = _git_show(f"{LIVE_BRANCH}:{LIVE_LAST_GENERATED_PATH}") if remote_raw is None: return remote_payload = json.loads(remote_raw) remote_generated_at = _parse_generated_at(remote_payload, f"{LIVE_BRANCH}:{LIVE_LAST_GENERATED_PATH}") if local_generated_at < remote_generated_at: raise RuntimeError( "local AUTO_GEN product-pack mirror is stale: " f"local generatedAt={local_generated_at.isoformat()} < " f"{LIVE_BRANCH} generatedAt={remote_generated_at.isoformat()}. " "Refresh from origin/product-pack-live or re-run sync-product-pack before generating diffs." )