Skip to content

e2e: replace nextjs deploy-in-webServer with pnpm injected deps (supersedes #435 approach) #451

Description

@omridevk

Why

e2e/nextjs + e2e/nextjs-component currently pnpm deploy --legacy the app into a mktemp dir inside playwright's webServer.command — a full fresh registry resolution of the workspace graph on every run, under one 180s timeout (the #435 flake). The deploy exists only to give Next/Turbopack a real non-symlinked node_modules (serverExternalPackages requires resolution under node_modules/; workspace symlinks resolve outside it — see b1a96d8).

Spike-verified (3 rounds, evidence in session): pnpm's own primitives replace the whole dance —

  • dependenciesMeta: {"@conciv/it": {"injected": true}} installs a real hard-copy. In-place next dev boots in 0.3-1s, widget spec green, and the builtin server extensions load (plain symlinks reproducibly log failed to load builtin server extensions … MODULE_NOT_FOUND from the terminal extension's dynamic require and go green anyway — silent coverage loss, which disqualifies the zero-injection option).
  • syncInjectedDepsAfterScripts: ["build"] (pnpm ≥10.5, top-level key in pnpm-workspace.yaml) closes the staleness gap: verified the sync fires when turbo spawns the build (turbo shells to pnpm run), fires on direct pnpm --filter run build, and recreates missing/new dist files (inode-verified hardlinks). CI order is safe: test:e2e dependsOn ^build, and the build is what triggers the sync.
  • The packed tarball harness (e2e/nextjs/packed/*) is orthogonal and untouched — it remains the published-shape verifier.

Tasks

T1 — injection config (XS)
dependenciesMeta.injected for the @Conciv runtime deps of both nextjs e2e apps (verify which deps each app's runtime code actually imports — for nextjs it is @conciv/it only; verify nextjs-component equivalently). Add syncInjectedDepsAfterScripts: ["build"] to pnpm-workspace.yaml. Acceptance: injected copies are real dirs with current dist; marker-verified resync after pnpm turbo run build --filter=@conciv/it --force.

T2 — in-place webServer (S)
Both playwright configs: webServer.command = in-place pnpm exec next dev --port <port> only; delete the mktemp/deploy shell chain; tighten webServer timeout to an honest 60s. No deploy helpers, no CLIs, no root-walkers anywhere.

T3 — extension-load guard (S)
The silent-failure mode found in the spike must be a test failure, not a log line: add a positive assertion that builtin server extensions actually loaded (prefer asserting through real behavior/engine surface — e.g. an extension-provided UI or endpoint visible in the existing spec flow; implementer picks the least-invasive honest signal and states it in the PR). A run where extensions fail to load must go red.

T4 — gates + CI validation (S)
Full local gates; then verify on the PR that CI's install→build→e2e order produces fresh injected copies (the spike's mechanism analysis says yes — confirm empirically on the PR run, quote the timings). Expect e2e consumer shard time to drop by the deploy duration.

T5 — cleanup (XS)
Close PR #443 as superseded (its diagnosis was right; this replaces its mechanism). Closes #435. Remove CONCIV_DEPLOY_FRESH references if any landed anywhere.

Deferred, documented

@conciv/it's transitive workspace deps remain symlinked one level down (spike: extensions load correctly with top-level injection alone). If a transitive-symlink resolution bug surfaces later, the lever is dependenciesMeta.injected inside packages/it — do not apply pre-emptively.

Risks

Risk Impact Mitigation
An e2e path exercises a transitive symlink Turbopack mishandles M T3's guard turns it red instead of silent; deferred lever documented
syncInjectedDepsAfterScripts interacts with unrelated packages' build scripts L key is script-name-scoped; verify pnpm install behavior unchanged for the rest of the workspace in T4
nextjs-component has a different dep shape L T1 verifies per-app instead of assuming

🤖 Generated with Claude Code

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions