fix(docker): share corepack cache so etherpad user can resolve pnpm#7689
Merged
JohnMcLear merged 2 commits intodevelopfrom May 7, 2026
Merged
fix(docker): share corepack cache so etherpad user can resolve pnpm#7689JohnMcLear merged 2 commits intodevelopfrom
JohnMcLear merged 2 commits intodevelopfrom
Conversation
…7687) PR #7674 switched the Dockerfile from `npm install -g pnpm` to corepack and `corepack prepare pnpm@${PnpmVersion} --activate`. The activate step runs as root and writes its lastKnownGood pin into `$COREPACK_HOME`, which defaults to `~/.cache/node/corepack` — i.e. a per-user path. The Dockerfile then drops to `USER etherpad` and later runs `bin/installLocalPlugins.sh`, which invokes `pnpm` as etherpad. With an empty per-user corepack cache and no shared activation file, corepack re-resolves pnpm and (for forks/configs without a `packageManager` pin matching the activated version) can fall back to "latest" from the registry — pulling `pnpm@10.33.4` instead of the requested 11.x and failing the workspace's `engines.pnpm` check. Pin `COREPACK_HOME=/opt/corepack` and chown it to etherpad after the prepare step. Both root and etherpad now share the same lastKnownGood file and tarball cache, so etherpad inherits the activated pnpm without hitting the registry again. Verified end-to-end: - `docker build --target development --build-arg ETHERPAD_LOCAL_PLUGINS=ep_test` with a stub local plugin runs `installLocalPlugins.sh` cleanly: `Done in 16.6s using pnpm v11.0.6`. - `docker run ... pnpm --version` as etherpad reports 11.0.6 from the shared cache — no "Unsupported environment" error. Note: corepack still emits a one-time "about to download" line at runtime because `corepack prepare pnpm@11.0.6` resolves to the highest matching patch (11.0.8) at build time while the project's `packageManager` field pins exactly 11.0.6. That's a follow-up — the download succeeds non-interactively and the engine check passes. Fixes #7687. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
ⓘ You've reached your Qodo monthly free-tier limit. Reviews pause until next month — upgrade your plan to continue now, or link your paid account if you already have one. |
Review Summary by QodoShare corepack cache between root and etherpad user
WalkthroughsDescription• Pins COREPACK_HOME=/opt/corepack to share pnpm cache between root and etherpad user • Prevents corepack from re-resolving pnpm and falling back to latest version • Fixes etherpad user's inability to resolve correct pnpm version during plugin installation • Ensures bin/installLocalPlugins.sh uses activated pnpm 11.0.6 instead of registry fallback Diagramflowchart LR
A["Root activates pnpm<br/>via corepack"] -->|writes to COREPACK_HOME| B["Shared /opt/corepack<br/>cache directory"]
B -->|chown to etherpad| C["Etherpad user<br/>inherits activation"]
C -->|pnpm resolved| D["installLocalPlugins.sh<br/>succeeds"]
File Changes1. Dockerfile
|
Code Review by Qodo
1. COREPACK_HOME fix lacks test
|
Comment on lines
+102
to
+116
| # Share corepack's cache between root (which activates pnpm here) and | ||
| # the `etherpad` user (which invokes pnpm later via the corepack shim). | ||
| # $COREPACK_HOME defaults to ~/.cache/node/corepack and is per-user; | ||
| # without this pin the etherpad user finds an empty cache, re-resolves | ||
| # pnpm, and corepack can fall back to "latest" from the registry. See | ||
| # https://github.com/ether/etherpad/issues/7687. | ||
| ENV COREPACK_HOME=/opt/corepack | ||
|
|
||
| # the mkdir is needed for configuration of openjdk-11-jre-headless, see | ||
| # https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=863199 | ||
| RUN \ | ||
| mkdir -p /usr/share/man/man1 && \ | ||
| mkdir -p /usr/share/man/man1 /opt/corepack && \ | ||
| npm install -g corepack@latest && \ | ||
| corepack enable && corepack prepare pnpm@${PnpmVersion} --activate && \ | ||
| chown -R etherpad:etherpad /opt/corepack && \ |
There was a problem hiding this comment.
1. Corepack_home fix lacks test 📘 Rule violation ⚙ Maintainability
This PR fixes a Docker build bug (Corepack cache visibility across USER switch) but does not add an automated regression test to ensure the local plugin install path keeps using pnpm >=11 in future changes. Without a CI check that builds with ETHERPAD_LOCAL_PLUGINS set, the original failure mode can silently reappear.
Agent Prompt
## Issue description
The Dockerfile bug fix is not protected by an automated regression test that exercises the local plugin installation path (the path that runs `pnpm` during image build).
## Issue Context
The reported failure happens when `ETHERPAD_LOCAL_PLUGINS` is set, causing `bin/installLocalPlugins.sh` to run `pnpm`. Current CI builds the Docker image but does not build with local plugins enabled, so the regression scenario is not automatically checked.
## Fix Focus Areas
- .github/workflows/docker.yml[36-82]
- bin/installLocalPlugins.sh[36-51]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
- Replace hard-coded /opt/corepack with ${COREPACK_HOME} in mkdir/chown
so the env var stays the single source of truth (Qodo: "COREPACK_HOME
path duplication").
- Add a build-test-local-plugin job to .github/workflows/docker.yml that
builds the development target with a stub ETHERPAD_LOCAL_PLUGINS so
the original failure mode (corepack/pnpm cache invisible across the
USER switch) cannot silently regress (Qodo: "COREPACK_HOME fix lacks
test"). The job is small — `docker build` only, no run — and uses the
shared GHA buildx cache.
Verified: same docker build + `docker run pnpm --version` flow on the
variable form gives identical output (pnpm 11.0.6 from the etherpad-owned
cache).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
COREPACK_HOME=/opt/corepackand chowns it to theetherpaduser, so the corepacklastKnownGoodactivation file written by root is visible after theUSER etherpadswitch.bin/installLocalPlugins.shinvokespnpm; corepack re-resolves and (for builds without a matchingpackageManagerpin) falls back topnpm@latest(currently 10.33.4), failing the workspace'sengines.pnpmcheck.Why
PR #7674 (docker CVE sweep) replaced
npm install -g pnpmwithcorepack prepare pnpm@${PnpmVersion} --activate.corepack prepare --activatewrites to$COREPACK_HOME, which defaults to~/.cache/node/corepack— a per-user path. We activate as root, then drop toetherpad, whose home dir has no cache. Sharing$COREPACK_HOMEis the smallest fix.Reported by @ferrlen in #7687 — they hit:
Test plan
docker build --target build .succeeds.docker run --rm <build> sh -c 'pnpm --version'asetherpadreports the activated pnpm version (11.0.6) instead of falling back to "latest".docker build --target development --build-arg ETHERPAD_LOCAL_PLUGINS=ep_test_corepack .with a stub local plugin runsinstallLocalPlugins.shcleanly (Done in 16.6s using pnpm v11.0.6) — the original failure scenario.Follow-up (not blocking)
corepack prepare pnpm@11.0.6 --activateresolves to the highest matching patch (11.0.8) and caches that, whilepackage.jsonpinspackageManager: "pnpm@11.0.6"exactly. Result: corepack emits a one-time "about to download pnpm-11.0.6.tgz" line at runtime even though the activated version is in the cache. Functional, just inefficient — worth a separate small PR to either drop thepackageManagerexact pin or align with corepack's resolution.🤖 Generated with Claude Code