ci(metis): dedupe test case metrics before publish
This commit is contained in:
parent
3f6be39da0
commit
5d1b28a3b0
@ -6,6 +6,7 @@ from __future__ import annotations
|
|||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
import urllib.error
|
||||||
import urllib.request
|
import urllib.request
|
||||||
import xml.etree.ElementTree as ET
|
import xml.etree.ElementTree as ET
|
||||||
|
|
||||||
@ -88,6 +89,32 @@ def _load_junit_cases(path: str) -> list[tuple[str, str]]:
|
|||||||
return cases
|
return cases
|
||||||
|
|
||||||
|
|
||||||
|
def _collapse_test_cases(test_cases: list[tuple[str, str]]) -> list[tuple[str, str]]:
|
||||||
|
"""Return one final sample per test, keeping the last retry result."""
|
||||||
|
|
||||||
|
order: list[str] = []
|
||||||
|
results: dict[str, str] = {}
|
||||||
|
for test_id, status in test_cases:
|
||||||
|
if test_id not in results:
|
||||||
|
order.append(test_id)
|
||||||
|
results[test_id] = status
|
||||||
|
return [(test_id, results[test_id]) for test_id in order]
|
||||||
|
|
||||||
|
|
||||||
|
def _totals_from_cases(test_cases: list[tuple[str, str]]) -> dict[str, int]:
|
||||||
|
"""Build aggregate JUnit-style totals from final per-test statuses."""
|
||||||
|
|
||||||
|
totals = {"tests": len(test_cases), "failures": 0, "errors": 0, "skipped": 0}
|
||||||
|
for _, status in test_cases:
|
||||||
|
if status == "failed":
|
||||||
|
totals["failures"] += 1
|
||||||
|
elif status == "error":
|
||||||
|
totals["errors"] += 1
|
||||||
|
elif status == "skipped":
|
||||||
|
totals["skipped"] += 1
|
||||||
|
return totals
|
||||||
|
|
||||||
|
|
||||||
def _load_exit_code(path: str) -> int | None:
|
def _load_exit_code(path: str) -> int | None:
|
||||||
if not path or not os.path.exists(path):
|
if not path or not os.path.exists(path):
|
||||||
return None
|
return None
|
||||||
@ -108,9 +135,14 @@ def _post_text(url: str, payload: str) -> None:
|
|||||||
method="PUT",
|
method="PUT",
|
||||||
headers={"Content-Type": "text/plain"},
|
headers={"Content-Type": "text/plain"},
|
||||||
)
|
)
|
||||||
with urllib.request.urlopen(req, timeout=10) as resp:
|
try:
|
||||||
if resp.status >= 400:
|
with urllib.request.urlopen(req, timeout=10) as resp:
|
||||||
raise RuntimeError(f"metrics push failed status={resp.status}")
|
if resp.status >= 400:
|
||||||
|
raise RuntimeError(f"metrics push failed status={resp.status}")
|
||||||
|
except urllib.error.HTTPError as exc:
|
||||||
|
body = exc.read().decode("utf-8", errors="replace").strip()
|
||||||
|
detail = f": {body}" if body else ""
|
||||||
|
raise RuntimeError(f"metrics push failed status={exc.code}{detail}") from exc
|
||||||
|
|
||||||
|
|
||||||
def _read_http(url: str) -> str:
|
def _read_http(url: str) -> str:
|
||||||
@ -247,8 +279,9 @@ def main() -> int:
|
|||||||
raise RuntimeError(f"missing junit file {junit_path}")
|
raise RuntimeError(f"missing junit file {junit_path}")
|
||||||
|
|
||||||
coverage = _load_coverage(coverage_path)
|
coverage = _load_coverage(coverage_path)
|
||||||
totals = _load_junit(junit_path)
|
raw_test_cases = _load_junit_cases(junit_path)
|
||||||
test_cases = _load_junit_cases(junit_path)
|
test_cases = _collapse_test_cases(raw_test_cases)
|
||||||
|
totals = _totals_from_cases(test_cases) if test_cases else _load_junit(junit_path)
|
||||||
test_exit_code = _load_exit_code(test_exit_code_path)
|
test_exit_code = _load_exit_code(test_exit_code_path)
|
||||||
docs_exit_code = _load_exit_code(docs_exit_code_path)
|
docs_exit_code = _load_exit_code(docs_exit_code_path)
|
||||||
source_files_total = _count_source_files(repo_root)
|
source_files_total = _count_source_files(repo_root)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user