Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/docker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ jobs:
# Regression test for #7718. Reproduces the production
# docker-compose layout reported in that issue: a named volume
# mounted on src/plugin_packages with no TTY allocated. Under
# the previous `CMD ["pnpm", "run", "prod"]`, pnpm 11's
# the previous `CMD ["pnpm", "run", "prod"]`, pnpm's
# runDepsStatusCheck spuriously decided node_modules was out of
# sync at boot and tried to wipe + reinstall, aborting with
# ERR_PNPM_ABORTED_REMOVE_MODULES_DIR_NO_TTY before the HTTP
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ jobs:
cache-dependency-path: etherpad/pnpm-lock.yaml
- name: Install dependencies ether.github.com
# ether.github.com depends on sharp (Next.js image pipeline), whose
# install script must run to fetch the platform binary. pnpm 11
# install script must run to fetch the platform binary. pnpm
# turned ignored-builds into an error; allow all builds for this
# external repo since we don't control its pnpm-workspace.yaml.
run: pnpm install --frozen-lockfile --config.dangerously-allow-all-builds=true
Expand Down
32 changes: 15 additions & 17 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@
# docker build --build-arg BUILD_ENV=copy .
ARG BUILD_ENV=git

# NOTE: this intentionally lags the "packageManager" pin in package.json. pnpm
# 11.1.x enforces the minimum-release-age supply-chain policy during install,
# which the frozen-lockfile Docker build can't satisfy, so the image stays on
# 11.0.x. The version gap is made harmless by pnpm_config_pm_on_fail=ignore in
# the build stage below — see ether/etherpad#7911.
ARG PnpmVersion=11.0.6
# NOTE: this tracks the "packageManager" pin in package.json. pnpm's
# minimum-release-age supply-chain policy (enforced during install) is satisfied
# by the `minimumReleaseAgeExclude` list in pnpm-workspace.yaml, so the image no
# longer needs to lag the pin the way it did during the pnpm 11.1.x era — see
# ether/etherpad#7911.
ARG PnpmVersion=12.4.2

FROM node:24-alpine AS adminbuild
# Install pnpm directly via npm (rather than via corepack) so the same
Expand All @@ -33,15 +33,13 @@ RUN pnpm run build:ui
FROM node:24-alpine AS build
LABEL maintainer="Etherpad team, https://github.com/ether/etherpad"

# The image's pnpm intentionally lags the "packageManager" pin (see the ARG
# note above). pnpm would otherwise try to self-provision the pinned version on
# invocation — including the informational `pnpm --version` probe Etherpad runs
# at startup — which fails closed with no network and breaks air-gapped boots
# (ether/etherpad#7911). pm_on_fail=ignore makes pnpm use the installed version
# instead. Inherited by the development and production runtime stages, so it
# also covers the updater's pnpm-on-PATH check and ad-hoc `pnpm` in an exec
# shell. It does not change which pnpm runs the build-time install (still the
# installed 11.0.x), so the frozen-lockfile build is unaffected.
# The image's pnpm matches the "packageManager" pin (see the ARG note above),
# so pnpm does not self-provision on invocation. pm_on_fail=ignore is kept as
# belt-and-suspenders: if the pin and the image ever drift again, pnpm falls
# back to the installed version instead of downloading the pinned build — which
# fails closed with no network and breaks air-gapped boots (ether/etherpad#7911).
# Inherited by the development and production runtime stages, so it also covers
# the updater's pnpm-on-PATH check and ad-hoc `pnpm` in an exec shell.
ENV pnpm_config_pm_on_fail=ignore

# Set these arguments when building the image from behind a proxy
Expand Down Expand Up @@ -202,7 +200,7 @@ ENV ETHERPAD_PRODUCTION=true
# needed at runtime. Overwrite it with a production-only version so
# pnpm install doesn't warn about missing workspace directories.
# Preserve the build-script policy from the source workspace file so
# pnpm 11 doesn't error out with ERR_PNPM_IGNORED_BUILDS for transitive
# pnpm doesn't error out with ERR_PNPM_IGNORED_BUILDS for transitive
# postinstalls (e.g. @scarf/scarf via swagger-ui-dist).
RUN printf 'packages:\n - src\n - bin\nonlyBuiltDependencies:\n - esbuild\nignoredBuiltDependencies:\n - "@scarf/scarf"\nstrictDepBuilds: false\n' > pnpm-workspace.yaml

