ci(titan-iac): infer coverage/loc metrics from quality summary artifacts
This commit is contained in:
parent
e8823197f8
commit
cb1c41c6ea
@ -159,6 +159,47 @@ def _summary_int(summary: dict, key: str) -> int:
|
|||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
def _infer_workspace_coverage_percent(summary: dict, default_xml: str) -> float:
|
||||||
|
"""Infer workspace line coverage from quality summary coverage XML metadata."""
|
||||||
|
results = summary.get("results", []) if isinstance(summary, dict) else []
|
||||||
|
coverage_xml = default_xml
|
||||||
|
for result in results:
|
||||||
|
if not isinstance(result, dict):
|
||||||
|
continue
|
||||||
|
if str(result.get("name") or "").strip().lower() != "coverage":
|
||||||
|
continue
|
||||||
|
candidate = str(result.get("coverage_xml") or "").strip()
|
||||||
|
if candidate:
|
||||||
|
coverage_xml = candidate
|
||||||
|
break
|
||||||
|
xml_path = Path(coverage_xml)
|
||||||
|
if not xml_path.exists():
|
||||||
|
return 0.0
|
||||||
|
try:
|
||||||
|
root = ET.parse(xml_path).getroot()
|
||||||
|
line_rate = root.attrib.get("line-rate")
|
||||||
|
if line_rate is None:
|
||||||
|
return 0.0
|
||||||
|
return float(line_rate) * 100.0
|
||||||
|
except (ET.ParseError, OSError, ValueError):
|
||||||
|
return 0.0
|
||||||
|
|
||||||
|
|
||||||
|
def _infer_source_lines_over_500(summary: dict) -> int:
|
||||||
|
"""Infer over-limit source file count from hygiene issue payloads."""
|
||||||
|
results = summary.get("results", []) if isinstance(summary, dict) else []
|
||||||
|
for result in results:
|
||||||
|
if not isinstance(result, dict):
|
||||||
|
continue
|
||||||
|
if str(result.get("name") or "").strip().lower() not in {"hygiene", "loc", "smell"}:
|
||||||
|
continue
|
||||||
|
issues = result.get("issues")
|
||||||
|
if not isinstance(issues, list):
|
||||||
|
continue
|
||||||
|
return sum(1 for item in issues if isinstance(item, str) and item.startswith("file exceeds"))
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
def _normalize_result_status(value: str | None, default: str = "failed") -> str:
|
def _normalize_result_status(value: str | None, default: str = "failed") -> str:
|
||||||
"""Map arbitrary check status text into canonical check result buckets."""
|
"""Map arbitrary check status text into canonical check result buckets."""
|
||||||
if not value:
|
if not value:
|
||||||
@ -394,7 +435,11 @@ def main() -> int:
|
|||||||
status = "ok" if exit_code == 0 else "failed"
|
status = "ok" if exit_code == 0 else "failed"
|
||||||
summary = _load_summary(summary_path)
|
summary = _load_summary(summary_path)
|
||||||
workspace_line_coverage_percent = _summary_float(summary, "workspace_line_coverage_percent")
|
workspace_line_coverage_percent = _summary_float(summary, "workspace_line_coverage_percent")
|
||||||
|
if workspace_line_coverage_percent <= 0:
|
||||||
|
workspace_line_coverage_percent = _infer_workspace_coverage_percent(summary, "build/coverage-unit.xml")
|
||||||
source_lines_over_500 = _summary_int(summary, "source_lines_over_500")
|
source_lines_over_500 = _summary_int(summary, "source_lines_over_500")
|
||||||
|
if source_lines_over_500 <= 0:
|
||||||
|
source_lines_over_500 = _infer_source_lines_over_500(summary)
|
||||||
sonarqube_report = _load_optional_json(os.getenv("QUALITY_GATE_SONARQUBE_REPORT", "build/sonarqube-quality-gate.json"))
|
sonarqube_report = _load_optional_json(os.getenv("QUALITY_GATE_SONARQUBE_REPORT", "build/sonarqube-quality-gate.json"))
|
||||||
supply_chain_report = _load_optional_json(os.getenv("QUALITY_GATE_IRONBANK_REPORT", "build/ironbank-compliance.json"))
|
supply_chain_report = _load_optional_json(os.getenv("QUALITY_GATE_IRONBANK_REPORT", "build/ironbank-compliance.json"))
|
||||||
supply_chain_required = os.getenv("QUALITY_GATE_IRONBANK_REQUIRED", "0").strip().lower() in {"1", "true", "yes", "on"}
|
supply_chain_required = os.getenv("QUALITY_GATE_IRONBANK_REQUIRED", "0").strip().lower() in {"1", "true", "yes", "on"}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user