From 1e2d5dddc9b28497db6b0c0a5780f739db3414e9 Mon Sep 17 00:00:00 2001 From: ethernet Date: Thu, 30 Jul 2026 17:48:39 -0400 Subject: [PATCH] fix(tests): pre-clean container names + tolerant teardown in docker conftest MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Root cause of the last two amd64 docker failures: attempt 1 of a flaky file times out mid-teardown (busy dind), the stale hermes-test-* name survives, and the file-retry's docker run fails with a name Conflict — so the retry mechanism itself was poisoned. The fixture now removes the name BEFORE the test (fresh subprocess retry gets a clean slate), and teardown swallows a slow-daemon TimeoutExpired instead of erroring a passing test (1 passed, 1 error -> 1 passed). --- tests/docker/conftest.py | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/tests/docker/conftest.py b/tests/docker/conftest.py index 01b6ca2f8e5..4bd3ab3ff02 100644 --- a/tests/docker/conftest.py +++ b/tests/docker/conftest.py @@ -72,14 +72,32 @@ def built_image() -> str: @pytest.fixture def container_name(request) -> Iterator[str]: - """Generate a unique container name and ensure cleanup on test exit.""" + """Generate a unique container name and ensure cleanup on test exit. + + Cleans up BOTH before and after the test. The pre-clean matters for + the file-retry path: if attempt 1's teardown ``docker rm -f`` timed + out (busy daemon), the stale container survives and attempt 2's + ``docker run --name`` fails with a name Conflict. The teardown also + tolerates a slow daemon instead of raising TimeoutExpired out of the + fixture (which turns a passing test into an ERROR). + """ safe = request.node.name.replace("[", "_").replace("]", "_") name = f"hermes-test-{safe}" + + def _rm(timeout: int) -> None: + try: + subprocess.run( + ["docker", "rm", "-f", name], + capture_output=True, timeout=timeout, + ) + except subprocess.TimeoutExpired: + # Daemon is thrashing; the pre-clean of the next run (or the + # ephemeral CI pod being destroyed) picks up the stragglers. + pass + + _rm(timeout=30) yield name - subprocess.run( - ["docker", "rm", "-f", name], - capture_output=True, timeout=10, - ) + _rm(timeout=30) # ---------------------------------------------------------------------------