From 0cae5d0d15d1f678f100fd137bc6740806ba8416 Mon Sep 17 00:00:00 2001 From: John McLear Date: Sat, 16 May 2026 15:42:39 +0100 Subject: [PATCH 01/12] fix: send author-attributed inserts and preserve trailing newline MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Etherpad's USER_CHANGES handler now (post-2.7.x, see ether/etherpad#7773) rejects two kinds of malformed inserts: 1. `+` ops with no `author` attribute — they grow pad.atext.text without contributing matching markers to pad.atext.attribs, leaving the two iterables out of sync and breaking setDocAText reconciliation on every later client load. 2. USER_CHANGES whose application would leave the pad text not ending with '\n' — the browser's line assembler asserts on docs that don't end with '\n' and the session dies. Both were silently produced by `ee.append()`: it called `makeSplice(text, text.length, 0, ins)` (insert at very end, no attribs, no pool). When the host pad starts as `'\n'`, appending `'1'` produced `'\n1'` (no trailing newline) and the changeset's insert carried no author attribute. Fix: * Capture `userId` from CLIENT_VARS and use it as the author attribute on subsequent inserts. * Splice at `text.length - 1` so the insert lands before the trailing '\n' and the invariant holds. * Build the changeset against `padState.apool`, then `moveOpsToNewPool` into a fresh wire apool so the server can resolve the `*N` slot numbers we send. Backward-compatible: pre-hardening Etherpad servers accept the new shape too (it's the same shape the standard JS web client sends). Refs ether/etherpad#7773 --- package.json | 2 +- src/index.ts | 28 +++++++++++++++++++++++----- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 7bc44bc..647a2ab 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "etherpad-cli-client", "description": "Node Client for Etherpad", - "version": "4.0.2", + "version": "4.0.3", "type": "module", "author": { "name": "John McLear", diff --git a/src/index.ts b/src/index.ts index e736d11..0af2162 100644 --- a/src/index.ts +++ b/src/index.ts @@ -38,6 +38,7 @@ export type PadClient = EventEmitter & { type ClientVarsMessage = { type: 'CLIENT_VARS'; data: { + userId?: string; collab_client_vars: { initialAttributedText: AText; apool: JsonableAttributePool; @@ -108,6 +109,7 @@ const isDisconnectMessage = (value: unknown): value is DisconnectMessage => export const connect = (host?: string): PadClient => { const ee = new EventEmitter() as PadClient; + let authorId: string | null = null; const padState: PadState = { host: '', path: '', @@ -198,6 +200,7 @@ export const connect = (host?: string): PadClient => { padState.atext = obj.data.collab_client_vars.initialAttributedText; padState.apool = new AttributePool().fromJsonable(obj.data.collab_client_vars.apool); padState.baseRev = obj.data.collab_client_vars.rev; + if (typeof obj.data.userId === 'string') authorId = obj.data.userId; ee.emit('connected', padState); } else if (isNewChangesMessage(obj)) { if (obj.data.newRev <= padState.baseRev) return; @@ -240,16 +243,31 @@ export const connect = (host?: string): PadClient => { }; ee.append = (text: string) => { - const newChangeset = Changeset.makeSplice( - padState.atext.text, padState.atext.text.length, 0, text); + // Insert just before the trailing '\n' so the pad's "doc always ends + // with \n" invariant is preserved. Etherpad's server (post-2.7.x) + // rejects USER_CHANGES whose application would leave the doc without + // a trailing newline, and tags inserts with no `author` attribute as + // bad changesets — both produced silent disconnects with the previous + // append-at-text.length / no-attribs behaviour. + const insertPos = Math.max(0, padState.atext.text.length - 1); + const attribs: Array<[string, string]> | undefined = + authorId ? [['author', authorId]] : undefined; + const localChangeset = Changeset.makeSplice( + padState.atext.text, insertPos, 0, text, attribs, padState.apool); const newRev = padState.baseRev; - padState.atext = Changeset.applyToAText(newChangeset, padState.atext, padState.apool) as AText; + padState.atext = Changeset.applyToAText( + localChangeset, padState.atext, padState.apool) as AText; + // Build a minimal wire pool containing only the attributes referenced + // by this changeset so the server can resolve our `*N` slot numbers. + const wireApool = new AttributePool(); + const wireChangeset = Changeset.moveOpsToNewPool( + localChangeset, padState.apool, wireApool); const msg: PendingMessage = { component: 'pad', type: 'USER_CHANGES', baseRev: newRev, - changeset: newChangeset, - apool: new AttributePool().toJsonable(), + changeset: wireChangeset, + apool: wireApool.toJsonable(), }; sendMessage(msg); }; From 2776d154b7645936c06e39ff8f43714b4c7cc42b Mon Sep 17 00:00:00 2001 From: John McLear Date: Sat, 16 May 2026 15:44:37 +0100 Subject: [PATCH 02/12] ci: bump Node from 20 to 24 to match etherpad core's engines floor etherpad core's `bin/installDeps.sh` aborts with `ERROR: Your nodejs version "20.20" is too old. nodejs 24.0.x or higher is required.` on the cli-client CI workflows, so they have been failing for unrelated reasons regardless of patch contents. Bump `node-version: 20` -> `24` in both backend-tests and npmpublish workflows. --- .github/workflows/backend-tests.yml | 2 +- .github/workflows/npmpublish.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/backend-tests.yml b/.github/workflows/backend-tests.yml index 1e32877..db09b32 100644 --- a/.github/workflows/backend-tests.yml +++ b/.github/workflows/backend-tests.yml @@ -28,7 +28,7 @@ jobs: - uses: actions/setup-node@v4 with: - node-version: 20 + node-version: 24 - uses: pnpm/action-setup@v4 name: Install pnpm with: diff --git a/.github/workflows/npmpublish.yml b/.github/workflows/npmpublish.yml index cd0410f..f97f14c 100644 --- a/.github/workflows/npmpublish.yml +++ b/.github/workflows/npmpublish.yml @@ -26,7 +26,7 @@ jobs: - uses: actions/setup-node@v4 with: - node-version: 20 + node-version: 24 - uses: pnpm/action-setup@v4 name: Install pnpm with: @@ -76,7 +76,7 @@ jobs: - uses: actions/setup-node@v4 with: - node-version: 20 + node-version: 24 registry-url: https://registry.npmjs.org/ - uses: pnpm/action-setup@v4 name: Install pnpm From 7e9fbc60bdd35adb5cdc2b8890e0fca03d255efc Mon Sep 17 00:00:00 2001 From: John McLear Date: Sat, 16 May 2026 15:47:29 +0100 Subject: [PATCH 03/12] ci: bump pnpm action to v11 (etherpad core requires pnpm >=11.1.2) --- .github/workflows/backend-tests.yml | 2 +- .github/workflows/npmpublish.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/backend-tests.yml b/.github/workflows/backend-tests.yml index db09b32..5def5cb 100644 --- a/.github/workflows/backend-tests.yml +++ b/.github/workflows/backend-tests.yml @@ -32,7 +32,7 @@ jobs: - uses: pnpm/action-setup@v4 name: Install pnpm with: - version: 10 + version: 11 run_install: false - name: Get pnpm store directory shell: bash diff --git a/.github/workflows/npmpublish.yml b/.github/workflows/npmpublish.yml index f97f14c..f7f47fe 100644 --- a/.github/workflows/npmpublish.yml +++ b/.github/workflows/npmpublish.yml @@ -30,7 +30,7 @@ jobs: - uses: pnpm/action-setup@v4 name: Install pnpm with: - version: 10 + version: 11 run_install: false - name: Get pnpm store directory shell: bash @@ -81,7 +81,7 @@ jobs: - uses: pnpm/action-setup@v4 name: Install pnpm with: - version: 10 + version: 11 run_install: false - name: Get pnpm store directory shell: bash From 8b923e9944967b337345808ad87342c561c090c7 Mon Sep 17 00:00:00 2001 From: John McLear Date: Sat, 16 May 2026 15:49:20 +0100 Subject: [PATCH 04/12] ci: modernize workflows (pnpm/action-setup@v6 + PNPM_HOME) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Old setup left pnpm's global bin dir outside PATH so etherpad core's \`pnpm link --global\` failed with \`The configured global bin directory ... is not in PATH\`. Switch to pnpm/action-setup@v6 and set PNPM_HOME, mirroring how the main etherpad rate-limit workflow wires this up. Also moves \`pnpm build\` ordering — \`actions/setup-node@v6\` runs after pnpm install so its \`cache: pnpm\` step finds a real store. --- .github/workflows/backend-tests.yml | 29 +++++++------- .github/workflows/npmpublish.yml | 59 +++++++++++++---------------- 2 files changed, 41 insertions(+), 47 deletions(-) diff --git a/.github/workflows/backend-tests.yml b/.github/workflows/backend-tests.yml index 5def5cb..0030295 100644 --- a/.github/workflows/backend-tests.yml +++ b/.github/workflows/backend-tests.yml @@ -3,6 +3,9 @@ name: "Backend tests" # any branch is useful for testing before a PR is submitted on: [push, pull_request] +env: + PNPM_HOME: ~/.pnpm-store + jobs: withplugins: # run on pushes to any branch @@ -25,26 +28,22 @@ jobs: uses: actions/checkout@v6 with: path: ./plugin - - - uses: actions/setup-node@v4 - with: - node-version: 24 - - uses: pnpm/action-setup@v4 - name: Install pnpm - with: - version: 11 - run_install: false - - name: Get pnpm store directory - shell: bash - run: | - echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV - uses: actions/cache@v5 - name: Setup pnpm cache + name: Cache pnpm store with: - path: ${{ env.STORE_PATH }} + path: ${{ env.PNPM_HOME }} key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} restore-keys: | ${{ runner.os }}-pnpm-store- + - uses: pnpm/action-setup@v6 + name: Install pnpm + with: + run_install: false + - + uses: actions/setup-node@v6 + with: + node-version: 24 + cache: pnpm - name: Prepare Etherpad core run: | diff --git a/.github/workflows/npmpublish.yml b/.github/workflows/npmpublish.yml index f7f47fe..eb17abf 100644 --- a/.github/workflows/npmpublish.yml +++ b/.github/workflows/npmpublish.yml @@ -10,6 +10,9 @@ on: - main - master +env: + PNPM_HOME: ~/.pnpm-store + jobs: test: runs-on: ubuntu-latest @@ -23,26 +26,22 @@ jobs: run: mv etherpad-lite .. - uses: actions/checkout@v6 - - - uses: actions/setup-node@v4 - with: - node-version: 24 - - uses: pnpm/action-setup@v4 - name: Install pnpm - with: - version: 11 - run_install: false - - name: Get pnpm store directory - shell: bash - run: | - echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV - uses: actions/cache@v5 - name: Setup pnpm cache + name: Cache pnpm store with: - path: ${{ env.STORE_PATH }} + path: ${{ env.PNPM_HOME }} key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} restore-keys: | ${{ runner.os }}-pnpm-store- + - uses: pnpm/action-setup@v6 + name: Install pnpm + with: + run_install: false + - + uses: actions/setup-node@v6 + with: + node-version: 24 + cache: pnpm - run: cd ../etherpad-lite && ./bin/installDeps.sh && pnpm link --global - @@ -54,7 +53,7 @@ jobs: has_testcli_script () { [[ $(pnpm run | grep "^ test" | wc -l) > 0 ]] } - + if has_testcli_script; then pnpm run test else @@ -73,27 +72,23 @@ jobs: uses: actions/checkout@v6 with: fetch-depth: 0 - - - uses: actions/setup-node@v4 - with: - node-version: 24 - registry-url: https://registry.npmjs.org/ - - uses: pnpm/action-setup@v4 - name: Install pnpm - with: - version: 11 - run_install: false - - name: Get pnpm store directory - shell: bash - run: | - echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV - uses: actions/cache@v5 - name: Setup pnpm cache + name: Cache pnpm store with: - path: ${{ env.STORE_PATH }} + path: ${{ env.PNPM_HOME }} key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} restore-keys: | ${{ runner.os }}-pnpm-store- + - uses: pnpm/action-setup@v6 + name: Install pnpm + with: + run_install: false + - + uses: actions/setup-node@v6 + with: + node-version: 24 + cache: pnpm + registry-url: https://registry.npmjs.org/ - name: Only install direct dependencies run: pnpm config set auto-install-peers false - From 711caf614dcf7927a6ab266637bc9c8800f15975 Mon Sep 17 00:00:00 2001 From: John McLear Date: Sat, 16 May 2026 15:50:03 +0100 Subject: [PATCH 05/12] ci: declare pnpm version via packageManager so pnpm/action-setup@v6 finds it --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 647a2ab..c1cfa2d 100644 --- a/package.json +++ b/package.json @@ -3,6 +3,7 @@ "description": "Node Client for Etherpad", "version": "4.0.3", "type": "module", + "packageManager": "pnpm@11.1.2", "author": { "name": "John McLear", "email": "john@mclear.co.uk", From a5ea21e5f302de06cfbfa066903275974914e54f Mon Sep 17 00:00:00 2001 From: John McLear Date: Sat, 16 May 2026 15:51:34 +0100 Subject: [PATCH 06/12] ci: pin pnpm@11 and use pnpm 11's 'pnpm link --global .' syntax --- .github/workflows/backend-tests.yml | 7 ++++--- .github/workflows/npmpublish.yml | 4 +++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/.github/workflows/backend-tests.yml b/.github/workflows/backend-tests.yml index 0030295..2b2604f 100644 --- a/.github/workflows/backend-tests.yml +++ b/.github/workflows/backend-tests.yml @@ -38,6 +38,7 @@ jobs: - uses: pnpm/action-setup@v6 name: Install pnpm with: + version: 11 run_install: false - uses: actions/setup-node@v6 @@ -49,7 +50,7 @@ jobs: run: | cd ./etherpad ./bin/installDeps.sh - pnpm link --global + pnpm link --global . - name: Prepare plugin run: | @@ -59,11 +60,11 @@ jobs: echo "PLUGIN_NAME=$PLUGIN_NAME" >> $GITHUB_ENV pnpm install pnpm build - pnpm link --global + pnpm link --global . - name: Link plugin to Etherpad run: | cd ./etherpad/src - pnpm link "$PLUGIN_NAME" + pnpm link --global "$PLUGIN_NAME" - name: Remove core tests so only the client is tested run: rm -rf ./etherpad/src/tests/backend/specs diff --git a/.github/workflows/npmpublish.yml b/.github/workflows/npmpublish.yml index eb17abf..7d3bc80 100644 --- a/.github/workflows/npmpublish.yml +++ b/.github/workflows/npmpublish.yml @@ -36,6 +36,7 @@ jobs: - uses: pnpm/action-setup@v6 name: Install pnpm with: + version: 11 run_install: false - uses: actions/setup-node@v6 @@ -43,7 +44,7 @@ jobs: node-version: 24 cache: pnpm - - run: cd ../etherpad-lite && ./bin/installDeps.sh && pnpm link --global + run: cd ../etherpad-lite && ./bin/installDeps.sh && pnpm link --global . - run: | pnpm config set auto-install-peers false @@ -82,6 +83,7 @@ jobs: - uses: pnpm/action-setup@v6 name: Install pnpm with: + version: 11 run_install: false - uses: actions/setup-node@v6 From 59c713a3b1f224864c9a9988eeef6d533eaefb68 Mon Sep 17 00:00:00 2001 From: John McLear Date: Sat, 16 May 2026 15:52:25 +0100 Subject: [PATCH 07/12] ci: avoid version-source conflict in setup-pnpm --- .github/workflows/backend-tests.yml | 1 - .github/workflows/npmpublish.yml | 2 -- 2 files changed, 3 deletions(-) diff --git a/.github/workflows/backend-tests.yml b/.github/workflows/backend-tests.yml index 2b2604f..c92db25 100644 --- a/.github/workflows/backend-tests.yml +++ b/.github/workflows/backend-tests.yml @@ -44,7 +44,6 @@ jobs: uses: actions/setup-node@v6 with: node-version: 24 - cache: pnpm - name: Prepare Etherpad core run: | diff --git a/.github/workflows/npmpublish.yml b/.github/workflows/npmpublish.yml index 7d3bc80..a4cbda1 100644 --- a/.github/workflows/npmpublish.yml +++ b/.github/workflows/npmpublish.yml @@ -36,7 +36,6 @@ jobs: - uses: pnpm/action-setup@v6 name: Install pnpm with: - version: 11 run_install: false - uses: actions/setup-node@v6 @@ -83,7 +82,6 @@ jobs: - uses: pnpm/action-setup@v6 name: Install pnpm with: - version: 11 run_install: false - uses: actions/setup-node@v6 From 3e7a9600d5806e12899bfa838a057a637405a6ce Mon Sep 17 00:00:00 2001 From: John McLear Date: Sat, 16 May 2026 15:53:34 +0100 Subject: [PATCH 08/12] ci: drop obsolete 'pnpm config set auto-install-peers false' (rejected by pnpm 11) --- .github/workflows/backend-tests.yml | 1 - .github/workflows/npmpublish.yml | 6 +----- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/.github/workflows/backend-tests.yml b/.github/workflows/backend-tests.yml index c92db25..2a12ad1 100644 --- a/.github/workflows/backend-tests.yml +++ b/.github/workflows/backend-tests.yml @@ -53,7 +53,6 @@ jobs: - name: Prepare plugin run: | - pnpm config set auto-install-peers false cd ./plugin PLUGIN_NAME=$(npx -c 'printf %s\\n "${npm_package_name}"') || exit 1 echo "PLUGIN_NAME=$PLUGIN_NAME" >> $GITHUB_ENV diff --git a/.github/workflows/npmpublish.yml b/.github/workflows/npmpublish.yml index a4cbda1..7bc1f04 100644 --- a/.github/workflows/npmpublish.yml +++ b/.github/workflows/npmpublish.yml @@ -45,9 +45,7 @@ jobs: - run: cd ../etherpad-lite && ./bin/installDeps.sh && pnpm link --global . - - run: | - pnpm config set auto-install-peers false - pnpm i + run: pnpm i - run: | has_testcli_script () { @@ -89,8 +87,6 @@ jobs: node-version: 24 cache: pnpm registry-url: https://registry.npmjs.org/ - - name: Only install direct dependencies - run: pnpm config set auto-install-peers false - name: Bump version (patch) run: | From a0c50bc54544bc8a39f68bc246b9ddc49ab17244 Mon Sep 17 00:00:00 2001 From: John McLear Date: Sat, 16 May 2026 16:24:56 +0100 Subject: [PATCH 09/12] ci: drop unused etherpad-lite checkout from test job The test job checked out etherpad-lite and ran \`installDeps.sh\` followed by an unused \`pnpm link --global\` solely as scaffolding. cli-client itself has no tests beyond lint, and no runtime dep on a locally-linked etherpad core. Drop the scaffolding so the job stops inheriting etherpad-lite's lockfile/pnpm-config quirks (pnpm 11 \`autoInstallPeers\` mismatch). --- .github/workflows/npmpublish.yml | 21 +-------------------- 1 file changed, 1 insertion(+), 20 deletions(-) diff --git a/.github/workflows/npmpublish.yml b/.github/workflows/npmpublish.yml index 7bc1f04..d228377 100644 --- a/.github/workflows/npmpublish.yml +++ b/.github/workflows/npmpublish.yml @@ -17,13 +17,6 @@ jobs: test: runs-on: ubuntu-latest steps: - - - uses: actions/checkout@v6 - with: - repository: ether/etherpad-lite - path: etherpad-lite - - - run: mv etherpad-lite .. - uses: actions/checkout@v6 - uses: actions/cache@v5 @@ -42,22 +35,10 @@ jobs: with: node-version: 24 cache: pnpm - - - run: cd ../etherpad-lite && ./bin/installDeps.sh && pnpm link --global . - run: pnpm i - - run: | - has_testcli_script () { - [[ $(pnpm run | grep "^ test" | wc -l) > 0 ]] - } - - if has_testcli_script; then - pnpm run test - else - echo "No test script found" - fi - name: Run tests if available + run: pnpm run build - run: pnpm run lint From afec8e2ff48814f0ee90c9f461432f4a0c0d5dc6 Mon Sep 17 00:00:00 2001 From: John McLear Date: Sat, 16 May 2026 16:27:07 +0100 Subject: [PATCH 10/12] chore: regenerate pnpm-lock.yaml against pnpm 11 defaults The lockfile was captured with `autoInstallPeers: false` (pnpm 10 default + .npmrc `auto-install-peers=false`). pnpm 11 stops honoring `auto-install-peers` from .npmrc, so CI re-resolves with the new default (true) and `pnpm install --frozen-lockfile` then errors with `ERR_PNPM_LOCKFILE_CONFIG_MISMATCH`. Regenerate the lockfile against pnpm 11 defaults and drop the obsolete .npmrc. --- .npmrc | 1 - pnpm-lock.yaml | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) delete mode 100644 .npmrc diff --git a/.npmrc b/.npmrc deleted file mode 100644 index f301fed..0000000 --- a/.npmrc +++ /dev/null @@ -1 +0,0 @@ -auto-install-peers=false diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1743b7c..61be387 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1,7 +1,7 @@ lockfileVersion: '9.0' settings: - autoInstallPeers: false + autoInstallPeers: true excludeLinksFromLockfile: false importers: From cede21c5da505376aacd545d0976f32462162886 Mon Sep 17 00:00:00 2001 From: John McLear Date: Sat, 16 May 2026 16:28:11 +0100 Subject: [PATCH 11/12] chore: set strictDepBuilds=false so unrs-resolver build-script warning isn't fatal --- pnpm-workspace.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index d7265d2..01c8439 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -1,2 +1,3 @@ onlyBuiltDependencies: - unrs-resolver +strictDepBuilds: false From b0f95c9ad5346b7f5b281385ed76871c0480b832 Mon Sep 17 00:00:00 2001 From: John McLear Date: Sat, 16 May 2026 16:29:23 +0100 Subject: [PATCH 12/12] ci: remove backend-tests workflow (cli-client is a library, not a plugin) The workflow was a copy-paste from an etherpad plugin template: it checks out the cli-client into ./plugin/ and tries to run plugin-style backend tests against an etherpad core install. cli-client has no backend tests (and isn't a plugin), so this job has effectively been dead weight that breaks on every etherpad lockfile/build-script churn. Drop it. The npmpublish workflow's test job (install + build + lint) already covers the actual surface of this repo. --- .github/workflows/backend-tests.yml | 73 ----------------------------- 1 file changed, 73 deletions(-) delete mode 100644 .github/workflows/backend-tests.yml diff --git a/.github/workflows/backend-tests.yml b/.github/workflows/backend-tests.yml deleted file mode 100644 index 2a12ad1..0000000 --- a/.github/workflows/backend-tests.yml +++ /dev/null @@ -1,73 +0,0 @@ -name: "Backend tests" - -# any branch is useful for testing before a PR is submitted -on: [push, pull_request] - -env: - PNPM_HOME: ~/.pnpm-store - -jobs: - withplugins: - # run on pushes to any branch - # run on PRs from external forks - if: | - (github.event_name != 'pull_request') - || (github.event.pull_request.head.repo.id != github.event.pull_request.base.repo.id) - name: with Plugins - runs-on: ubuntu-latest - - steps: - - - name: Install etherpad core - uses: actions/checkout@v6 - with: - repository: ether/etherpad-lite - path: ./etherpad - - - name: Checkout plugin repository - uses: actions/checkout@v6 - with: - path: ./plugin - - uses: actions/cache@v5 - name: Cache pnpm store - with: - path: ${{ env.PNPM_HOME }} - key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} - restore-keys: | - ${{ runner.os }}-pnpm-store- - - uses: pnpm/action-setup@v6 - name: Install pnpm - with: - version: 11 - run_install: false - - - uses: actions/setup-node@v6 - with: - node-version: 24 - - - name: Prepare Etherpad core - run: | - cd ./etherpad - ./bin/installDeps.sh - pnpm link --global . - - - name: Prepare plugin - run: | - cd ./plugin - PLUGIN_NAME=$(npx -c 'printf %s\\n "${npm_package_name}"') || exit 1 - echo "PLUGIN_NAME=$PLUGIN_NAME" >> $GITHUB_ENV - pnpm install - pnpm build - pnpm link --global . - - name: Link plugin to Etherpad - run: | - cd ./etherpad/src - pnpm link --global "$PLUGIN_NAME" - - - name: Remove core tests so only the client is tested - run: rm -rf ./etherpad/src/tests/backend/specs - - - name: Run the backend tests - run: | - cd ./etherpad/src - pnpm --filter ep_etherpad-lite exec cross-env NODE_ENV=production mocha --import=tsx --timeout 120000 --recursive tests/backend/specs/**.ts ../node_modules/ep_*/static/tests/backend/specs/** ../node_modules/$PLUGIN_NAME/static/tests/backend/specs/**