Skip to content

fix(e2e): deploy packed apps before webServer, avoid fresh resolution (#435) - #443

Closed
omridevk wants to merge 1 commit into
mainfrom
fix/435-e2e-deploy-resolve
Closed

fix(e2e): deploy packed apps before webServer, avoid fresh resolution (#435)#443
omridevk wants to merge 1 commit into
mainfrom
fix/435-e2e-deploy-resolve

Conversation

@omridevk

Copy link
Copy Markdown
Contributor

Diagnosis

#435: Error: Timed out waiting 180000ms from config.webServer. on the nextjs e2e shard
(run 31548790369 attempt 7). webServer.command in e2e/nextjs/playwright.config.ts and
e2e/nextjs-component/playwright.config.ts ran pnpm --filter <app> deploy --legacy --prod=false
then next dev, both inside one 180s webServer budget.

Reproduced locally: pnpm --filter conciv-e2e-nextjs deploy --legacy --prod=false <dir> shows
[WARN] Shared workspace lockfile detected but configuration forces legacy deploy implementation.
then does a completely fresh dependency resolution — Progress: resolved 229, reused 0, downloaded 0
(exact match to the CI log quoted in the issue), climbing to resolved 2705, reused 0 before next dev
is even spawned. Individual registry metadata requests stall for seconds ([WARN] Request took 10384ms: https://registry.npmjs.org/playwright-core, 29962ms: .../drizzle-orm). next dev itself
boots in well under a second once the deploy is done.

Fix

  1. Stop the fresh resolve. deploy.ts now runs the legacy deploy with --prefer-offline (skip
    CONCIV_DEPLOY_FRESH=1 to opt back into a live consumer-realism resolve, mirroring the
    CONCIV_PACKED_FRESH=1 convention from fix(e2e): resolve packed installs from a committed lockfile #378's packed-lockfile fix). --prefer-offline skips the
    per-package staleness-revalidation GET that --offline/no-flag both pay for on every already-cached
    package — that revalidation round trip is exactly what the CI log's [WARN] Request took 10384ms: .../playwright-core lines are.

    --legacy deploy resolves against the whole workspace graph, not just the deployed package's own
    deps (confirmed: [WARN] Shared workspace lockfile detected but configuration forces legacy deploy implementation — pnpm sees the workspace lockfile and would normally reuse it, but --legacy
    deliberately discards that reuse and re-resolves from scratch instead, floating any "latest"-pinned
    specifier anywhere in the 68-package workspace, e.g. e2e/tanstack-start's
    @tanstack/react-router: latest, to whatever the registry says right now). That ruled out the
    stricter --offline: it hard-errors (ERR_PNPM_NO_OFFLINE_META, reproduced locally resolving
    @neodrag/solid@3.0.0-next.11 pulled in transitively via a newer @tanstack/react-devtools) the
    moment that live re-resolution lands on a version whose metadata was never fetched. --prefer-offline
    degrades gracefully instead: reuse the cache when it has the answer, fetch live only when it
    doesn't, never error.

    Verified locally (same store, same lockfile, controlled A/B): --offline failed outright with
    ERR_PNPM_NO_OFFLINE_META; --prefer-offline completed clean with zero [WARN] Request took
    stalls in the log, resolved 2705, reused 0, downloaded 3, exit 0. Modern (non-legacy) deploy was
    also tried and rejected: it requires inject-workspace-packages=true workspace-wide
    (ERR_PNPM_DEPLOY_NONINJECTED_WORKSPACE), a much larger blast-radius config change than this issue
    warrants and out of scope per the dispatch's scope guard.

  2. Decouple deploy from webServer's clock. @conciv/e2e-utils gets a deployPackedApp helper
    (e2e/e2e-utils/src/deploy.ts) plus a deploy-cli.ts entry point, invoked from each app's
    test:e2e script before playwright test starts:
    "test:e2e": "pnpm --filter @conciv/e2e-utils run deploy nextjs conciv-e2e-nextjs && playwright test".
    The deploy target is now a deterministic path (deployDir(app) in config.ts, under
    os.tmpdir()/conciv-e2e-deploy/<app>) shared between the pretest deploy step and
    webServer.command, which is now just cd "<dir>" && pnpm exec next dev --port <port>.
    e2eConfig() grew a webServerTimeout option (default unchanged, 180s) so the two apps that no
    longer do any installing inside their webServer command can tighten it to 60s — comfortable
    headroom over the observed ~1-10s next-dev + first-compile time — without touching every other
    e2e app's webServer timeout. Applied identically to
    both nextjs and nextjs-component, the only two apps using this deploy pattern (surveyed every
    e2e/*/playwright.config.ts; no other app matches).

    Playwright always starts webServer before running globalSetup (confirmed in
    playwright/lib/runner/index.js: createGlobalSetupTasks runs plugin setup — which starts
    webServer — before the globalSetups task), so globalSetup isn't usable for this; a pretest
    npm-script step is.

Trade-off: local iterative pnpm test:e2e reruns now always redeploy first (previously, with
reuseExistingServer: true outside CI, an already-running dev server would skip the deploy step
inline in webServer.command). CI never reuses, so this doesn't affect the actual bug; noted here
for anyone iterating locally.

Gates

  • pnpm turbo run typecheck --filter=@conciv/e2e-utils --filter=conciv-e2e-nextjs --filter=conciv-e2e-nextjs-component — pass
  • pnpm turbo run test:e2e --filter=conciv-e2e-nextjs --concurrency=1 — pass, 10/10 (6.5m)
  • pnpm turbo run test:e2e --filter=conciv-e2e-nextjs-component --concurrency=1 — pass, 1/1 (18.7s)
  • pnpm lint — pass (pre-existing unrelated warnings only)
  • pnpm format:check — pass on all touched files (one pre-existing unrelated failure in
    docs/assets/page-session-card-spike/fake-form.html, untouched by this diff)
  • pnpm exec fallow audit --changed-since main --format json — pass, zero introduced findings

Closes #435

🤖 Generated with Claude Code

…resh resolution (#435)

pnpm --filter <app> deploy --legacy discards the workspace lockfile and
does a fully independent resolution of the whole 2700+ package workspace
graph, previously run inside playwright's webServer.command alongside
next dev, all under one 180s timeout. On CI the resolution phase alone
(individual registry metadata requests, 10-30s each) could exhaust the
budget before next dev (which boots in under a second) ever started.

- deployPackedApp() (e2e/e2e-utils/src/deploy.ts) runs the legacy deploy
  with --prefer-offline, which skips the per-package staleness
  revalidation GET that was the actual bottleneck, while still falling
  back to a live fetch for anything not cached (unlike --offline, which
  hard-errors the moment a workspace-wide "latest" specifier floats to a
  version nothing has fetched yet - reproduced locally resolving
  @neodrag/solid via a newer @tanstack/react-devtools). CONCIV_DEPLOY_FRESH=1
  opts back into a live resolve, mirroring #378's CONCIV_PACKED_FRESH=1.
- Each app's test:e2e script now runs the deploy as a pretest step
  (`pnpm --filter @conciv/e2e-utils run deploy <app> <pnpmFilter> &&
  playwright test`), before playwright's webServer phase even starts.
  webServer.command is now just `cd <deployDir> && next dev`, and
  e2eConfig() grew a webServerTimeout option so nextjs/nextjs-component
  can tighten their webServer budget to 60s without touching the other
  e2e apps' 180s default.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@omridevk, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 36 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

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.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: f2d3603e-ef58-4b8f-8172-18ab63bd5c96

📥 Commits

Reviewing files that changed from the base of the PR and between 09d466d and f29042e.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (10)
  • e2e/e2e-utils/package.json
  • e2e/e2e-utils/src/config.ts
  • e2e/e2e-utils/src/deploy-cli.ts
  • e2e/e2e-utils/src/deploy.ts
  • e2e/e2e-utils/src/ports.ts
  • e2e/nextjs-component/package.json
  • e2e/nextjs-component/playwright.config.ts
  • e2e/nextjs/package.json
  • e2e/nextjs/playwright.config.ts
  • turbo.json

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

@omridevk

Copy link
Copy Markdown
Contributor Author

Superseded by #452 (injected-deps redesign per #451) — deploy-in-webServer approach abandoned.

@omridevk omridevk closed this Aug 12, 2026
@omridevk
omridevk deleted the fix/435-e2e-deploy-resolve branch August 12, 2026 20:55
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.

flaky: e2e consumer webServer boot timeout (180s) on nextjs shard

1 participant