From 6403fa3d4220c8936abe103b0d0f96bf05e4be16 Mon Sep 17 00:00:00 2001 From: "anthony.wen" Date: Mon, 13 Apr 2026 22:46:23 -0400 Subject: [PATCH] fix: preserve all hosts in non-categorized watcher summaries --- atvm/watcher-service/atvm_run_watcher.py | 32 +++++++++++++++++++----- 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/atvm/watcher-service/atvm_run_watcher.py b/atvm/watcher-service/atvm_run_watcher.py index f81c1ad..2539af0 100644 --- a/atvm/watcher-service/atvm_run_watcher.py +++ b/atvm/watcher-service/atvm_run_watcher.py @@ -696,6 +696,26 @@ def extract_latest_run_summary(log_text: str, inventory: Dict[str, str]) -> Opti return summaries[-1] +def extract_merged_run_summary(log_text: str, inventory: Dict[str, str]) -> Optional[Dict[str, object]]: + summaries = extract_completed_subrun_summaries(log_text, inventory) + if not summaries: + return None + + merged_host_results: Dict[str, HostResult] = {} + latest_currents_url: Optional[str] = None + for summary in summaries: + for host, result in summary["host_results"].items(): + merged_host_results[host] = result + currents_url = summary.get("currents_url") + if isinstance(currents_url, str) and currents_url: + latest_currents_url = currents_url + + return { + "host_results": merged_host_results, + "currents_url": latest_currents_url, + } + + def collect_host_results( reporter_root: Path, expected_hosts: List[str], @@ -1830,16 +1850,16 @@ def determine_state( # Non-categorized runs often only write a final check-xml reporter XML. # Prefer the parent "Cloud Run Finished" host summary because it preserves # final pass/fail counts even when reporter fallback artifacts are sparse. - latest_summary = extract_latest_run_summary(log_text, inventory) - if latest_summary: - summary_results = latest_summary["host_results"] + merged_summary = extract_merged_run_summary(log_text, inventory) + if merged_summary: + summary_results = merged_summary["host_results"] for host, result in summary_results.items(): parent_host_results[host] = result if subrun_states: subrun = subrun_states[-1] - subrun["host_results"] = summary_results - if not subrun.get("currents_url") and latest_summary.get("currents_url"): - subrun["currents_url"] = latest_summary["currents_url"] + subrun["host_results"] = dict(parent_host_results) + if not subrun.get("currents_url") and merged_summary.get("currents_url"): + subrun["currents_url"] = merged_summary["currents_url"] subrun["state"] = "FAILED" if any(result.failures for result in summary_results.values()) else "COMPLETED" parent_start_candidates = [subrun["start_ts"] for subrun in subrun_states if subrun["start_ts"]]