fix(tests): pre-clean container names + tolerant teardown in docker conftest

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).
This commit is contained in:
ethernet 2026-07-30 17:48:39 -04:00
parent 67516f0ba1
commit 1e2d5dddc9

View file

@ -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)
# ---------------------------------------------------------------------------