feat(toolbarSelect): DRY up the toolbar <select>-change boilerplate #30
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
| name: Etherpad Integration | |
| # Boots a real Etherpad against this helper in a matrix of core versions | |
| # and asserts the pad page renders cleanly. Catches interop regressions | |
| # (for example the #7543 CJS/ESM settings.toolbar bug) *before* they | |
| # propagate to every downstream plugin that depends on this helper. | |
| on: | |
| push: | |
| branches: [main] | |
| pull_request: | |
| workflow_dispatch: | |
| permissions: | |
| contents: read | |
| jobs: | |
| smoke: | |
| runs-on: ubuntu-latest | |
| strategy: | |
| # Don't cancel sibling versions if one fails — we want the full | |
| # compatibility picture in the check output, not just the first red. | |
| fail-fast: false | |
| matrix: | |
| etherpad-ref: | |
| # Oldest release we want to stay compatible with (v2.6.1 is the | |
| # last tag as of 2026-04; ships the core CJS/ESM interop bug). | |
| - v2.6.1 | |
| # Current development tip (has the #7421 compat shim). | |
| - develop | |
| name: smoke (etherpad@${{ matrix.etherpad-ref }}) | |
| steps: | |
| - name: Check out this helper | |
| uses: actions/checkout@v6 | |
| with: | |
| path: plugin | |
| - name: Check out Etherpad core (${{ matrix.etherpad-ref }}) | |
| uses: actions/checkout@v6 | |
| with: | |
| repository: ether/etherpad | |
| ref: ${{ matrix.etherpad-ref }} | |
| path: etherpad | |
| - uses: pnpm/action-setup@v6 | |
| name: Install pnpm | |
| with: | |
| version: 10 | |
| run_install: false | |
| - uses: actions/setup-node@v6 | |
| with: | |
| node-version: 25 | |
| cache: pnpm | |
| cache-dependency-path: etherpad/pnpm-lock.yaml | |
| - name: Install Etherpad core dependencies | |
| working-directory: ./etherpad | |
| run: bin/installDeps.sh | |
| - name: Install this helper into Etherpad | |
| working-directory: ./etherpad | |
| run: pnpm run plugins i --path ../../plugin | |
| - name: Install a representative consumer (ep_font_color) | |
| working-directory: ./etherpad | |
| # Exercises the template({skip: () => settings.toolbar…}) path that | |
| # hit #7543. Installing via the public registry against the helper | |
| # we just linked verifies the resolver picks up our copy. | |
| run: pnpm run plugins i ep_font_color | |
| - name: Log which helper version Etherpad will load | |
| working-directory: ./etherpad | |
| # Informational only. Etherpad may resolve the helper either from the | |
| # local path or transitively via a consumer plugin (whichever pnpm | |
| # picks). The actual contract — "a crashing skip() does not take the | |
| # pad down" — is verified by the later pad-load step, not by version | |
| # equality. | |
| run: | | |
| pkg_path=$(find src/plugin_packages -maxdepth 5 -type f -name package.json \ | |
| -path '*ep_plugin_helpers*' 2>/dev/null | head -1) | |
| if [ -z "$pkg_path" ]; then | |
| echo "::warning::could not locate ep_plugin_helpers under src/plugin_packages/; listing tree" | |
| find src/plugin_packages -maxdepth 4 -type d | head -30 | |
| else | |
| echo "helper installed at: $pkg_path" | |
| node -p "'helper version: ' + require('$(pwd)/$pkg_path').version" | |
| fi | |
| - name: Start Etherpad in the background | |
| working-directory: ./etherpad | |
| run: | | |
| nohup pnpm run dev > /tmp/etherpad.log 2>&1 & | |
| echo $! > /tmp/etherpad.pid | |
| - name: Wait for Etherpad to listen on :9001 | |
| run: | | |
| for i in $(seq 1 60); do | |
| if curl -fsS http://localhost:9001/ -o /dev/null; then | |
| echo "Etherpad up after ${i}s" | |
| exit 0 | |
| fi | |
| sleep 1 | |
| done | |
| echo "::error::Etherpad did not start within 60s" | |
| tail -200 /tmp/etherpad.log | |
| exit 1 | |
| - name: Load a pad and assert HTTP 200 | |
| # The #7543 symptom was a 500 from eejs rendering the pad template. | |
| # A 200 on /p/<id> is the simplest proof that the helper's template | |
| # pipeline didn't throw when a consumer plugin is installed. | |
| run: | | |
| status=$(curl -s -o /tmp/pad.html -w '%{http_code}' http://localhost:9001/p/ci-smoke-$(date +%s)) | |
| echo "pad status: $status" | |
| if [ "$status" != "200" ]; then | |
| echo "::error::Pad load returned $status (expected 200)" | |
| echo "--- pad body ---" | |
| cat /tmp/pad.html | |
| echo "--- server log (last 200 lines) ---" | |
| tail -200 /tmp/etherpad.log | |
| exit 1 | |
| fi | |
| - name: Scan server log for uncaught template errors | |
| # On the buggy path Etherpad emits the crash at [ERROR] level from the | |
| # `settings` or `http` logger: | |
| # [ERROR] settings - TypeError: ... Cannot read properties of | |
| # undefined (reading 'indexOf') at Object.skip (ep_font_color) | |
| # The helper's swallowing WARN line looks the same textually but lives | |
| # at [WARN] level, so anchor the pattern to [ERROR] to avoid matching | |
| # our own intentional log entry. | |
| run: | | |
| if grep -E "\[ERROR\].*(Cannot read properties of undefined.*indexOf|TypeError.*eejs)" \ | |
| /tmp/etherpad.log; then | |
| echo "::error::Detected the #7543 crash pattern in server log" | |
| tail -200 /tmp/etherpad.log | |
| exit 1 | |
| fi | |
| echo "no [ERROR]-level template crash pattern in log" | |
| - name: Upload server log on failure | |
| if: failure() | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: etherpad-log-${{ matrix.etherpad-ref }} | |
| path: /tmp/etherpad.log | |
| retention-days: 7 | |
| - name: Stop Etherpad | |
| if: always() | |
| run: | | |
| if [ -f /tmp/etherpad.pid ]; then | |
| kill "$(cat /tmp/etherpad.pid)" 2>/dev/null || true | |
| fi |