"""Render HTML report from Pulumi + HTTP coverage results."""
from __future__ import annotations
import html
import json
from datetime import UTC, datetime
from pathlib import Path
from typing import Any
SERIES_ORDER = ("yoga", "antelope", "caracal", "dalmatian")
def _methods_line(methods: dict[str, Any]) -> str:
return " ".join(f"{m}={methods.get(m, 0)}" for m in ("GET", "POST", "PUT", "PATCH", "DELETE"))
def render_html(summary: dict[str, Any], series_reports: list[dict[str, Any]]) -> str:
generated = datetime.now(UTC).strftime("%Y-%m-%d %H:%M:%S UTC")
cards = []
for rep in series_reports:
series = html.escape(str(rep.get("series", "?")))
pu = rep.get("pulumi", {})
http = rep.get("http", {})
cards.append(
f"""
{series}
pulumi_openstack + HTTP pack probe
pulumi exports ok={len(pu.get("outputs", {})) - len(pu.get("empty_exports", []))}
empty exports={len(pu.get("empty_exports", []))}
http ok={http.get("ok_count", 0)}
http fail={http.get("fail_count", 0)} nonempty_fail={http.get("nonempty_fail_count", 0)}
http total={http.get("total", 0)}/{http.get("expected_ops", "?")}
methods: {html.escape(_methods_line(http.get("methods") or {}))}
{" · coverage incomplete" if http.get("coverage_incomplete") else ""}
"""
)
detail_rows = []
for rep in series_reports:
series = rep.get("series", "?")
for item in rep.get("http", {}).get("failures", [])[:500]:
detail_rows.append(
''
f"| {html.escape(str(series))} | "
f"{html.escape(str(item.get('service', '')))} | "
f"{html.escape(str(item.get('operation_id', '')))} | "
f"{html.escape(str(item.get('method', '')))} | "
f"{html.escape(str(item.get('path', '')))} | "
f"{html.escape(str(item.get('status', '')))} | "
f"{html.escape(str(item.get('detail', ''))[:240])} | "
"
"
)
for empty in rep.get("pulumi", {}).get("empty_exports", []):
detail_rows.append(
''
f"| {html.escape(str(series))} | "
f"pulumi_openstack | "
f"export_nonempty | "
f"— | export | — | "
f"{html.escape(str(empty))} | "
"
"
)
return f"""
Pulumi OpenStack coverage
{summary.get("series_count", 0)} series
{summary.get("pulumi_ok", 0)} pulumi stacks ok
{summary.get("pulumi_fail", 0)} pulumi failures
{summary.get("http_ok", 0)} http ops ok
{summary.get("http_fail", 0)} http / nonempty fails
Series
{"".join(cards)}
Failures
| Series | Service | Operation | Method | Path | HTTP | Detail |
{"".join(detail_rows) if detail_rows else '| No failures |
'}
"""
def write_html(
report_dir: Path, summary: dict[str, Any], series_reports: list[dict[str, Any]]
) -> Path:
path = report_dir / "pulumi-report.html"
path.write_text(render_html(summary, series_reports), encoding="utf-8")
return path
def load_series_files(report_dir: Path) -> list[dict[str, Any]]:
out = []
for series in SERIES_ORDER:
path = report_dir / f"series-{series}.json"
if path.exists():
out.append(json.loads(path.read_text(encoding="utf-8")))
return out