"""Structured preflight reports. A preflight run writes both a machine-readable ``preflight.json`` (the contract a future publish step will consume and re-verify) and a human ``preflight.txt``. """ from __future__ import annotations import json from pathlib import Path REPORTS_RELPATH = Path("build") / "release" / "reports" SCHEMA_VERSION = 1 def reports_root(repo_root: Path, override: Path | None = None) -> Path: return Path(override) if override else Path(repo_root) / REPORTS_RELPATH def render_text(payload: dict) -> str: git = payload.get("git") or {} interpreter = payload.get("interpreter") or {} lines = [ f"orisys release preflight :: version {payload.get('version')}", f" result: {'PASS' if payload.get('ok') else 'FAIL'}", f" git: {git.get('branch')} @ {git.get('commit')} (dirty={git.get('dirty')})", f" interpreter: {interpreter.get('version')} at {interpreter.get('executable')}", f" duration: {payload.get('duration_s')}s", "", ] for step in payload.get("steps", []): flag = "ok " if step.get("ok") else "FAIL" lines.append(f"[{flag}] {step.get('name')} ({step.get('duration_s')}s)") for detail_line in str(step.get("detail") or "").splitlines(): lines.append(f" {detail_line}") lines.append("") wheels = payload.get("wheels") or [] if wheels: lines.append("wheels:") for wheel in wheels: lines.append( f" {wheel.get('name')} {wheel.get('size')} bytes sha256={wheel.get('sha256')}" ) lines.append("") options = payload.get("options") or {} waived = [ key for key, value in options.items() if value and key in {"skip_tests", "allow_dirty", "force", "no_runtime", "no_assets"} ] if waived: lines.append(f"waived guards: {', '.join(sorted(waived))}") lines.append("") return "\n".join(lines).rstrip() + "\n" def write_report(payload: dict, out_dir: Path) -> tuple[Path, Path]: out_dir = Path(out_dir) out_dir.mkdir(parents=True, exist_ok=True) payload = {**payload, "schema": SCHEMA_VERSION} json_path = out_dir / "preflight.json" text_path = out_dir / "preflight.txt" json_path.write_text(json.dumps(payload, indent=2, sort_keys=False), encoding="utf-8") text_path.write_text(render_text(payload), encoding="utf-8") return json_path, text_path