from __future__ import annotations """Command-line entry point for publishing CI test metrics.""" import argparse import json from pathlib import Path from .summary import load_junit_summary, publish_quality_metrics def _build_parser() -> argparse.ArgumentParser: """Build the CLI parser for the metrics publisher.""" parser = argparse.ArgumentParser(description="Publish test-suite metrics to Pushgateway") parser.add_argument("--gateway", required=True, help="Pushgateway base URL") parser.add_argument("--suite", required=True, help="Logical suite name") parser.add_argument("--job", default="platform-quality-ci", help="Pushgateway job label") parser.add_argument("--status", choices=("ok", "failed"), required=True, help="Gate outcome") parser.add_argument("--junit", nargs="*", default=(), help="JUnit XML files to aggregate") parser.add_argument("--quality-report", default="build/quality-gate.json", help="Quality gate JSON report") return parser def _load_quality_report(path: Path) -> tuple[float, int]: """Read workspace coverage/LOC summary from the quality gate JSON output.""" if not path.exists(): return 0.0, 0 payload = json.loads(path.read_text(encoding="utf-8")) coverage = payload.get("workspace_line_coverage_percent") if not isinstance(coverage, (int, float)): coverage = 0.0 source_lines = payload.get("source_lines_over_500") if not isinstance(source_lines, int): source_lines = 0 return float(coverage), int(source_lines) def main(argv: list[str] | None = None) -> int: """Parse arguments, aggregate JUnit files, and publish metrics.""" parser = _build_parser() args = parser.parse_args(argv) summary = load_junit_summary(Path(path) for path in args.junit) coverage_percent, source_lines_over_500 = _load_quality_report(Path(args.quality_report)) publish_quality_metrics( gateway=args.gateway, suite=args.suite, job=args.job, status=args.status, summary=summary, workspace_line_coverage_percent=coverage_percent, source_lines_over_500=source_lines_over_500, ) return 0 if __name__ == "__main__": raise SystemExit(main())