From d248db1cacb50785bb886b6fa2ed0fed429e2d90 Mon Sep 17 00:00:00 2001 From: Matsu Date: Tue, 25 Aug 2026 10:43:20 +0300 Subject: [PATCH] build: Fix Docker build chain after DHI base drift and the pnpm 11 upgrade (#36984) Co-authored-by: Claude Opus 5 (1M context) --- .github/workflows/build-base-image.yml | 10 ++++----- docker/images/n8n-base/Dockerfile | 2 +- pnpm-workspace.yaml | 4 ++++ scripts/build-n8n.mjs | 31 ++++++++++++-------------- 4 files changed, 24 insertions(+), 23 deletions(-) diff --git a/.github/workflows/build-base-image.yml b/.github/workflows/build-base-image.yml index d8b4f272cc4..dd9e3badecd 100644 --- a/.github/workflows/build-base-image.yml +++ b/.github/workflows/build-base-image.yml @@ -32,11 +32,11 @@ jobs: # when updating. include: - node_version: '22' - dhi_ref: dhi.io/node:22.23.2-alpine3.24-dev@sha256:a6ac21cfbc4bb746c1cfc6cf1501ec13c961ae71558ff2ac7e021caaaf91a224 - - node_version: '24.18.1' - dhi_ref: dhi.io/node:24.18.1-alpine3.24-dev@sha256:074b5aa92e1ce74cd575214211bbcb8d1550710aec59558da734a67d84d31679 - - node_version: '26.5.1' - dhi_ref: dhi.io/node:26.5.1-alpine3.24-dev@sha256:c4062f85acd1ca91ffb7d15048dcc5f15a922d630e65eb3c3c0dcdcef6ea36d8 + dhi_ref: dhi.io/node:22.23.2-alpine3.24-dev@sha256:155a95d59244a71e9479e191ff718f03a7197d6829612e0707608be92988cb87 + - node_version: '24.19.0' + dhi_ref: dhi.io/node:24.19.0-alpine3.24-dev@sha256:dc2989ad23938772abaf549ed7bde5d61d70377005229bb55bef94bff40f8bbd + - node_version: '26.7.0' + dhi_ref: dhi.io/node:26.7.0-alpine3.24-dev@sha256:4b494d89fb26c950ce97865acf45b480dc7a6868fdc2b81c2d66599702eeac3f steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 diff --git a/docker/images/n8n-base/Dockerfile b/docker/images/n8n-base/Dockerfile index acc6c001d99..1f2a82aa961 100644 --- a/docker/images/n8n-base/Dockerfile +++ b/docker/images/n8n-base/Dockerfile @@ -1,6 +1,6 @@ # CI passes one DHI reference per published Node version (see the matrix in # build-base-image.yml). The default keeps plain `docker build` working. -ARG DHI_REF=dhi.io/node:24.18.1-alpine3.24-dev@sha256:074b5aa92e1ce74cd575214211bbcb8d1550710aec59558da734a67d84d31679 +ARG DHI_REF=dhi.io/node:24.19.0-alpine3.24-dev@sha256:dc2989ad23938772abaf549ed7bde5d61d70377005229bb55bef94bff40f8bbd FROM ${DHI_REF} # Install all dependencies in a single layer to minimize image size diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 0008cadf26c..5e61b8ba4dc 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -12,6 +12,10 @@ hoistPattern: - '*' - '!typescript' allowUnusedPatches: true +# The docker build trims frontend manifests and deploys with --prod before later +# scripts run; pnpm 11's pre-run install would reinstall production-only and prune +# the devDependencies those scripts import. +verifyDepsBeforeRun: false pmOnFail: warn fund: false diff --git a/scripts/build-n8n.mjs b/scripts/build-n8n.mjs index 0427425cbe1..aff6ddf2970 100755 --- a/scripts/build-n8n.mjs +++ b/scripts/build-n8n.mjs @@ -10,6 +10,7 @@ import { $, echo, fs, chalk } from 'zx'; import path from 'path'; +import os from 'os'; // Check if running in a CI environment const isCI = process.env.CI === 'true'; @@ -123,14 +124,13 @@ const packageJsonFiles = await $`cd ${config.rootDir} && find . -name "package.j -not -path "./compiled/*" \ -type f`.lines(); -// Backup all package.json files -// This is only needed locally, not in CI -if (process.env.CI !== 'true') { - for (const file of packageJsonFiles) { - if (file) { - const fullPath = path.join(config.rootDir, file); - await fs.copy(fullPath, `${fullPath}.bak`); - } +// Backup all package.json files. The FE trim below mutates them, and pnpm verifies +// the lockfile before running any later script, which fails until they are restored. +// Backups live outside the workspace: siblings would be packed into the deployment. +const packageJsonBackupDir = await fs.mkdtemp(path.join(os.tmpdir(), 'n8n-build-pkgjson-')); +for (const file of packageJsonFiles) { + if (file) { + await fs.copy(path.join(config.rootDir, file), path.join(packageJsonBackupDir, file)); } } // Run FE trim script @@ -303,18 +303,15 @@ if (generateLicenses) { } // Restore package.json files -// This is only needed locally, not in CI -if (process.env.CI !== 'true') { - for (const file of packageJsonFiles) { - if (file) { - const fullPath = path.join(config.rootDir, file); - const backupPath = `${fullPath}.bak`; - if (await fs.pathExists(backupPath)) { - await fs.move(backupPath, fullPath, { overwrite: true }); - } +for (const file of packageJsonFiles) { + if (file) { + const backupPath = path.join(packageJsonBackupDir, file); + if (await fs.pathExists(backupPath)) { + await fs.move(backupPath, path.join(config.rootDir, file), { overwrite: true }); } } } +await fs.remove(packageJsonBackupDir); // Calculate output size const compiledAppOutputSize = (await $`du -sh ${config.compiledAppDir} | cut -f1`).stdout.trim();