From 4655ea97aeeacd7ecb19c710ad4450bc92e953da Mon Sep 17 00:00:00 2001
From: Clark Boylan <clark.boylan@gmail.com>
Date: Wed, 9 Apr 2025 14:33:59 -0700
Subject: [PATCH] Update Etherpad to 2.3.0

There is a new Etherpad 2.3.0 release. We update our Dockerfile to build
that release and in the process attempt to resynchronize with the
upstream Dockerfile. The config files don't seem to change in any
meanginful way.

The changelog can be found here:

  https://github.com/ether/etherpad-lite/blob/v2.3.0/CHANGELOG.md

While we are at it we add screenshots of the main landing page and an
etherpad. This should make it easier to quickly check things when making
changes.

Change-Id: Ibfdab811b51626729f8107146b34794db0e9e2ae
---
 docker/etherpad/Dockerfile    | 58 ++++++++++++++++++++++++++---------
 playbooks/test-etherpad.yaml  |  5 +++
 testinfra/test_etherpad.py    | 27 ++++++++++++++++
 zuul.d/system-config-run.yaml |  1 +
 4 files changed, 77 insertions(+), 14 deletions(-)
 create mode 100644 playbooks/test-etherpad.yaml

diff --git a/docker/etherpad/Dockerfile b/docker/etherpad/Dockerfile
index c48817553a..308e5db710 100644
--- a/docker/etherpad/Dockerfile
+++ b/docker/etherpad/Dockerfile
@@ -23,6 +23,7 @@
 # https://github.com/ether/etherpad-lite
 #
 # Author: muxator
+ARG BUILD_ENV=git
 
 # We set defaults here so that we can make use of them in different
 # stages of the multi stage build.
@@ -30,6 +31,8 @@ ARG EP_DIR=/opt/etherpad-lite
 ARG SETTINGS=./settings.json.docker
 ARG ETHERPAD_PLUGINS="ep_headings2"
 
+# Upstream is using nodejs 23 now which is not an LTS.
+# We stick to the latest LTS which is 22.
 FROM node:22-bookworm-slim AS adminBuild
 ARG EP_DIR
 WORKDIR "${EP_DIR}"
