build: Deploy production closures without pnpm deploy --legacy (no-changelog) - #37890
build: Deploy production closures without pnpm deploy --legacy (no-changelog)#37890shortstacked wants to merge 3 commits into
Conversation
Use the dedicated-lockfile deploy with command-scoped workspace injection for the n8n, task-runner and engine closures. The legacy deploy re-resolves the workspace against the registry on every build; the dedicated lockfile is derived from pnpm-lock.yaml. Move editor-ui dependencies to devDependencies: the package ships a bundle and its dependencies must stay out of the lockfile-derived closure. Drop the build-time manifest trim, which the lockfile-derived deploy does not read. Declare pg-native as a typeorm devDependency so the auto-installed optional peer stays out of the production closure. Keep the task-runner closure extendable with pnpm add: restore the source specifiers, record the closure under its workspace importer, and remove the pnpm files that point at this checkout. Link the runtime pnpm to the executable bin/pnpm.mjs.
|
Running ultrareview automatically — Cross-cutting rewrite of production closure deployment for the n8n/engine/runners Docker images, moving runtime dependencies to devDependencies and changing pnpm deploy semantics—any missed dependency or peer-resolution change could break the built images at runtime.. I'll post findings when complete. |
PR review overviewBased on ownership of the 10 changed files in this PR:
|
Bundle ReportBundle size has no change ✅ Affected Assets, Files, and Routes:view changes for bundle: editor-ui-esmAssets Changed:
|
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
… test The dedicated-lockfile deploy names a workspace package after its absolute file: URL and materializes each one once, including @n8n/ai-utilities. Allow devDependency imports across editor-ui: the package bundles everything it imports, so all of its dependencies are devDependencies now.
There was a problem hiding this comment.
0 issues found across 2 files (changes from recent commits).
Confidence score: 5/5
- Automated review surfaced no issues in the provided summaries.
- No files require special attention.
Shadow auto-approve: would not auto-approve. Auto-approval blocked by 3 unresolved issues from previous reviews.
Re-trigger cubic
… deploy change The frontend module scaffolder anchored on editor-ui's dependencies block, which is now devDependencies. The engine image copies the whole deploy output, so drop pnpm's deploy-only files there too. Add an image smoke check that extends the JS runner with pnpm add, the flow derived images use, so a deploy that makes pnpm prune the runner fails the build.
There was a problem hiding this comment.
0 issues found across 4 files (changes from recent commits).
Confidence score: 5/5
- Automated review surfaced no issues in the provided summaries.
- No files require special attention.
Shadow auto-approve: would not auto-approve. Auto-approval blocked by 2 unresolved issues from previous reviews.
Re-trigger cubic
Summary
Deploys the n8n, task-runner and engine production closures with pnpm's dedicated-lockfile deploy instead of
pnpm deploy --legacy. Supersedes #37866, tracked in DEVP-440.The legacy deploy re-resolves the workspace against the registry on every build (~900MB of metadata on the cold cache every CI Docker job starts with). The dedicated lockfile is derived from
pnpm-lock.yamland mostly copies files.CI,
Docker Build Smoke Test(no cache), master vs this PRThe n8n deploy is now bound by materializing ~113k files, not by resolution. Image size is unchanged:
n8nio/n8n1.86GB → 1.87GB,n8nio/runners844MB → 844MB.Changes
scripts/build-n8n.mjs— both deploys use--prod --config.inject-workspace-packages=true. The workspace-package glob matches pnpm's naming on Linux and macOS. Adds a timer for the task-runner deploy. Drops pnpm's deploy-only files (pnpm-lock.yaml,pnpm-workspace.yaml, workspace state) fromcompiled/so cdxgen keeps inventoryingnode_modulesfor the SBOM.packages/frontend/editor-ui—dependencies→devDependencies. The package ships a Vite bundle and its published manifest already has no dependencies. A lockfile-derived closure ignores the build-time manifest trim, so this is what keeps the frontend libraries out of the image. The trim call is removed from the build;release-publish.ymlstill uses the script. Lint allows devDependency imports across the package; the module scaffolder anchors ondevDependencies.packages/@n8n/typeorm—pg-nativedeclared as a devDependency.autoInstallPeersrecords the optional peer underdependencies, which pulledpg-native+libpqinto the closure. TypeORM switches to the native driver whenpg-nativeloads.pnpm add(the runners Dockerfiles addmoment; users extend derived images per the docs). The raw deploy output is not: its manifest carriesfile:and peer-suffixed specifiers and pnpm prunes the whole runner on the nextpnpm add(+4 -438). The build restores the source specifiers and records the closure underpackages/@n8n/task-runnerwith an empty root importer — the shape the legacy deploy wrote.docker/images/runners/Dockerfile— the runtimepnpmsymlink now points atbin/pnpm.mjs. It pointed atbin/pnpm.cjs, which ships without the execute bit, sopnpmin the published image fails withPermission denied(pnpm: Permission denied #37808, since build: Install pnpm from npm in the runners images (no-changelog) #36702).scripts/smoke-n8n-image.mjs— the workspace-package check matches the new naming and no longer allows the@n8n/ai-utilitiesdouble copy (the new deploy materializes every workspace package once). New check:pnpm add uuidinn8nio/runners:localmust extend the closure and keep the runner resolving. It fails on the current master image and passes here.packages/@n8n/engine— same deploy flags; deploy-only pnpm files removed fromcompiled/.Not changed
@langchain/corestill resolves to two peer variants in the n8n closure; master has the same two copies and the verifier stays report-only. pnpm 12 was benchmarked: no deploy speed gain over this, rejects then8nclosure withERR_PNPM_DEPLOY_AMBIGUOUS_PEER(vuepeer variants that differ only by a dev-onlytypescriptalias), and leaves an unreferenced 173MB tree on macOS. That is a separate upgrade decision.How to test
pnpm build:docker— expect✅ Task runner deployment completed in …s,✅ Task runner closure is extendable, closure ~1.3GB / ~113k files.pnpm build:docker:smoke(needshelm) — all checks pass, includingpnpm add extends the JS runner in n8nio/runners:local.docker run --rm --entrypoint sh n8nio/runners:local -c 'pnpm --version'prints11.25.0.n8nio/n8n:localand open the editor.N8N_GENERATE_LICENSES=true node scripts/build-n8n.mjsrenders the SBOM andTHIRD_PARTY_LICENSES.md(1489 components, all licenses valid).Related Linear tickets, Github issues, and Community forum posts
https://linear.app/n8n/issue/DEVP-440
fixes #37808
Review / Merge checklist
Backport to Beta,Backport to Stable, orBackport to v1(if the PR is an urgent fix that needs to be backported)🤖 PR Summary generated by AI