Skip to content

ci(web-e2e): run against a local API + Neon proxy instead of the deployed API#2541

Merged
andrew-bierman merged 4 commits into
developmentfrom
fix/web-e2e-local-api
Jun 6, 2026
Merged

ci(web-e2e): run against a local API + Neon proxy instead of the deployed API#2541
andrew-bierman merged 4 commits into
developmentfrom
fix/web-e2e-local-api

Conversation

@andrew-bierman

Copy link
Copy Markdown
Collaborator

Problem

Web E2E has been failing on development for days (5+ consecutive runs). globalSetup.ts signs in via a cross-origin browser fetch to the deployed API (EXPO_PUBLIC_API_URL), which returns Failed to fetch (status 0) through all 8 retries — the deployed dev API is 5xx-ing / unreachable from CI. The code comment already assumed "a local wrangler dev worker talking to a raw Postgres," but the workflow never stood one up — it pointed at the deployed API instead.

CORS is not the issue (/^http:\/\/localhost:\d+$/ is already in the API's allowlist). And driving the login UI wouldn't help — the app's client resolves to the same EXPO_PUBLIC_API_URL (getBaseUrl.ts), so it'd make the identical failing request.

Fix

Wire the workflow to the local stack that already exists for local dev (docker-compose.test.yml, maybeConfigureLocalNeon in packages/api/src/index.ts, .dev.vars.e2e.example) — it was used on developer machines (hit "9/14 passing" per the solution doc) but never in CI:

  1. Start Postgres + the Neon HTTP/WS proxy (:4444) via docker-compose.test.yml.
  2. Migrate + seed the e2e user into the local DB (Node-side scripts use raw pg on :5433; the worker uses db.localtest.me → proxy :4444).
  3. Boot the API with wrangler dev on :8787, with a generated .dev.vars (real URLs + dummy-but-schema-valid stand-ins for the ~25 keys env-validation.ts requires; sign-in only needs the DB + Better Auth).
  4. Build the web app against http://localhost:8787 and serve on :8081.
  5. Point Playwright (API_URL / BASE_URL) at the local stack.

Now sign-in runs against a local worker + local DB — no dependency on deployed-API health or cross-origin config, using the same @neondatabase/serverless driver path as production.

⚠️ Iteration-1 — expect CI rounds

I can't exercise this locally (Docker + secrets), so it's push-and-watch. Known open questions the first runs will answer:

  • Does wrangler dev boot cleanly given the container-backed AppContainer Durable Object (image: ./Dockerfile)? If it tries to build that container at boot, the step may need a tweak. Logs are captured (Dump API log on failure).
  • May need repo secrets E2E_BETTER_AUTH_SECRET / E2E_JWT_SECRET (falls back to placeholders).
  • db.localtest.me DNS resolution + migrate/seed connectivity in CI.

Note

The checks job on this PR will show a pre-existing @packrat-ai/nativewindui version mismatch on development (packages/ui ^2.0.6 vs apps/expo 2.0.3-2) — not introduced here; it's resolved by the dependency-policy PR (#2531).


Compound Engineering
Claude Code

…oyed API

Web E2E has been failing on development for days: globalSetup signs in via a
cross-origin fetch to the *deployed* API (EXPO_PUBLIC_API_URL), which returns
'Failed to fetch' (status 0) through all 8 retries — the deployed dev API is
5xx-ing / unreachable from CI. The code comment already assumed 'a local
wrangler dev worker', but the workflow never stood one up.

This wires the workflow to the local stack that already exists for local dev
(docker-compose.test.yml + maybeConfigureLocalNeon + .dev.vars.e2e.example):
- start Postgres + the Neon HTTP/WS proxy (:4444) via docker-compose.test.yml
- migrate + seed the e2e user into the local DB (raw pg on :5433)
- boot the API via 'wrangler dev' on :8787 with a generated .dev.vars
  (real URLs + dummy-but-schema-valid stand-ins for AI/email/storage keys)
- build the web app against http://localhost:8787 and serve it on :8081
- point Playwright (API_URL/BASE_URL) at the local stack

CORS already allows localhost, so sign-in works against the local worker with
no dependency on deployed-API health or cross-origin config.

NOTE: first CI iteration — the open question is whether 'wrangler dev' boots
cleanly given the container-backed AppContainer Durable Object (image:
./Dockerfile); logs are captured (Dump API log on failure) to debug. May also
need E2E_BETTER_AUTH_SECRET / E2E_JWT_SECRET repo secrets (falls back to
placeholders).
Copilot AI review requested due to automatic review settings June 1, 2026 15:54
@coderabbitai

coderabbitai Bot commented Jun 1, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

@andrew-bierman, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 17 minutes and 46 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 80db37c6-159b-4f00-8877-3785069b01c5

📥 Commits

Reviewing files that changed from the base of the PR and between cb9f64d and 5cf3ac3.

📒 Files selected for processing (1)
  • .github/workflows/web-e2e-tests.yml
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/web-e2e-local-api

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Switches the Web E2E workflow from hitting the deployed dev API (which has been failing for days with Failed to fetch) to a fully local stack: a Dockerized Postgres + Neon HTTP/WS proxy, a wrangler dev worker, and the web SPA — all on localhost. This eliminates the cross-origin/deployed‑API dependency that was breaking globalSetup's sign‑in.

Changes:

  • Adds packages/api/** to the workflow's path filters and triggers.
  • Stands up Postgres + Neon proxy via docker-compose.test.yml, runs migrate + seed against raw Postgres on :5433, and writes a synthesized .dev.vars (real DB/auth URLs, placeholder values for AI/email/storage keys) so the worker can boot.
  • Boots wrangler dev on :8787, retargets the Expo build, the served SPA, and Playwright (API_URL/BASE_URL) at localhost; drops the NEON_DEV_DATABASE_URL/EXPO_PUBLIC_API_URL secret dependency and dumps wrangler logs on failure.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +150 to +156
RESEND_API_KEY=e2e-resend-key
EMAIL_FROM=no-reply@packrattest.local
OPENAI_API_KEY=sk-e2e-placeholder
GOOGLE_GENERATIVE_AI_API_KEY=e2e-google-ai
PERPLEXITY_API_KEY=pplx-e2e-placeholder
OPENWEATHER_KEY=e2e-openweather
WEATHER_API_KEY=e2e-weather
First CI run got the full stack up (Postgres + Neon proxy + worker env all
loaded) but wrangler dev failed: the Workers AI binding runs in 'remote' mode
(no local emulator), so wrangler opened a remote-proxy session requiring CF
login. Sign-in never uses AI, and env-validation's AI: z.unknown() tolerates
it absent, so generate an AI-stripped wrangler.e2e.json for the run → no remote
bindings → boots fully local, no CF auth needed. (The container-backed
AppContainer DO booted fine — wrangler only lists it, doesn't build at startup.)
Iteration 2 reached the actual sign-in: the local worker booted and responded,
but POST /api/auth/sign-in/email 500'd because the per-request getEnv()
validation found EMAIL_PROVIDER and AI_PROVIDER missing (required enums). Both
are in .dev.vars.e2e.example; they were omitted from the generated vars. Added
EMAIL_PROVIDER=resend and AI_PROVIDER=openai.
Iter 3 got past env-validation; sign-in now 403'd with 'Invalid origin:
http://localhost:8081'. Elysia CORS allows localhost (OPTIONS 204), but Better
Auth has its own trustedOrigins check that only adds 'http://localhost:*' when
env.ENVIRONMENT === 'development' (auth/index.ts:207) — and the workflow never
set ENVIRONMENT. Add ENVIRONMENT=development to .dev.vars. (The Apple
client-secret pkcs8 warning from the dummy key is harmless — web OAuth only.)
andrew-bierman added a commit that referenced this pull request Jun 1, 2026
…ey fix)

The previous workflow pointed playwright at the deployed API
($EXPO_PUBLIC_API_URL) but this branch's e2e changes assume a fully
local stack — Docker Postgres + Neon HTTP proxy + wrangler dev — with
localhost-trusted origins, ENVIRONMENT=development gating, etc.

Adopt the workflow from PR #2541 (fix/web-e2e-local-api), which:
  - boots a local Neon proxy + Postgres via docker compose
  - writes a CI-only .dev.vars with valid placeholder schema entries
  - generates a no-AI-binding wrangler.e2e.json so wrangler dev doesn't
    need a CF login for the binding
  - runs wrangler dev locally, serves the exported web SPA on :8081
  - drives playwright against that fully-local stack

Re-apply the cache-key fix from c760b79 on top: hash workspace
package.json files too and drop the wildcard restore-keys so the
@babel/helper-compilation-targets nested lru-cache@5 doesn't disappear
between bun.lock-equivalent updates.

This file overlaps with PR #2541; the divergence is just the cache key
hardening. Whichever lands second can keep that delta in a follow-up.
@andrew-bierman andrew-bierman merged commit 700561c into development Jun 6, 2026
8 of 9 checks passed
@andrew-bierman andrew-bierman deleted the fix/web-e2e-local-api branch June 6, 2026 00:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants