Skip to content

fix(e2e): exempt loopback from ambient HTTP proxy so pnpm e2e:web boots locally#116

Merged
ryota-murakami merged 1 commit into
mainfrom
fix/115-e2e-webserver-proxy
Jun 24, 2026
Merged

fix(e2e): exempt loopback from ambient HTTP proxy so pnpm e2e:web boots locally#116
ryota-murakami merged 1 commit into
mainfrom
fix/115-e2e-webserver-proxy

Conversation

@ryota-murakami

@ryota-murakami ryota-murakami commented Jun 24, 2026

Copy link
Copy Markdown
Collaborator

Summary

pnpm e2e:web could not boot locally on macOS — Playwright's webServer readiness
probe timed out at 120s before next start was ever reached, so no web E2E spec
could run on this machine. This exempts loopback from any ambient HTTP proxy before
Playwright reads the environment, so the probe connects straight to next.

Closes #115.

Root cause (corrected)

The earlier hypothesis in the issue (IPv4/IPv6 loopback / happy-eyeballs mismatch)
was falsified: pinning the probe to the 127.0.0.1 literal still timed out, while
curl/bare-Node got 200 on the same URL.

The real cause is the Bash-tool network sandbox (Socket Firewall / sfw): it
injects HTTP_PROXY/http_proxy=http://127.0.0.1:<dynamic-port> into every child
process to police outbound traffic. Playwright's webServer waiter resolves its target
through proxy-from-env (getProxyForUrl), which honors those vars — so the
http://127.0.0.1:4991 probe was routed through the firewall proxy, which answered
405 (observed before next had even started — only a proxy can 405 a port
with no upstream). 405 >= 400, so the waiter never saw the dev server's real 200
and timed out. curl/bare-Node bypass the proxy, which is why they returned 200 and
made the hostname theories look plausible.

This is a sandbox artifact, not a defect in the Mac or the project — a normal
terminal (no injected proxy) boots pnpm e2e:web fine. The fix makes the probe
proxy-robust and is a strict no-op when no proxy is set.

Fix

playwright.config.ts, top-level (runs before defineConfig reads env):

const LOOPBACK_NO_PROXY = 'localhost,127.0.0.1,[::1]'
for (const proxyExemptionKey of ['NO_PROXY', 'no_proxy']) {
  process.env[proxyExemptionKey] = [process.env[proxyExemptionKey], LOOPBACK_NO_PROXY]
    .filter(Boolean)
    .join(',')
}
  • Adds loopback to NO_PROXY/no_proxy so getProxyForUrl returns "" for the
    probe URL and the waiter connects directly to next.
  • External hosts stay absent from NO_PROXY (Clerk, corelive.app) — they remain
    proxied, so the firewall is still enforced for real outbound traffic.
  • IPv6 loopback is bracketed ([::1], not bare ::1): proxy-from-env matches
    NO_PROXY entries against the URL host verbatim and a URL host keeps its brackets,
    so a bare ::1 entry would never match a [::1] probe.
  • The probe url stays pinned to the 127.0.0.1 literal (unambiguous IPv4, matches
    the host CI listens on); use.baseURL stays localhost (drives Chromium; Clerk dev
    keys are localhost-scoped) — unchanged.

Verification

  • pnpm e2e:web e2e/web/category.spec.ts under the live sandbox → 21 passed (3.8m);
    DEBUG=pw:webserver shows ECONNREFUSED → start → HTTP 200 → WebServer available
    (no 405, no timeout).
  • mise exec node@24.13.0 -- pnpm test662 passed / 33 skipped, exit 0.
  • CI is a no-op: GitHub runners set no proxy, so getProxyForUrl already returns
    "" for loopback regardless — the appended NO_PROXY changes nothing there.

