"""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", "HEAD") ) 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)} critical={http.get("critical", 0)} http total={http.get("total", 0)}/{http.get("expected_ops", "?")} (declared={http.get("declared_ops", "?")}+HEAD={http.get("head_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

Pulumi OpenStack API coverage

Generated {html.escape(generated)} · 100% = HTTP contract matrix (pack ops + synthetic HEAD), not pulumi_openstack resource count. Layer B provider lifecycle is smoke only.

{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

{"".join(detail_rows) if detail_rows else ''}
SeriesServiceOperationMethodPathHTTPDetail
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