From 450cc52b258f859af239b2bcee75b4ed239f038e Mon Sep 17 00:00:00 2001 From: Devin Date: Sun, 27 Sep 2026 13:38:47 -0700 Subject: [PATCH 1/2] Preserve Docker image PATH during sandbox imports --- .../client/managers/sandboxes/image_build.py | 1 - tests/test_sandbox_image_build_helpers.py | 51 ++++++++++++++----- 2 files changed, 38 insertions(+), 14 deletions(-) diff --git a/hyperbrowser/client/managers/sandboxes/image_build.py b/hyperbrowser/client/managers/sandboxes/image_build.py index 0a59beed..d315c6a1 100644 --- a/hyperbrowser/client/managers/sandboxes/image_build.py +++ b/hyperbrowser/client/managers/sandboxes/image_build.py @@ -65,7 +65,6 @@ "USER", "LOGNAME", "SHELL", - "PATH", "PWD", "DISPLAY", } diff --git a/tests/test_sandbox_image_build_helpers.py b/tests/test_sandbox_image_build_helpers.py index 7998604a..9cbb45aa 100644 --- a/tests/test_sandbox_image_build_helpers.py +++ b/tests/test_sandbox_image_build_helpers.py @@ -631,54 +631,79 @@ def test_sync_dockerfile_build_uses_remote_context_by_default(monkeypatch, tmp_p assert captured[0].context_manifest.context_mode == "sparse" -def test_sync_docker_image_exact_reuse_skips_docker_save(monkeypatch): +@pytest.mark.anyio +@pytest.mark.parametrize("use_async", [False, True], ids=["sync", "async"]) +@pytest.mark.parametrize("path_override", [None, "/request/bin:/usr/bin", ""]) +async def test_docker_image_exact_reuse_preserves_env_without_docker_save( + monkeypatch, use_async, path_override +): cleaned = [] source = image_build.DockerImageManifestSource( image_digest="sha256:" + "a" * 64, config={ "User": "node", - "Env": ["APP_ENV=prod"], + "Env": [ + "APP_ENV=prod", + "PATH=/opt/venv/bin:/usr/bin", + "VIRTUAL_ENV=/opt/venv", + "HOME=/ignored", + "SANDBOX_ENABLED=false", + ], "Entrypoint": ["node"], "Cmd": ["server.js"], "WorkingDir": "/app", }, cleanup_callback=lambda: cleaned.append(True), ) + module = async_sandbox_module if use_async else sync_sandbox_module monkeypatch.setattr( - sync_sandbox_module, + module, "prepare_docker_image_manifest_source", lambda *args, **kwargs: source, ) monkeypatch.setattr( - sync_sandbox_module, + module, "package_docker_image_manifest", lambda *args, **kwargs: pytest.fail("cache hit unexpectedly ran docker save"), ) - manager = SandboxManager( + manager_class = AsyncSandboxManager if use_async else SandboxManager + manager = manager_class( SimpleNamespace(timeout=30, config=SimpleNamespace(runtime_proxy_override=None)) ) reused = [] + + def reuse(params): + reused.append(params) + return SimpleNamespace(hit=True, build=_image_build("completed")) + + async def reuse_async(params): + return reuse(params) + monkeypatch.setattr( - manager, - "reuse_docker_image", - lambda params: ( - reused.append(params) - or SimpleNamespace(hit=True, build=_image_build("completed")) - ), + manager, "reuse_docker_image", reuse_async if use_async else reuse ) + overrides = {"APP_ENV": "test"} + if path_override is not None: + overrides["PATH"] = path_override result = manager.build_image_from_docker_image( docker_image="local/app:latest", image_name="custom", - image_init={"env": {"APP_ENV": "test"}, "working_dir": "/srv"}, + image_init={"env": overrides, "working_dir": "/srv"}, builder_cpus=8, builder_memory_mib=16384, ) + if use_async: + result = await result assert result.status == "completed" assert reused[0].source_image_digest == "sha256:" + "a" * 64 assert reused[0].image_config_user == "node" - assert reused[0].image_init.env == {"APP_ENV": "test"} + assert reused[0].image_init.env == { + "APP_ENV": "test", + "VIRTUAL_ENV": "/opt/venv", + "PATH": "/opt/venv/bin:/usr/bin" if path_override is None else path_override, + } assert reused[0].image_init.args == ["node", "server.js"] assert reused[0].image_init.working_dir == "/srv" assert cleaned == [True] From 00905edd12308ee0b514fb2c84b2688300dce78c Mon Sep 17 00:00:00 2001 From: Devin Date: Sun, 27 Sep 2026 13:48:59 -0700 Subject: [PATCH 2/2] Bump version from 1.9.0 to 1.9.1 --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 024f0894..dc51777e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "hyperbrowser" -version = "1.9.0" +version = "1.9.1" description = "Python SDK for hyperbrowser" authors = ["Nikhil Shahi "] license = "MIT"