Skip to content

Added CI guard against pnpm patched dependencies#28014

Closed
9larsons wants to merge 1 commit into
mainfrom
ci-guard-no-pnpm-patches
Closed

Added CI guard against pnpm patched dependencies#28014
9larsons wants to merge 1 commit into
mainfrom
ci-guard-no-pnpm-patches

Conversation

@9larsons
Copy link
Copy Markdown
Contributor

Summary

Adds a CI check that fails if the repo declares pnpm patchedDependencies, preventing a recurrence of the broken production build fixed in #28011 (introduced by #28009).

pnpm patch is structurally incompatible with Ghost's production build: Dockerfile.production installs from the packed ghost/core archive, which doesn't include the repo-root patches/ directory — so pnpm install --prod aborts with ENOENT on the patch file. There's no "correct" way to use it, so the check is a flat hard-fail: pnpm patch is not supported in this repo.

What it does

  • New script .github/scripts/check-no-patched-dependencies.js — fails if patchedDependencies is declared in either package.json (pnpm.patchedDependencies) or pnpm-workspace.yaml (pnpm 10 allows both).
  • Wired into the Lint job, before pnpm install, so it fails in seconds rather than after a ~7-minute Docker build.
  • It only targets patchedDependencies — that's the only pnpm config field that references external files. overrides, packageExtensions, and onlyBuiltDependencies are pure in-package.json config and install fine in the prod image.

Complementary action (not code)

The other half of preventing this — making Build & Publish Artifacts a required status check on main — is a branch-protection setting, not a code change. #28009 merged red because that job's failure only caused its dependent E2E jobs to skip, and skipped required checks count as passing. That has to be set in repo Settings → Branches.

`pnpm patch` is incompatible with Ghost's production build:
Dockerfile.production installs from the packed ghost/core archive, which
does not include the repo-root patches/ directory, so `pnpm install
--prod` fails with ENOENT on the patch file. #28009 shipped such a patch
and broke Build & Publish on main.

Adds a check to the Lint job that fails if `patchedDependencies` is
declared in either package.json or pnpm-workspace.yaml — giving fast
feedback (~seconds) instead of a ~7-minute Docker build failure, and
making "don't use pnpm patch" an enforced rule rather than a convention.
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 21, 2026

Review Change Stack

Walkthrough

This PR adds a Node.js CI guard script that fails the pipeline if pnpm patchedDependencies are detected. The script reads package.json to check for non-empty pnpm.patchedDependencies and scans pnpm-workspace.yaml for inline or block patchedDependencies: entries. If violations are found, it prints a formatted CI error message with remediation steps and exits with code 1; otherwise it logs success. The script is integrated into the linting job as an early verification step.

Possibly related PRs

  • TryGhost/Ghost#28011: Removes patchedDependencies entries from the codebase; this PR adds the CI guard to prevent their reintroduction.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main change: adding a CI guard against pnpm patched dependencies.
Description check ✅ Passed The description is detailed and directly related to the changeset, explaining the rationale, what the script does, and how it's integrated.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch ci-guard-no-pnpm-patches

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
.github/scripts/check-no-patched-dependencies.js (1)

27-41: 💤 Low value

Consider checking additional lines for more robust block-entry detection.

The current logic checks only lines[idx + 1] for block entries. This could miss cases where an empty line appears between patchedDependencies: and its first entry:

patchedDependencies:

  foo@1.0.0: patches/foo.patch

Given the intentional trade-off (lightweight text scan vs. YAML parser dependency) and the low likelihood of this formatting in auto-generated patches, this is acceptable. However, if you want to strengthen the detection, consider checking a few lines ahead:

Optional enhancement to detect block entries across empty lines
 const workspaceFile = path.join(repoRoot, 'pnpm-workspace.yaml');
 if (fs.existsSync(workspaceFile)) {
     const lines = fs.readFileSync(workspaceFile, 'utf8').split('\n');
     const idx = lines.findIndex(line => /^patchedDependencies:/.test(line));
     if (idx !== -1) {
         const inline = lines[idx].slice('patchedDependencies:'.length).trim();
         const hasInlineEntries = inline !== '' && inline !== '{}';
-        const hasBlockEntries = /^\s+\S/.test(lines[idx + 1] || '');
+        // Check next few lines to handle empty lines or comments
+        const hasBlockEntries = lines.slice(idx + 1, idx + 4).some(line => 
+            /^\s+[^#\s]/.test(line) // Indented non-comment line
+        );
         if (hasInlineEntries || hasBlockEntries) {
             offenders.push('pnpm-workspace.yaml -> patchedDependencies');
         }
     }
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/scripts/check-no-patched-dependencies.js around lines 27 - 41, The
block-entry detection for patchedDependencies only inspects lines[idx + 1], so
it misses cases with one or more blank lines after the header; update the check
around patchedDependencies to scan forward a few lines (e.g., loop from idx+1 to
idx+N) skipping blank lines and test each for a non-indented entry, replacing
the single-line check that sets hasBlockEntries; refer to the existing
variables/workflow (workspaceFile, lines, idx, hasInlineEntries,
hasBlockEntries, offenders) and stop the scan early if you hit another top-level
key or end of file.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In @.github/scripts/check-no-patched-dependencies.js:
- Around line 27-41: The block-entry detection for patchedDependencies only
inspects lines[idx + 1], so it misses cases with one or more blank lines after
the header; update the check around patchedDependencies to scan forward a few
lines (e.g., loop from idx+1 to idx+N) skipping blank lines and test each for a
non-indented entry, replacing the single-line check that sets hasBlockEntries;
refer to the existing variables/workflow (workspaceFile, lines, idx,
hasInlineEntries, hasBlockEntries, offenders) and stop the scan early if you hit
another top-level key or end of file.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: f4dca963-1ef2-426b-a359-55eaa6dd1cfc

📥 Commits

Reviewing files that changed from the base of the PR and between bd46a1c and 40f5eae.

📒 Files selected for processing (2)
  • .github/scripts/check-no-patched-dependencies.js
  • .github/workflows/ci.yml

@codecov
Copy link
Copy Markdown

codecov Bot commented May 21, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 73.83%. Comparing base (bd46a1c) to head (40f5eae).

Additional details and impacted files
@@           Coverage Diff           @@
##             main   #28014   +/-   ##
=======================================
  Coverage   73.83%   73.83%           
=======================================
  Files        1523     1523           
  Lines      128982   128982           
  Branches    15483    15483           
=======================================
  Hits        95233    95233           
  Misses      32787    32787           
  Partials      962      962           
Flag Coverage Δ
admin-tests 53.57% <ø> (ø)
e2e-tests 73.83% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@9larsons 9larsons closed this May 21, 2026
@9larsons 9larsons deleted the ci-guard-no-pnpm-patches branch May 31, 2026 22:04
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.

1 participant