Acceptance criteria (#115)

  • pnpm e2e:web boots locally on macOS (21-pass proof above)
  • CI behavior unchanged (no-op without an ambient proxy — to be confirmed green by the web-E2E job on this PR)
  • Fix committed and documented (accurate root-cause comment in playwright.config.ts)

Summary by CodeRabbit

  • Bug Fixes
    • Improved local test setup reliability when a proxy is present.
    • Updated the dev-server check to use a loopback IP address, helping ensure the browser test runner connects correctly on machines with proxy settings.
    • Expanded loopback bypass coverage so localhost, IPv4, and IPv6 loopback traffic are handled consistently.

…rver probe

When `pnpm e2e:web` runs inside an ambient HTTP-proxy environment (e.g. a
network sandbox that injects HTTP_PROXY/http_proxy), Playwright's webServer
readiness probe resolves its target through `proxy-from-env`, so the
`http://127.0.0.1:4991` probe was routed through the proxy, which answered
405. 405 is >= 400, so the waiter never saw the dev server's real 200 and
timed out at 120s — the server itself was healthy the whole time.

Fix: exempt loopback (localhost,127.0.0.1,::1) from NO_PROXY before Playwright
reads the env, so the probe connects straight to `next`. External hosts (Clerk,
corelive.app) stay proxied, so any firewall is still enforced for real outbound
traffic. Strict no-op where no proxy is set (e.g. CI) — `getProxyForUrl` already
returns "" there regardless. Also pin the probe to the 127.0.0.1 IP literal
(unambiguous IPv4, matches the host CI listens on); the NO_PROXY exemption is
what actually unblocks it.

Verified: `pnpm e2e:web e2e/web/category.spec.ts` -> 21 passed under the sandbox
(previously a 120s webServer timeout).

Closes #115
@vercel

vercel Bot commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
corelive Ready Ready Preview, Comment Jun 24, 2026 3:37pm

Request Review

@coderabbitai

coderabbitai Bot commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 6d192a60-f919-433b-89af-ffca6e06f0b4

📥 Commits

Reviewing files that changed from the base of the PR and between 42747b5 and e66b50d.

📒 Files selected for processing (1)
  • playwright.config.ts

📝 Walkthrough

Walkthrough

playwright.config.ts is updated to append loopback addresses (localhost, 127.0.0.1, [::1]) to NO_PROXY and no_proxy environment variables at module load time. The webServer.url readiness probe is changed from http://localhost:4991 to http://127.0.0.1:4991, with comments updated accordingly.

Changes

Playwright loopback proxy exemption and probe URL fix

Layer / File(s) Summary
NO_PROXY loopback exemption and webServer probe URL
playwright.config.ts
Adds a LOOPBACK_NO_PROXY constant and appends it to both NO_PROXY and no_proxy in process.env at module load time. Changes webServer.url from http://localhost:4991 to http://127.0.0.1:4991 so the readiness probe uses the IPv4 literal, bypassing any ambient HTTP proxy.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐇 A rabbit once hopped to localhost one day,
but the proxy said "No! You shall not pass this way!"
So I patched in my NO_PROXY with IPv4 flair,
127.0.0.1 — the IP that's always there.
Now e2e boots without timeout's despair! 🎉

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main fix: making local e2e boot work by exempting loopback from ambient proxy settings.
Linked Issues check ✅ Passed The change addresses issue #115 by forcing loopback traffic to bypass proxy env vars so Playwright reaches the local webServer directly.
Out of Scope Changes check ✅ Passed The edits are confined to the Playwright config and directly support the local e2e boot fix, with no unrelated changes.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/115-e2e-webserver-proxy

Comment @coderabbitai help to get the list of available commands.

@codecov-commenter

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 67.18%. Comparing base (42747b5) to head (e66b50d).

Additional details and impacted files
@@           Coverage Diff           @@
##             main     #116   +/-   ##
=======================================
  Coverage   67.18%   67.18%           
=======================================
  Files         138      138           
  Lines        4376     4376           
  Branches     1197     1197           
=======================================
  Hits         2940     2940           
  Misses       1218     1218           
  Partials      218      218           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@ryota-murakami ryota-murakami merged commit 888a5b1 into main Jun 24, 2026
25 checks passed
@ryota-murakami ryota-murakami deleted the fix/115-e2e-webserver-proxy branch June 24, 2026 15:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Local pnpm e2e:web can't boot via Playwright webServer (localhost IPv4/IPv6 loopback mismatch)

2 participants