diff --git a/ops/runner/read-public-gitea-actions-queue.py b/ops/runner/read-public-gitea-actions-queue.py index bbeb191f..e1f3f061 100644 --- a/ops/runner/read-public-gitea-actions-queue.py +++ b/ops/runner/read-public-gitea-actions-queue.py @@ -415,6 +415,14 @@ def build_readback( ) effective_tests_log_classifier["host_pressure_waiting"] = False effective_tests_log_classifier["host_pressure_blocked_or_waiting"] = False + effective_cd_failure_classifier = build_log_classifier["failure_classifier"] + if ( + not effective_cd_failure_classifier + and latest_cd_status in {"Blocked", "Canceled", "Failure"} + and cd_jobs_stale_or_mismatched + and cd_jobs_payload_classifier + ): + effective_cd_failure_classifier = cd_jobs_payload_classifier latest_cd_no_matching_runner_label = ( latest_cd_run.get("no_matching_runner_label", "") or workflow_no_matching_labels.get("cd.yaml", "") @@ -617,9 +625,7 @@ def build_readback( controlled_profile_no_matching_runner_labels ), "latest_visible_cd_build_log_http_status": latest_cd_build_log_http_status, - "latest_visible_cd_failure_classifier": build_log_classifier[ - "failure_classifier" - ], + "latest_visible_cd_failure_classifier": effective_cd_failure_classifier, "latest_visible_cd_failure_status_code": build_log_classifier[ "failure_status_code" ], @@ -937,9 +943,7 @@ def build_readback( "controlled_profile_no_matching_runner_labels": ( controlled_profile_no_matching_runner_labels ), - "current_main_cd_failure_classifier": build_log_classifier[ - "failure_classifier" - ], + "current_main_cd_failure_classifier": effective_cd_failure_classifier, "current_main_cd_inflight_classifier": build_log_classifier[ "inflight_classifier" ], diff --git a/ops/runner/test_read_public_gitea_actions_queue.py b/ops/runner/test_read_public_gitea_actions_queue.py index ef133f39..867adba1 100644 --- a/ops/runner/test_read_public_gitea_actions_queue.py +++ b/ops/runner/test_read_public_gitea_actions_queue.py @@ -1219,6 +1219,37 @@ def test_stale_waiting_host_pressure_log_does_not_hide_failed_cd_jobs_payload() ) +def test_failed_cd_with_stale_jobs_payload_gets_failure_classifier() -> None: + module = _load_module() + payload = module.build_readback( + actions_html=_actions_html_failed_cd_run(), + actions_list_http_status=401, + actions_list_payload={"message": "token is required"}, + cd_jobs_http_status=200, + cd_jobs_payload={ + "jobs": [ + { + "run_id": 4043, + "name": "tests", + "head_sha": "9c4e754d3369fa2de7606e7092712cf6d85e18e2", + "conclusion": "success", + } + ], + "total_count": 1, + }, + ) + + assert payload["status"] == "cd_jobs_stale_or_mismatched" + assert payload["readback"]["latest_visible_cd_run_status"] == "Failure" + assert payload["readback"]["cd_run_jobs_head_sha_mismatch"] is True + assert payload["readback"]["latest_visible_cd_failure_classifier"] == ( + "cd_jobs_api_head_sha_mismatch_for_visible_cd_run" + ) + assert payload["rollups"]["current_main_cd_failure_classifier"] == ( + "cd_jobs_api_head_sha_mismatch_for_visible_cd_run" + ) + + def test_interrupted_host_pressure_reports_postgres_recovery_cpu() -> None: module = _load_module() payload = module.build_readback(