From d2984b5eec4222817f7c7430e5d7efeae259decb Mon Sep 17 00:00:00 2001 From: maocheng23 Date: Mon, 5 Oct 2026 22:59:35 -0700 Subject: [PATCH 1/2] test(capture-gate): print server.log tail when sglang fails to start The gate only reported the server.log path, which lives in the CI container and is gone after the job. Include the exit code and the last 80 lines so a startup crash is diagnosable from the job log. Co-Authored-By: Claude Opus 5.5 --- tests/test_runtime/test_server_capture_gate.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/tests/test_runtime/test_server_capture_gate.py b/tests/test_runtime/test_server_capture_gate.py index 08832183a..ff6cf51fe 100644 --- a/tests/test_runtime/test_server_capture_gate.py +++ b/tests/test_runtime/test_server_capture_gate.py @@ -76,6 +76,15 @@ def _mooncake_available() -> bool: return importlib.util.find_spec("mooncake.store") is not None +def _log_tail(path, lines=80): + """Last lines of a subprocess log, so CI shows why the process died.""" + try: + with open(path, errors="replace") as f: + return "".join(f.readlines()[-lines:]) + except OSError as exc: + return f"" + + @unittest.skipUnless( CUDA and ENABLED, "server-capture gate: set SPECFORGE_RUN_SERVER_CAPTURE_TESTS=1 (GPU)", @@ -183,7 +192,9 @@ def setUpClass(cls): break time.sleep(5) raise RuntimeError( - f"sglang server did not become healthy; see {cls.workdir}/server.log" + "sglang server did not become healthy " + f"(exit code {cls.server.poll()}); tail of {cls.workdir}/server.log:\n" + + _log_tail(os.path.join(cls.workdir, "server.log")) ) @classmethod From 2a632112fd14734d1956edb1c3ac83816ff403c3 Mon Sep 17 00:00:00 2001 From: maocheng23 Date: Mon, 5 Oct 2026 23:09:28 -0700 Subject: [PATCH 2/2] ci: keep loopback off the runner proxy in unit-test The self-hosted runner still exports HTTP_PROXY/HTTPS_PROXY into the job container but stopped exporting NO_PROXY (present on 09-30, absent since). sglang's startup warmup POSTs to 127.0.0.1, went through the proxy, got a 502 and the server killed itself, failing the live server-capture gate on every PR. Set NO_PROXY for loopback at the job level. Co-Authored-By: Claude Opus 5.5 --- .github/workflows/test.yaml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 9c174578c..0bb63f6a8 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -41,6 +41,13 @@ jobs: container: image: lmsysorg/sglang:v0.5.18-cu130 # we lock to this version to avoid repeated docker pull options: --gpus all --shm-size=2g --rm -v /dev/shm --privileged --pid=host + # The self-hosted runner exports HTTP(S)_PROXY into the container but no + # longer a NO_PROXY, so local requests (sglang's own warmup to 127.0.0.1) + # went through the proxy and got 502. Keep loopback off the proxy here + # instead of relying on the runner's environment. (Actions env keys are + # case-insensitive, so no separate no_proxy; Python reads either case.) + env: + NO_PROXY: localhost,127.0.0.1,::1 steps: - name: Checkout code uses: actions/checkout@v4