@@ -40,9 +43,9 @@ RUN export DEBIAN_FRONTEND=noninteractive; \
     apt-get -qq --no-install-recommends install ca-certificates git && \
     apt-get -qq clean && \
     rm -rf /var/lib/apt/lists/*
-RUN npm install -g pnpm@9.0.4
+RUN npm install -g pnpm@latest
 RUN git clone https://github.com/ether/etherpad-lite ${EP_DIR}
-RUN git checkout v2.2.7
+RUN git checkout v2.3.0
 RUN pnpm install
 RUN pnpm run build:ui
 
@@ -132,7 +135,7 @@ RUN mkdir -p "${EP_DIR}" && chown etherpad:etherpad "${EP_DIR}"
 # https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=863199
 RUN export DEBIAN_FRONTEND=noninteractive; \
     mkdir -p /usr/share/man/man1 && \
-    npm install pnpm@9.0.4 -g  && \
+    npm install pnpm@latest -g  && \
     apt-get -qq update && \
     apt-get -qq dist-upgrade && \
     apt-get -qq --no-install-recommends install \
@@ -140,7 +143,7 @@ RUN export DEBIAN_FRONTEND=noninteractive; \
         curl \
         git \
         ${INSTALL_ABIWORD:+abiword} \
-        ${INSTALL_SOFFICE:+libreoffice} \
+        ${INSTALL_SOFFICE:+libreoffice openjdk-11-jre} \
         && \
     apt-get -qq clean && \
     rm -rf /var/lib/apt/lists/*
@@ -149,26 +152,48 @@ USER etherpad
 
 RUN git clone https://github.com/ether/etherpad-lite ${EP_DIR}
 WORKDIR "${EP_DIR}"
-RUN git checkout v2.2.7
+RUN git checkout v2.3.0
+
+# Upstream differentiates between a build copy and a build git source
+# for building etherpad. We only do build_git.
+FROM build AS build_git
+
+FROM build AS build_copy
+
+
+
+
+FROM build_${BUILD_ENV} AS development
 
-FROM build AS development
 ARG ETHERPAD_PLUGINS
+ARG ETHERPAD_LOCAL_PLUGINS=
+ARG ETHERPAD_LOCAL_PLUGINS_ENV=
+ARG ETHERPAD_GITHUB_PLUGINS=
 
 # This copy is not necessary as we clone and checkout in the build image
 # COPY --chown=etherpad:etherpad ./src/ ./src/
 COPY --chown=etherpad:etherpad --from=adminbuild /opt/etherpad-lite/src/ templates/admin./src/templates/admin
 COPY --chown=etherpad:etherpad --from=adminbuild /opt/etherpad-lite/src/static/oidc ./src/static/oidc
 
+# This copy is not necessary we don't have any local plugins
+# COPY --chown=etherpad:etherpad ./local_plugin[s] ./local_plugins/
+
+RUN bash -c ./bin/installLocalPlugins.sh
+
 RUN bin/installDeps.sh && \
-    if [ ! -z "${ETHERPAD_PLUGINS}" ] || [ ! -z "${ETHERPAD_LOCAL_PLUGINS}" ] || [ ! -z "${ETHERPAD_GITHUB_PLUGINS}" ]; then \
-        pnpm run plugins i ${ETHERPAD_PLUGINS} ${ETHERPAD_LOCAL_PLUGINS:+--path ${ETHERPAD_LOCAL_PLUGINS}} ${ETHERPAD_GITHUB_PLUGINS:+--github ${ETHERPAD_GITHUB_PLUGINS}}; \
-    fi
+  if [ ! -z "${ETHERPAD_PLUGINS}" ] || [ ! -z "${ETHERPAD_GITHUB_PLUGINS}" ]; then \
+      pnpm run plugins i ${ETHERPAD_PLUGINS} ${ETHERPAD_GITHUB_PLUGINS:+--github ${ETHERPAD_GITHUB_PLUGINS}}; \
+  fi
 
 
-FROM build AS production
+FROM build_${BUILD_ENV} AS production
+
 ARG EP_DIR
 ARG SETTINGS
 ARG ETHERPAD_PLUGINS
+ARG ETHERPAD_LOCAL_PLUGINS=
+ARG ETHERPAD_LOCAL_PLUGINS_ENV=
+ARG ETHERPAD_GITHUB_PLUGINS=
 
 ENV NODE_ENV=production
 ENV ETHERPAD_PRODUCTION=true
@@ -178,10 +203,15 @@ ENV ETHERPAD_PRODUCTION=true
 COPY --chown=etherpad:etherpad --from=adminbuild /opt/etherpad-lite/src/templates/admin ./src/templates/admin
 COPY --chown=etherpad:etherpad --from=adminbuild /opt/etherpad-lite/src/static/oidc ./src/static/oidc
 
-RUN bin/installDeps.sh && rm -rf ~/.npm && rm -rf ~/.local && rm -rf ~/.cache && \
-    if [ ! -z "${ETHERPAD_PLUGINS}" ] || [ ! -z "${ETHERPAD_LOCAL_PLUGINS}" ] || [ ! -z "${ETHERPAD_GITHUB_PLUGINS}" ]; then \
-      pnpm run plugins i ${ETHERPAD_PLUGINS} ${ETHERPAD_LOCAL_PLUGINS:+--path ${ETHERPAD_LOCAL_PLUGINS}} ${ETHERPAD_GITHUB_PLUGINS:+--github ${ETHERPAD_GITHUB_PLUGINS}}; \
-    fi
+# This copy is not necessary we don't have any local plugins
+# COPY --chown=etherpad:etherpad ./local_plugin[s] ./local_plugins/
+
+RUN bash -c ./bin/installLocalPlugins.sh
+
+RUN bin/installDeps.sh && \
+  if [ ! -z "${ETHERPAD_PLUGINS}" ] || [ ! -z "${ETHERPAD_GITHUB_PLUGINS}" ]; then \
+      pnpm run plugins i ${ETHERPAD_PLUGINS} ${ETHERPAD_GITHUB_PLUGINS:+--github ${ETHERPAD_GITHUB_PLUGINS}}; \
+  fi
 
 # Copy the configuration file.
 COPY --chown=etherpad:etherpad ${SETTINGS} "${EP_DIR}"/settings.json
diff --git a/playbooks/test-etherpad.yaml b/playbooks/test-etherpad.yaml
new file mode 100644
index 0000000000..b104461f20
--- /dev/null
+++ b/playbooks/test-etherpad.yaml
@@ -0,0 +1,5 @@
+- hosts: "etherpad"
+  tasks:
+    - name: Run selenium container
+      include_role:
+        name: run-selenium
diff --git a/testinfra/test_etherpad.py b/testinfra/test_etherpad.py
index 3feb0b7d94..61820bd674 100644
--- a/testinfra/test_etherpad.py
+++ b/testinfra/test_etherpad.py
@@ -15,6 +15,8 @@
 import json
 import urllib.parse
 
+from util import take_screenshots
+
 testinfra_hosts = ['etherpad99.opendev.org']
 
 
@@ -156,3 +158,28 @@ def test_etherpad_restore_pad(host):
     assert '"message":"ok"' in cmd.stdout
     assert firststr in cmd.stdout
     assert secondstr not in cmd.stdout
+
+def test_etherpad_screenshots(host):
+    # Prepare our test pad for screenshotting
+    teststr = '🖖 Live long and prosper 🖖'
+    urlstr = urllib.parse.quote(teststr)
+
+    token = _get_bearer_token(host)
+
+    cmd = host.run('curl -H "Authorization: Bearer %s" '
+                   '"http://localhost:9001/api/1/createPad?'
+                   'padID=screenshot"' % token)
+    assert '"code":0' in cmd.stdout
+    assert '"message":"ok"' in cmd.stdout
+    cmd = host.run('curl -H "Authorization: Bearer %s" '
+                   '"http://localhost:9001/api/1/setText?'
+                   'padID=screenshot&text=%s"' % (token, urlstr))
+    assert '"code":0' in cmd.stdout
+    assert '"message":"ok"' in cmd.stdout
+    shots = (
+        ('http://localhost:9001', None, 'etherpad-main.png'),
+        ('http://localhost:9001/p/screenshot', None,
+         'etherpad-pad.png'),
+    )
+
+    take_screenshots(host, shots)
diff --git a/zuul.d/system-config-run.yaml b/zuul.d/system-config-run.yaml
index 97b78ccd3e..d36df475cc 100644
--- a/zuul.d/system-config-run.yaml
+++ b/zuul.d/system-config-run.yaml
@@ -636,6 +636,7 @@
       run_playbooks:
         - playbooks/letsencrypt.yaml
         - playbooks/service-etherpad.yaml
+      run_test_playbook: playbooks/test-etherpad.yaml
     files:
       - playbooks/bootstrap-bridge.yaml
       - playbooks/letsencrypt.yaml