From efed23e671290b20d817ba12c9b472b4a8dbc99d Mon Sep 17 00:00:00 2001 From: SlaiAgent <294879785+huong8373tt-beep@users.noreply.github.com> Date: Wed, 7 Oct 2026 21:54:06 +0800 Subject: [PATCH 1/2] Make-Windows-task-container-proxy-opt-in --- launch/core/platforms/windows.py | 44 ++++++++++++++++-- tests/windows_container_proxy_test.py | 67 +++++++++++++++++++++++++++ 2 files changed, 108 insertions(+), 3 deletions(-) create mode 100644 tests/windows_container_proxy_test.py diff --git a/launch/core/platforms/windows.py b/launch/core/platforms/windows.py index 28c146e..47bd608 100644 --- a/launch/core/platforms/windows.py +++ b/launch/core/platforms/windows.py @@ -22,6 +22,46 @@ import uuid import docker + + +# Do not inherit or invent a machine-local proxy route for evaluated Windows +# containers. Callers that need one can opt in explicitly through these names. +WINDOWS_CONTAINER_PROXY_ENV = "REPOLAUNCH_WINDOWS_CONTAINER_PROXY" +WINDOWS_CONTAINER_NO_PROXY_ENV = "REPOLAUNCH_WINDOWS_CONTAINER_NO_PROXY" +DEFAULT_WINDOWS_CONTAINER_NO_PROXY = "localhost,127.0.0.1,::1" + + +def build_windows_container_environment() -> dict[str, str]: + """Build the task-container environment without a proxy by default. + + A Windows evaluation container may be able to reach an external registry + directly even when a host-local proxy is stale or unreachable from process + isolation. Keep proxy propagation opt-in. When a caller explicitly supplies + a proxy, set both conventional upper- and lower-case variables because + Windows project toolchains use both spellings. + """ + environment = {"TERM": "xterm-mono"} + proxy = os.environ.get(WINDOWS_CONTAINER_PROXY_ENV, "").strip() + if not proxy: + return environment + + environment.update({ + "HTTP_PROXY": proxy, + "HTTPS_PROXY": proxy, + "ALL_PROXY": proxy, + "http_proxy": proxy, + "https_proxy": proxy, + "all_proxy": proxy, + }) + no_proxy = os.environ.get( + WINDOWS_CONTAINER_NO_PROXY_ENV, + DEFAULT_WINDOWS_CONTAINER_NO_PROXY, + ).strip() + if no_proxy: + environment.update({"NO_PROXY": no_proxy, "no_proxy": no_proxy}) + return environment + + from docker.models.containers import Container @@ -157,9 +197,7 @@ def _start_container( stdin_open=True, tty=True, detach=True, - environment={ - "TERM": "xterm-mono", - }, + environment=build_windows_container_environment(), working_dir=working_dir, extra_hosts=extra_hosts, volumes={ diff --git a/tests/windows_container_proxy_test.py b/tests/windows_container_proxy_test.py new file mode 100644 index 0000000..832abca --- /dev/null +++ b/tests/windows_container_proxy_test.py @@ -0,0 +1,67 @@ +from __future__ import annotations + +import os +import sys +import unittest +from pathlib import Path +from unittest import mock + + +ROOT = Path(__file__).resolve().parents[1] +sys.path.insert(0, str(ROOT)) + +from launch.core.platforms.windows import ( + DEFAULT_WINDOWS_CONTAINER_NO_PROXY, + WINDOWS_CONTAINER_NO_PROXY_ENV, + WINDOWS_CONTAINER_PROXY_ENV, + build_windows_container_environment, +) + + +class WindowsContainerProxyTest(unittest.TestCase): + def test_default_does_not_inject_machine_local_proxy(self) -> None: + with mock.patch.dict(os.environ, {}, clear=True): + environment = build_windows_container_environment() + + self.assertEqual(environment, {"TERM": "xterm-mono"}) + self.assertNotIn("HTTP_PROXY", environment) + self.assertNotIn("http_proxy", environment) + + def test_explicit_proxy_populates_common_toolchain_spellings(self) -> None: + proxy = "http://host.docker.internal:7897" + with mock.patch.dict( + os.environ, + {WINDOWS_CONTAINER_PROXY_ENV: proxy}, + clear=True, + ): + environment = build_windows_container_environment() + + for key in ( + "HTTP_PROXY", + "HTTPS_PROXY", + "ALL_PROXY", + "http_proxy", + "https_proxy", + "all_proxy", + ): + self.assertEqual(environment[key], proxy) + self.assertEqual(environment["NO_PROXY"], DEFAULT_WINDOWS_CONTAINER_NO_PROXY) + self.assertEqual(environment["no_proxy"], DEFAULT_WINDOWS_CONTAINER_NO_PROXY) + + def test_explicit_no_proxy_overrides_default(self) -> None: + with mock.patch.dict( + os.environ, + { + WINDOWS_CONTAINER_PROXY_ENV: "http://proxy.example:8080", + WINDOWS_CONTAINER_NO_PROXY_ENV: "localhost,fakerepo", + }, + clear=True, + ): + environment = build_windows_container_environment() + + self.assertEqual(environment["NO_PROXY"], "localhost,fakerepo") + self.assertEqual(environment["no_proxy"], "localhost,fakerepo") + + +if __name__ == "__main__": + unittest.main() \ No newline at end of file From d49f3ca6ee7a9f9b4373ab739649d87b990e76a4 Mon Sep 17 00:00:00 2001 From: SlaiAgent <294879785+huong8373tt-beep@users.noreply.github.com> Date: Wed, 7 Oct 2026 22:42:43 +0800 Subject: [PATCH 2/2] Clarify explicit proxy configuration --- launch/core/platforms/windows.py | 9 ++++++--- tests/windows_container_proxy_test.py | 26 ++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/launch/core/platforms/windows.py b/launch/core/platforms/windows.py index 47bd608..86d3cbd 100644 --- a/launch/core/platforms/windows.py +++ b/launch/core/platforms/windows.py @@ -36,9 +36,12 @@ def build_windows_container_environment() -> dict[str, str]: A Windows evaluation container may be able to reach an external registry directly even when a host-local proxy is stale or unreachable from process - isolation. Keep proxy propagation opt-in. When a caller explicitly supplies - a proxy, set both conventional upper- and lower-case variables because - Windows project toolchains use both spellings. + isolation. Conversely, managed, regional, and enterprise environments may + require a proxy. Keep proxy propagation explicit rather than guessing from + host variables: callers can supply a container-reachable route through + ``REPOLAUNCH_WINDOWS_CONTAINER_PROXY``. When configured, set both + conventional upper- and lower-case variables because Windows project + toolchains use both spellings. """ environment = {"TERM": "xterm-mono"} proxy = os.environ.get(WINDOWS_CONTAINER_PROXY_ENV, "").strip() diff --git a/tests/windows_container_proxy_test.py b/tests/windows_container_proxy_test.py index 832abca..f81d09e 100644 --- a/tests/windows_container_proxy_test.py +++ b/tests/windows_container_proxy_test.py @@ -48,6 +48,32 @@ def test_explicit_proxy_populates_common_toolchain_spellings(self) -> None: self.assertEqual(environment["NO_PROXY"], DEFAULT_WINDOWS_CONTAINER_NO_PROXY) self.assertEqual(environment["no_proxy"], DEFAULT_WINDOWS_CONTAINER_NO_PROXY) + def test_host_proxy_is_used_only_when_explicitly_selected(self) -> None: + host_proxy = "http://host.docker.internal:7897" + with mock.patch.dict( + os.environ, + { + "HTTP_PROXY": host_proxy, + "HTTPS_PROXY": host_proxy, + "ALL_PROXY": host_proxy, + }, + clear=True, + ): + environment = build_windows_container_environment() + + self.assertEqual(environment, {"TERM": "xterm-mono"}) + self.assertNotIn("HTTP_PROXY", environment) + + with mock.patch.dict( + os.environ, + {WINDOWS_CONTAINER_PROXY_ENV: host_proxy}, + clear=True, + ): + environment = build_windows_container_environment() + + self.assertEqual(environment["HTTP_PROXY"], host_proxy) + self.assertEqual(environment["HTTPS_PROXY"], host_proxy) + def test_explicit_no_proxy_overrides_default(self) -> None: with mock.patch.dict( os.environ,