Expand Down Expand Up @@ -239,7 +237,7 @@ HEALTHCHECK --interval=5s --timeout=3s \
CMD wget -qO- http://127.0.0.1:9001/health | grep -E "pass|ok|up" > /dev/null || exit 1

EXPOSE 9001
# Run node directly instead of via `pnpm run prod`. pnpm 11's
# Run node directly instead of via `pnpm run prod`. pnpm's
# `runDepsStatusCheck` fires before every `pnpm run …` and spuriously
# decides node_modules is out of sync on first start under the named-
# volume layout used by docker-compose (mounting src/plugin_packages).
Expand Down
2 changes: 1 addition & 1 deletion bin/release.ts
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ try {
run('git pull --ff-only', {cwd: '../ether.github.com/'});
console.log('Committing documentation...');
run(`cp -R out/doc/ ../ether.github.com/public/doc/v'${newVersion}'`);
// pnpm 11 refuses `pnpm version` on a dirty tree (the doc copy above
// pnpm refuses `pnpm version` on a dirty tree (the doc copy above
// dirties it) even with --no-git-tag-version, so write the bump with jq —
// same pattern used for the etherpad package.json files at the top of
// this script. The git add+commit below picks up both the bump and the
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,9 @@
},
"engines": {
"node": ">=24.0.0",
"pnpm": ">=11.1.2"
"pnpm": ">=12.0.0"
},
"packageManager": "pnpm@11.10.0",
"packageManager": "pnpm@12.4.2",
"repository": {
"type": "git",
"url": "https://github.com/ether/etherpad.git"
Expand Down
2 changes: 1 addition & 1 deletion packaging/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ Built artefacts land in `./dist/`.

## Building locally

Prereqs: Node 24 (current LTS; matches `engines.node` floor), pnpm 11.1.2+, nfpm.
Prereqs: Node 24 (current LTS; matches `engines.node` floor), pnpm 12+, nfpm.

```sh
pnpm install --frozen-lockfile
Expand Down
158 changes: 158 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion snap/snapcraft.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ parts:
"${CRAFT_PART_INSTALL}/opt/node/bin/npm" install \
--prefix "${CRAFT_PART_INSTALL}/opt/node" -g corepack@latest
corepack enable --install-directory "${CRAFT_PART_INSTALL}/opt/node/bin"
corepack prepare pnpm@11.0.6 --activate
corepack prepare pnpm@12.4.2 --activate

# -- 3. Copy source into install dir and build.
APP_DIR="${CRAFT_PART_INSTALL}/opt/etherpad"
Expand Down
12 changes: 6 additions & 6 deletions src/tests/backend/specs/dockerfilePnpmPin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@
// download fails and pnpm exits non-zero, surfacing as `Failed to get pnpm
// version` and breaking offline boots.
//
// The image deliberately lags the pin (pnpm 11.1.x enforces a minimum-release-
// age policy the frozen-lockfile build can't satisfy), so the guard is not to
// force the versions equal but to neutralise the gap: the Dockerfile must set
// pnpm_config_pm_on_fail=ignore so pnpm uses the installed version instead of
// reaching for the network. This test fails if that guard is dropped while a
// version gap exists.
// The image and the pin are kept in sync, so the guard is belt-and-suspenders
// rather than strictly required. It exists to neutralise any future gap: if the
// image pnpm ever drifts from the "packageManager" pin again, the Dockerfile
// must set pnpm_config_pm_on_fail=ignore so pnpm uses the installed version
// instead of reaching for the network. This test fails if that guard is dropped
// while a version gap exists.

const assert = require('assert').strict;
import fs from 'fs';
Expand Down
Loading