From 1e396e72a84b8bc688e428bc1d08623988dfb3a8 Mon Sep 17 00:00:00 2001 From: Pascal Date: Mon, 10 Aug 2026 08:32:58 +0200 Subject: [PATCH] server: gate the docker tools runtime tests on a real container run (#26826) docker info only proves the daemon answers, so the Windows CI passes the check and then dies trying to run a linux image. The hosted Windows runners cannot run one: GitHub states the VMs are not enabled for nested virtualization and will not be, since they already sit one level deep and the hypervisor does not support more levels (https://github.com/orgs/community/discussions/25491). Probing the image itself skips those tests there, and pulls it before the server waits for the container id. --- tools/server/tests/unit/test_tools_builtin.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/tools/server/tests/unit/test_tools_builtin.py b/tools/server/tests/unit/test_tools_builtin.py index c651e8e72d..7da569d99f 100755 --- a/tools/server/tests/unit/test_tools_builtin.py +++ b/tools/server/tests/unit/test_tools_builtin.py @@ -13,6 +13,9 @@ PROJECT_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", ".. # marker for the grep_search test to find in this file GREP_MARKER = "llama_cpp_test_tools_builtin_marker_grep_search" +# image the container runtime tests run their shell in +DOCKER_IMAGE = "busybox" + @pytest.fixture(autouse=True) def create_server(): @@ -149,14 +152,16 @@ def test_tools_builtin_cwd_header(): def _docker_unavailable_reason() -> str | None: - """None if docker can be used to run a container, otherwise the reason it can't.""" + """None if docker can run the image these tests use, otherwise the reason it can't.""" docker_bin = shutil.which("docker") if docker_bin is None: return "docker is not installed" try: - subprocess.run([docker_bin, "info"], capture_output=True, timeout=5, check=True) + # a daemon that answers `docker info` still cannot run a linux image when it serves + # windows containers, so probe the image itself, which also pulls it before the tests + subprocess.run([docker_bin, "run", "--rm", DOCKER_IMAGE, "true"], capture_output=True, timeout=60, check=True) except Exception as e: - return f"docker daemon is not usable: {e}" + return f"docker cannot run {DOCKER_IMAGE}: {e}" return None @@ -167,7 +172,7 @@ def docker_container(): pytest.skip(reason) # ty: ignore[too-many-positional-arguments, invalid-argument-type] proc = subprocess.run( - ["docker", "run", "-d", "--rm", "busybox", "sleep", "300"], + ["docker", "run", "-d", "--rm", DOCKER_IMAGE, "sleep", "300"], capture_output=True, text=True, ) if proc.returncode != 0: @@ -214,7 +219,7 @@ def test_tools_builtin_docker_runtime_cleans_up_spawned_container(): pytest.skip(reason) # ty: ignore[too-many-positional-arguments, invalid-argument-type] global server - server.server_tools_runtime = "docker:busybox" + server.server_tools_runtime = f"docker:{DOCKER_IMAGE}" server.start() # exec_shell_command runs inside the container spawned for --tools-runtime; docker sets