Skip to content

Commit fe9727b

Browse files
JohnMcLearclaude
andauthored
fix(docker): share corepack cache so etherpad user can resolve pnpm (#7689)
* fix(docker): share corepack cache so etherpad user can resolve pnpm (#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> * chore(docker): action Qodo PR review (#7687 follow-up) - 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> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent b751fd7 commit fe9727b

2 files changed

Lines changed: 55 additions & 1 deletion

File tree

.github/workflows/docker.yml

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,51 @@ jobs:
8181
(cd src && pnpm run test-container)
8282
git clean -dxf .
8383
84+
build-test-local-plugin:
85+
# Regression coverage for #7687: the Docker image's
86+
# `bin/installLocalPlugins.sh` step runs as the `etherpad` user and
87+
# invokes pnpm via the corepack shim. A previous corepack/cache bug
88+
# made that path fail when ETHERPAD_LOCAL_PLUGINS was set. This job
89+
# builds the development target with a stub local plugin so the
90+
# regression cannot silently come back.
91+
runs-on: ubuntu-latest
92+
permissions:
93+
contents: read
94+
steps:
95+
-
96+
name: Check out
97+
uses: actions/checkout@v6
98+
with:
99+
path: etherpad
100+
-
101+
name: Set up Docker Buildx
102+
uses: docker/setup-buildx-action@v4
103+
-
104+
name: Stub a local plugin
105+
run: |
106+
mkdir -p etherpad/local_plugins/ep_test_corepack
107+
cat > etherpad/local_plugins/ep_test_corepack/package.json <<'EOF'
108+
{
109+
"name": "ep_test_corepack",
110+
"version": "0.0.1",
111+
"description": "regression-test stub for ether/etherpad#7687",
112+
"main": "index.js"
113+
}
114+
EOF
115+
cat > etherpad/local_plugins/ep_test_corepack/index.js <<'EOF'
116+
exports.placeholder = true;
117+
EOF
118+
-
119+
name: Build with ETHERPAD_LOCAL_PLUGINS (must succeed)
120+
uses: docker/build-push-action@v7
121+
with:
122+
context: ./etherpad
123+
target: development
124+
load: false
125+
build-args: |
126+
ETHERPAD_LOCAL_PLUGINS=ep_test_corepack
127+
cache-from: type=gha
128+
84129
build-test-db-drivers:
85130
# Spinning up MySQL + Postgres + cross-driver smoke is expensive; only
86131
# run it on pushes to develop (and tagged release pushes), not on every

Dockerfile

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,12 +99,21 @@ RUN groupadd --system ${EP_GID:+--gid "${EP_GID}" --non-unique} etherpad && \
9999
ARG EP_DIR=/opt/etherpad-lite
100100
RUN mkdir -p "${EP_DIR}" && chown etherpad:etherpad "${EP_DIR}"
101101

102+
# Share corepack's cache between root (which activates pnpm here) and
103+
# the `etherpad` user (which invokes pnpm later via the corepack shim).
104+
# $COREPACK_HOME defaults to ~/.cache/node/corepack and is per-user;
105+
# without this pin the etherpad user finds an empty cache, re-resolves
106+
# pnpm, and corepack can fall back to "latest" from the registry. See
107+
# https://github.com/ether/etherpad/issues/7687.
108+
ENV COREPACK_HOME=/opt/corepack
109+
102110
# the mkdir is needed for configuration of openjdk-11-jre-headless, see
103111
# https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=863199
104112
RUN \
105-
mkdir -p /usr/share/man/man1 && \
113+
mkdir -p /usr/share/man/man1 "${COREPACK_HOME}" && \
106114
npm install -g corepack@latest && \
107115
corepack enable && corepack prepare pnpm@${PnpmVersion} --activate && \
116+
chown -R etherpad:etherpad "${COREPACK_HOME}" && \
108117
rm -rf /usr/local/lib/node_modules/npm /usr/local/bin/npm /usr/local/bin/npx && \
109118
apk update && apk upgrade && \
110119
apk add --no-cache \

0 commit comments

Comments
 (0)