Skip to content

fix(docker): allowlist patches/ so pnpm patchedDependencies resolve in web build - #833

Merged
tolstenko merged 1 commit into
mainfrom
fix/dockerignore-pnpm-patches
Oct 13, 2026
Merged

tolstenko merged 1 commit into
mainfrom
fix/dockerignore-pnpm-patches

Conversation

@tolstenko

Copy link
Copy Markdown
Contributor

Problem

After the develop→main merge (#696), the Devtron web image build fails at the deps stage:

#16 1.014 ENOENT: no such file or directory, open '/repo/patches/braces@3.0.3.patch'
#16 1.014 pnpm: ENOENT: no such file or directory, open '/repo/patches/braces@3.0.3.patch'
ERROR: process "pnpm install --frozen-lockfile --prefer-offline --store-dir=/pnpm/store" did not complete successfully: exit code: 254

Root cause

.dockerignore is deny-all (**/* plus an allowlist) and never allowlisted patches/. The failure chain:

  1. pruner stage: COPY . . is filtered by .dockerignore → patches/ never enters the build context.
  2. turbo prune --docker only emits patches/ into out/json when the files exist in that context — they don't, so it omits them (verified: prune on a tree without patches/ produces out/json without patches/ while package.json still references the patch paths).
  3. deps stage: pnpm install --frozen-lockfile reads patchedDependencies (pnpm-workspace.yaml + pnpm-lock.yaml path: entries) → ENOENT, exit 254.

patches/ was introduced Oct 5 (braces CVE patch, 8ddfb2d656); the deny-all .dockerignore predates it (Sep 29) — a latent regression that surfaced the first time the tree was built post-merge.

Fix

  • .dockerignore: allowlist patches (one line, !patches — Docker semantics: re-including the dir re-includes its files).

Verification (real docker builds, --no-cache)

Stage origin/main This PR
deps (pnpm install --frozen-lockfile) FAILS — exact ENOENT, exit 254 PASSES — exit 0
pruner out/json/patches/ missing both .patch files present

Regression guard

scripts/ci/tests/dockerignore-pnpm-patches.test.mjs (wired into the always-on classify job in pr-verify):

  • every patchedDependencies path (pnpm-workspace.yaml, pnpm v10 location; falls back to root package.json) must be allowed by .dockerignore
  • every patch path in pnpm-lock.yaml must stay in sync and reachable

Verified the test fails on the broken state (with actionable message) and passes on the fix.

Note: same latent bug exists on develop — will cherry-pick there after this lands.

Pre-existing local-only failures in pull-ci-image.test.mjs (macOS bash 3.2 unbound variable) are unrelated and green on CI.

…n web build

The Devtron web image build fails at the deps stage:

  ENOENT: no such file or directory, open '/repo/patches/braces@3.0.3.patch'
  exit code: 254

.dockerignore is deny-all (`**/*` plus an allowlist) and never allowed
patches/. `turbo prune --docker` therefore runs without the patch files, so
it omits them from out/json, and the subsequent
`pnpm install --frozen-lockfile` cannot resolve the patchedDependencies
declared in pnpm-workspace.yaml.

Allowlist patches/ and lock the invariant with a CI test that fails if any
declared or lockfile-referenced patch path is excluded from the build
context.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Changes recommended

The regression guard can miss declared patches and provides incorrect remediation guidance.

3 open findings
What changed in this PR

Restores pnpm patch availability during Docker web builds and adds regression coverage.

Changes:

  • Allowlists patches/ in the Docker context.
  • Adds an always-on CI invariant test.
File Description
.dockerignore Includes pnpm patch files.
.github/​workflows/​pr-verify.yml Runs the new invariant test.
scripts/​ci/​tests/​dockerignore-pnpm-patches.test.mjs Validates patch configuration and Docker access.

🧠 Review effort: Balanced


💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

// pnpm v10 keeps patchedDependencies in the root pnpm-workspace.yaml (pnpm v9
// kept them in the root package.json `pnpm` key). Accept either location so the
// test survives the config move.
const readPatchedDependencies = () => {

// The pruner `COPY . .` only sees files the .dockerignore allows, and turbo's
// out/json tree preserves each patch at its repository-relative path.
for (const patchPath of Object.values(patched)) {
Comment on lines +99 to +100
`.dockerignore excludes it. Add \`!patches\` (and keep it above the ` +
`deny-all \`**\`) so turbo prune emits it into out/json.`,
@codacy-production

Copy link
Copy Markdown

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

🟢 Metrics 18 complexity

Metric Results
Complexity 18

View in Codacy

NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.

@tolstenko

Copy link
Copy Markdown
Contributor Author

Production-down blocker: the Devtron web image build fails post-#696 merge (ENOENT /repo/patches/braces@3.0.3.patch, exit 254). One-line .dockerignore fix + CI regression guard; root cause and docker-build evidence in the PR description. Cherry-pick already merged to develop (#834, CI green). Needs 2 approvals for main.

@tolstenko
tolstenko merged commit 5c269a2 into main Oct 13, 2026
25 checks passed
@tolstenko
tolstenko deleted the fix/dockerignore-pnpm-patches branch October 13, 2026 00:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants