From 1d9da3bca0f8816ea93087f155931fd9839b3421 Mon Sep 17 00:00:00 2001 From: ekklesia Date: Wed, 23 Sep 2026 19:38:04 -0500 Subject: [PATCH] test: rehearse the stable rooms' upgrade on every canary, and list Sunday's checks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit update_canary.sh now also validates the exact package it is about to publish as an upgrade from whatever stable names — 0.2.2 today, several releases behind the laptop's canary. A package that upgrades the laptop and breaks the desktops has to fail before it is published. The lab print check runs in the Plasma lab as well as a plain container: its rig lived in /tmp, which is a tmpfs there that docker cp cannot write into, and its inline-PDF server shared a port with another test server. docs/testing.md has the physical checks for 0.2.6.1 — paper through Elmer, the real keyboard's zoom keys, the machine's graphics through --diagnose, sign-out with a real account — before stable moves. Co-Authored-By: Claude Opus 5.5 --- docs/testing.md | 87 ++++++++++++++++++++++++++++++++ tests/test-deployment-support.sh | 3 ++ tools/lab/wonderink-print-check | 27 +++++++--- tools/lab/wonderink-print-rig.py | 2 +- update_canary.sh | 19 +++++++ 5 files changed, 130 insertions(+), 8 deletions(-) diff --git a/docs/testing.md b/docs/testing.md index 2d7a043..b252c49 100644 --- a/docs/testing.md +++ b/docs/testing.md @@ -574,3 +574,90 @@ ifupdown stanza is already gone. **Do not run `--adopt` on it.** - [ ] `nmcli -g 802-11-wireless.hidden connection show "ROGC Classroom"` still reports `yes` - [ ] The laptop still reconnects after a reboot + +## Wonder Ink — 0.2.6.1, before it goes to stable + +Everything below was done in the lab except what a lab cannot do: paper, +a classroom's own graphics, a real keyboard, its network and its screen. +Those are these checks. Stable stays on 0.2.2 until they pass. + +Before starting, on each machine: `dpkg-query -W ekklesia-classroom` +must say `0.2.6.1`. The desktops only get it once stable is moved, so on +a desktop install it by hand for the test: + +``` +curl -fsSL -o c.deb https://updates.riverofglorymn.org/canary/latest.deb +sha256sum c.deb # must match .../canary/manifest.json +sudo apt-get install -y ./c.deb && sudo reboot +``` + +This does **not** move the machine to canary (see provisioning.md): its +next automatic update follows stable again, which is still 0.2.2 — so +after testing, either promote or reinstall 0.2.2 the same way. + +### Little Waders — printing through Elmer + +- [ ] Open Wonder Ink, sign in, open a lesson with a worksheet +- [ ] Click the worksheet; it opens as a tab named after the file, with a + document icon +- [ ] Ctrl+P (or right-click → Print…): the preview shows the worksheet's + own pages, page count right, ‹ › turn them +- [ ] Printer shows **Elmer**, preselected +- [ ] Print → a notification "Sent to the printer — … — Elmer", Wonder Ink + stays open on the lesson +- [ ] **The worksheet comes out of Elmer**, every page, right size, in colour +- [ ] Pages `2`, Copies `2`, Black and white → exactly two grey copies of + page 2 come out +- [ ] Print a normal lesson page the same way; it comes out, Letter +- [ ] Open the preview and press Cancel → nothing prints +- [ ] Print three times in a row → three printouts, no crash +- [ ] `lpstat -W completed -o` shows each job; `journalctl --user -b | grep + "printed '"` shows Wonder Ink's line for each + +### Size and zoom + +- [ ] A lesson in Wonder Ink is the same size as the same page in the + browser on that machine (it was smaller in 0.2.2) +- [ ] **Ctrl and +** (the real keyboard), **Ctrl and −**, **Ctrl and 0** + change it; a "Lesson size" badge appears +- [ ] Open a second tab: it is the same size; the − 100% + and Print + buttons are at the top right +- [ ] Close Wonder Ink and open it again: the size is remembered +- [ ] A worksheet tab's own − / + (in the PDF toolbar) zoom it +- [ ] A lesson video still goes fullscreen and comes back with the tabs + +### Loading, and the machine's graphics + +From the maintenance terminal (Meta+Ctrl+Alt+Shift+K), in the session: + +``` +classroom-wonderink --diagnose +``` + +- [ ] Note the **GPU line**. A driver's name is right. "none … drawing in + software" means QtWebEngine has no GPU on this machine — compare + `chrome://gpu` in the browser; if Chrome has one, that is the cause of + slow lessons and is the next thing to fix +- [ ] Note the sign-in time (the lab: about 2.9 s wired). Much slower here + with a driver named above points at the network +- [ ] `free -m`: Wonder Ink needs about 610 MB plus 115 MB per extra tab + +### Signing out + +- [ ] Sign in, close Wonder Ink, open it again → **signed out**. (Cookies + are session-only and measured so; the site's Local Storage is not + cleared, which is the one way this could fail and has never been + tested with a real account) + +### After a reboot, and the other rooms + +- [ ] Reboot Little Waders: it comes up as the classroom, Wonder Ink opens +- [ ] On one other desktop, 0.2.6.1 installed: the browser, the DVD player + where there is a drive, Parent Call where enabled, sound through the + television, the panel order — all as on 0.2.2 +- [ ] **Presentations is not on the panel** of any desktop + (`grep PRESENTATIONS_ENABLED /etc/ekklesia-classroom/device.conf` + says `false`) + +If anything here fails, leave the desktops on stable 0.2.2 and fix it in +0.2.6.2 on canary. diff --git a/tests/test-deployment-support.sh b/tests/test-deployment-support.sh index 7a62068..6473cf2 100755 --- a/tests/test-deployment-support.sh +++ b/tests/test-deployment-support.sh @@ -245,6 +245,9 @@ check("a spent version is refused before the build", canary.index("release_check_new_version") < canary.index("build-release.sh")) check("and again after the gate", validation < canary.rindex("release_check_new_version") < first_upload) +check("the stable rooms' upgrade is rehearsed on the same file before publishing", + "VALIDATION_CHANNEL=stable" in canary + and canary.index("VALIDATION_CHANNEL=stable") < first_upload) check("the published channel is read back afterwards", canary.index("release_verify_channel canary") > canary.index("release_publish_manifest canary")) # The gate checks convergence, not just that the package installs: an diff --git a/tools/lab/wonderink-print-check b/tools/lab/wonderink-print-check index d163c88..1fe0ad9 100755 --- a/tools/lab/wonderink-print-check +++ b/tools/lab/wonderink-print-check @@ -19,8 +19,16 @@ COMMAND="${WONDERINK:-/usr/local/bin/classroom-wonderink}" lab() { docker exec -i "$NAME" bash -c "$1"; } -docker cp "$ROOT/tools/lab/wonderink-print-rig.py" "$NAME:/tmp/wonderink-print-rig.py" >/dev/null -lab 'chmod a+r /tmp/wonderink-print-rig.py' +# Not /tmp: in the Plasma lab /tmp is a tmpfs, and docker cp writes into +# the layer underneath it, where nothing can see the file. Measured — the +# first run there "failed" every scenario for exactly that reason. +RIG=/opt/wonderink-check/wonderink-print-rig.py +lab 'mkdir -p /opt/wonderink-check' +docker cp "$ROOT/tools/lab/wonderink-print-rig.py" "$NAME:$RIG" >/dev/null +lab "chmod -R a+rX /opt/wonderink-check && test -r $RIG" || { + echo "could not put the rig in the lab" >&2 + exit 1 +} # The church's printer network is fenced off inside the lab. Checked, not # assumed: a lab job must never be able to reach the real Elmer. @@ -52,11 +60,16 @@ lpadmin -p Refusing -E -v file:///dev/null -m "$driver" -D "LAB: refuses jobs" 2 cupsreject Refusing id teacher >/dev/null 2>&1 || useradd -m teacher install -d -o teacher -m 700 /tmp/teacher-rt -# An inline PDF, served the way a site shows one rather than sends it. -mkdir -p /tmp/www -pgrep -f "http.server 8088" >/dev/null || (cd /tmp/www && setsid python3 -m http.server 8088 >/dev/null 2>&1 &) +# An inline PDF, served the way a site shows one rather than sends it. Its +# own port and directory: a lab often has another test server on 8088. +mkdir -p /opt/wonderink-check/www ' || { echo "could not prepare the lab's CUPS" >&2; exit 1; } +# Started detached. A background process started inside a docker exec +# dies with it in the Plasma lab, whose PID 1 is systemd. +lab 'pgrep -f "[h]ttp.server 8089" >/dev/null' || \ + docker exec -d -w /opt/wonderink-check/www "$NAME" python3 -m http.server 8089 + passed=0 failed=0 @@ -76,7 +89,7 @@ run() { before=$(lab 'lpstat -W all -o 2>/dev/null | wc -l') out=$(lab "su teacher -c 'cd /tmp; XDG_RUNTIME_DIR=/tmp/teacher-rt QT_QPA_PLATFORM=offscreen \ QTWEBENGINE_CHROMIUM_FLAGS=\"--no-sandbox --disable-gpu\" \ - timeout 120 python3 /tmp/wonderink-print-rig.py $COMMAND $1 2>&1'; echo \"exit=\$?\"") + timeout 120 python3 $RIG $COMMAND $1 2>&1'; echo \"exit=\$?\"") sleep 3 jobs=$(lab "lpstat -W all -o | tail -n +$((before + 1)) | awk '{print \$1}' | tr '\n' ' '") job_options() { lab "grep -E '\\[Job ${1#*-}\\] argv\\[(4|5)\\]' /var/log/cups/error_log"; } @@ -92,7 +105,7 @@ scenarios=("$@") options bad-range broken cancel page-closes-itself close-window page-prints-again repeat) # The inline scenario needs a PDF to serve; the worksheet scenario writes one. -lab 'test -f /tmp/www/ark.pdf' || { run pdf >/dev/null; lab 'cp "/home/teacher/Downloads/Wonder Ink/Colour the Ark.pdf" /tmp/www/ark.pdf; chmod a+r /tmp/www/ark.pdf'; } +lab 'test -f /opt/wonderink-check/www/ark.pdf' || { run pdf >/dev/null; lab 'cp "/home/teacher/Downloads/Wonder Ink/Colour the Ark.pdf" /opt/wonderink-check/www/ark.pdf; chmod a+r /opt/wonderink-check/www/ark.pdf'; } for scenario in "${scenarios[@]}"; do echo "$scenario" diff --git a/tools/lab/wonderink-print-rig.py b/tools/lab/wonderink-print-rig.py index 1e21a68..376ce0f 100644 --- a/tools/lab/wonderink-print-rig.py +++ b/tools/lab/wonderink-print-rig.py @@ -121,7 +121,7 @@ elif scenario == "pdf-viewer-button": window.open_pdf(worksheet()); view = window.current() QTimer.singleShot(2500, lambda: (actions["web"](view), view.page().printRequested.emit())) elif scenario == "inline": - view = window.open_tab(); view.load(QUrl("http://127.0.0.1:8088/ark.pdf")) + view = window.open_tab(); view.load(QUrl("http://127.0.0.1:8089/ark.pdf")) QTimer.singleShot(4000, lambda: (stamp(f"inline mime={window._mime.get(view)!r} shows_pdf={window._shows_pdf(view)}"), QTimer.singleShot(0, lambda: window.print_view(view)), when(ready, lambda: (stamp(f"worksheet tab opened: tabs={window._tabs.count()} current_is_pdf={window.current() in window._pdf_views}"), press_print()), "inline preview"))) diff --git a/update_canary.sh b/update_canary.sh index 9f6c683..8cb2279 100755 --- a/update_canary.sh +++ b/update_canary.sh @@ -56,6 +56,25 @@ fi "$ROOT/tools/validate-trixie-release.sh" "${validation_args[@]}" +# And the stable rooms' own path, on the same file. Every canary is a +# stable release in waiting, and the desktops are not on the previous +# canary: they are on whatever stable names, which can be several +# releases back (0.2.2 under 0.2.6.1). A package that upgrades the +# laptop and breaks the desktops has to fail here, not on a Sunday. +if [[ -f "$RELEASE_LOCAL/stable/manifest.json" ]]; then + stable_package_name="$(python3 -c \ + 'import json, sys; print(json.load(open(sys.argv[1]))["package"].rsplit("/", 1)[-1])' \ + "$RELEASE_LOCAL/stable/manifest.json")" + stable_package="$RELEASE_LOCAL/packages/$stable_package_name" + + if [[ -f "$stable_package" && "$stable_package" != "${validation_args[1]:-}" ]]; then + echo + echo "Rehearsing the stable rooms' upgrade from $stable_package_name" + VALIDATION_CHANNEL=stable \ + "$ROOT/tools/validate-trixie-release.sh" "$package_path" "$stable_package" + fi +fi + # Checked again after the gate, which takes long enough for somebody else # to have published in the meantime. release_check_new_version "$version"