From 887023eaeb2ceab9cc2890592592bd0a26d8a715 Mon Sep 17 00:00:00 2001 From: jenkins Date: Tue, 19 May 2026 19:51:10 -0300 Subject: [PATCH] ci(testing): treat optional supply-chain as non-blocking --- ci/scripts/publish_test_metrics.py | 6 ++++- ci/scripts/publish_test_metrics_quality.py | 6 ++++- testing/tests/test_publish_test_metrics.py | 30 ++++++++++++++++++++++ 3 files changed, 40 insertions(+), 2 deletions(-) diff --git a/ci/scripts/publish_test_metrics.py b/ci/scripts/publish_test_metrics.py index 97174724..216655c7 100644 --- a/ci/scripts/publish_test_metrics.py +++ b/ci/scripts/publish_test_metrics.py @@ -287,7 +287,11 @@ def main() -> int: 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")) 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"} + truthy = {"1", "true", "yes", "on"} + supply_chain_required = ( + os.getenv("QUALITY_GATE_IRONBANK_REQUIRED", "0").strip().lower() in truthy + or os.getenv("PUBLISH_IMAGES", "false").strip().lower() in truthy + ) check_statuses = _build_check_statuses( summary=summary, tests=tests, diff --git a/ci/scripts/publish_test_metrics_quality.py b/ci/scripts/publish_test_metrics_quality.py index 09fe64e6..fca8cfa7 100644 --- a/ci/scripts/publish_test_metrics_quality.py +++ b/ci/scripts/publish_test_metrics_quality.py @@ -121,11 +121,15 @@ def _infer_supply_chain_status(report: dict, required: bool) -> str: return "failed" if required else "not_applicable" compliant = report.get("compliant") if isinstance(compliant, bool): - return "ok" if compliant else "failed" + if compliant: + return "ok" + return "failed" if required else "not_applicable" status = report.get("status") if status is None: return "failed" if required else "not_applicable" normalized = _normalize_result_status(str(status), default="failed") + if normalized == "failed" and not required: + return "not_applicable" if normalized == "not_applicable" and required: return "failed" return normalized diff --git a/testing/tests/test_publish_test_metrics.py b/testing/tests/test_publish_test_metrics.py index 6f129638..aa183a6b 100644 --- a/testing/tests/test_publish_test_metrics.py +++ b/testing/tests/test_publish_test_metrics.py @@ -166,6 +166,8 @@ def test_status_normalization_and_optional_reports(tmp_path: Path): assert publish_test_metrics._combine_statuses(["unknown"]) == "failed" assert publish_test_metrics._infer_supply_chain_status({"compliant": False}, required=True) == "failed" + assert publish_test_metrics._infer_supply_chain_status({"compliant": False}, required=False) == "not_applicable" + assert publish_test_metrics._infer_supply_chain_status({"status": "failed"}, required=False) == "not_applicable" assert publish_test_metrics._infer_supply_chain_status({"status": None}, required=False) == "not_applicable" assert publish_test_metrics._infer_supply_chain_status({"status": "not_applicable"}, required=True) == "failed" @@ -429,3 +431,31 @@ def test_main_marks_successful_run(tmp_path: Path, monkeypatch, capsys): assert rc == 0 assert summary["status"] == "ok" assert summary["checks_recorded"] == 7 + + +def test_main_requires_supply_chain_when_images_are_published(tmp_path: Path, monkeypatch): + build_dir = tmp_path / "build" + build_dir.mkdir() + (build_dir / "junit.xml").write_text( + '', + encoding="utf-8", + ) + (build_dir / "quality-gate.rc").write_text("0\n", encoding="utf-8") + (build_dir / "ironbank-compliance.json").write_text( + json.dumps({"compliant": False}), + encoding="utf-8", + ) + + posted = {} + + monkeypatch.setenv("JUNIT_GLOB", str(build_dir / "*.xml")) + monkeypatch.setenv("QUALITY_GATE_EXIT_CODE_PATH", str(build_dir / "quality-gate.rc")) + monkeypatch.setenv("QUALITY_GATE_SUMMARY_PATH", str(build_dir / "missing-summary.json")) + monkeypatch.setenv("QUALITY_GATE_IRONBANK_REPORT", str(build_dir / "ironbank-compliance.json")) + monkeypatch.setenv("QUALITY_GATE_IRONBANK_REQUIRED", "0") + monkeypatch.setenv("PUBLISH_IMAGES", "true") + monkeypatch.setattr(publish_test_metrics, "_fetch_existing_counter", lambda *args, **kwargs: 0) + monkeypatch.setattr(publish_test_metrics, "_post_text", lambda url, payload: posted.update({"payload": payload})) + + assert publish_test_metrics.main() == 0 + assert 'titan_iac_quality_gate_checks_total{suite="titan_iac",check="supply_chain",result="failed"} 1' in posted["payload"]