From 97fc4d2ff708a3a6542641374d122b6f2c4125c5 Mon Sep 17 00:00:00 2001 From: Arisu Tachibana Date: Wed, 29 Jul 2026 12:40:58 +0900 Subject: [PATCH] Fix --watch --test from waiting indefinitely Signed-off-by: Arisu Tachibana --- kcidev/libs/maestro_common.py | 12 +++++++++--- tests/test_maestro_common.py | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 3 deletions(-) diff --git a/kcidev/libs/maestro_common.py b/kcidev/libs/maestro_common.py index 3359f56..753ef06 100644 --- a/kcidev/libs/maestro_common.py +++ b/kcidev/libs/maestro_common.py @@ -234,6 +234,7 @@ def maestro_watch_jobs(baseurl, token, treeid, job_filter, test, root_node="chec logging.debug(f"Watching jobs: {job_filter}, test: {test}") previous_nodes = None running = False + jobs_done_ts = None job_info = {} for job in job_filter: @@ -248,7 +249,9 @@ def maestro_watch_jobs(baseurl, token, treeid, job_filter, test, root_node="chec kci_warning("No nodes found. Retrying...") time.sleep(5) continue - if previous_nodes == nodes: + # Keep checking the test-result deadline after the jobs have completed, + # even when the API response has not changed. + if previous_nodes == nodes and jobs_done_ts is None: logging.debug("No changes in nodes, waiting...") kci_msg_nonl(".") time.sleep(30) @@ -260,7 +263,6 @@ def maestro_watch_jobs(baseurl, token, treeid, job_filter, test, root_node="chec # Tricky part in watch is that we might have one item in job_filter (job, test), # but it might spawn multiple nodes with same name test_result = None - jobs_done_ts = None logging.debug(f"Processing {len(nodes)} nodes") for node in nodes: if node["name"] == test: @@ -304,7 +306,7 @@ def maestro_watch_jobs(baseurl, token, treeid, job_filter, test, root_node="chec if not test: return else: - if not jobs_done_ts: + if jobs_done_ts is None: jobs_done_ts = time.time() logging.debug("All jobs done, waiting for test results") # if all jobs done, usually test results must be available @@ -321,6 +323,10 @@ def maestro_watch_jobs(baseurl, token, treeid, job_filter, test, root_node="chec elif test_result: logging.info(f"Test {test} failed with result: {test_result}") sys.exit(1) + else: + logging.error(f"Test {test} result was not available after 60s") + kci_err(f"Test {test} result was not available after 60s") + sys.exit(2) running = True kci_msg_nonl(f"\rRunning job...") diff --git a/tests/test_maestro_common.py b/tests/test_maestro_common.py index 8ef52a7..4b70625 100644 --- a/tests/test_maestro_common.py +++ b/tests/test_maestro_common.py @@ -134,3 +134,38 @@ def test_maestro_watch_jobs_completes_with_patchset_root(monkeypatch): None, root_node="patchset", ) + + +def test_maestro_watch_jobs_times_out_waiting_for_test_result(monkeypatch): + nodes = [ + { + "name": "checkout", + "state": "done", + "result": "pass", + "kind": "checkout", + "id": "c1", + "updated": "now", + }, + { + "name": "job1", + "state": "done", + "result": "pass", + "kind": "job", + "id": "j1", + "updated": "now", + }, + ] + monkeypatch.setattr( + maestro_common, "maestro_retrieve_treeid_nodes", Mock(return_value=nodes) + ) + monkeypatch.setattr(maestro_common.time, "sleep", Mock()) + monkeypatch.setattr( + maestro_common.time, "time", Mock(side_effect=[100, 100, 161, 161, 161]) + ) + + with pytest.raises(SystemExit) as exc_info: + maestro_common.maestro_watch_jobs( + "https://api.example.org/", "token123", "t1", ["job1"], "missing-test" + ) + + assert exc_info.value.code == 2