"""Write JSON + self-contained HTML coverage reports."""
from __future__ import annotations
import html
import json
from pathlib import Path
from typing import Any
def write_reports(payload: dict[str, Any], report_dir: Path) -> tuple[Path, Path]:
report_dir.mkdir(parents=True, exist_ok=True)
json_path = report_dir / "pulumi-contract-coverage.json"
html_path = report_dir / "pulumi-contract-coverage.html"
json_path.write_text(json.dumps(payload, indent=2) + "\n", encoding="utf-8")
html_path.write_text(render_html(payload), encoding="utf-8")
return json_path, html_path
def render_html(payload: dict[str, Any]) -> str:
totals = payload.get("totals") or {}
methods = payload.get("methods") or {}
series_rows = []
for s in payload.get("series") or []:
series_rows.append(
"
"
f"| {html.escape(str(s.get('series')))} | "
f"{html.escape(str(s.get('api_version')))} | "
f"{s.get('total', 0)} | "
f"{s.get('passed', 0)} | "
f"{s.get('failed', 0)} | "
f"{s.get('skipped', 0)} | "
f"{s.get('duration_ms', 0):.0f} ms | "
"
"
)
method_rows = []
for method, count in sorted(methods.items()):
method_rows.append(
""
f"| {html.escape(str(method))} | "
f"{count} | "
"
"
)
if not method_rows:
method_rows.append("| No methods recorded. |
")
failed = [r for r in (payload.get("results") or []) if r.get("status") == "failed"]
fail_rows = []
for r in failed[:500]:
fail_rows.append(
""
f"| {html.escape(str(r.get('series')))} | "
f"{html.escape(str(r.get('operation_id')))} | "
f"{html.escape(str(r.get('method')))} | "
f"{html.escape(str(r.get('path_template')))} | "
f"{html.escape(str(r.get('http_status')))} | "
f"{html.escape(str(r.get('detail') or '')[:180])} | "
"
"
)
if not fail_rows:
fail_rows.append("| No failures. |
")
# Compact sample of passed ops (first 100) for confidence
passed = [r for r in (payload.get("results") or []) if r.get("status") == "passed"]
pass_sample = []
for r in passed[:100]:
pass_sample.append(
""
f"| {html.escape(str(r.get('series')))} | "
f"{html.escape(str(r.get('operation_id')))} | "
f"{html.escape(str(r.get('method')))} | "
f"{html.escape(str(r.get('http_status')))} | "
f"{r.get('duration_ms', 0)} | "
"
"
)
return f"""
oVirt Pulumi contract coverage
oVirt Pulumi contract coverage
Generated {html.escape(str(payload.get('generated_at')))}
ยท Engine {html.escape(str(payload.get('engine_url')))}
Total
{totals.get('total', 0)}
Passed
{totals.get('passed', 0)}
Failed
{totals.get('failed', 0)}
Skipped
{totals.get('skipped', 0)}
By HTTP method
| Method | Count |
{''.join(method_rows)}
By series
| Series | API | Total | Passed | Failed | Skipped | Duration |
{''.join(series_rows)}
Failures (up to 500)
| Series | Operation | Method | Path | HTTP | Detail |
{''.join(fail_rows)}
Passed sample (first 100)
| Series | Operation | Method | HTTP | ms |
{''.join(pass_sample) if pass_sample else '| No passed operations. |
'}
"""