diff --git a/.github/workflows/downstream-smoke.yml b/.github/workflows/downstream-smoke.yml index a3049d0c17f..c565a22c592 100644 --- a/.github/workflows/downstream-smoke.yml +++ b/.github/workflows/downstream-smoke.yml @@ -88,19 +88,16 @@ jobs: - name: Generate canonical wire-vectors run: cd src && pnpm run vectors:gen + # Rust toolchain for the `rust`-kind client (etherpad-pad). Other kinds + # use the node+pnpm already set up above. + - name: Install Rust toolchain + uses: dtolnay/rust-toolchain@stable + - name: Run enabled downstream clients - run: | - ENABLED=$(node -e 'const c=require("./src/tests/downstream/clients.json").filter(x=>x.enabled); process.stdout.write(JSON.stringify(c))') - if [ "$ENABLED" = "[]" ]; then - echo "No downstream clients enabled yet (Phase 1 harness only). Skipping." - exit 0 - fi - # Phase 2 implements per-`kind` clone @ pinned ref + toolchain setup + - # vector injection (cp src/tests/fixtures/wire-vectors.json into the - # client) + `vectorTest` + `smokeCmd` against http://localhost:9003, - # iterating the entries in $ENABLED. Until a client is enabled this is - # a no-op so the harness lands green on its own. - echo "$ENABLED" + env: + SMOKE_URL: http://localhost:9003 + SMOKE_APIKEY: ${{ env.APIKEY }} + run: bash src/tests/downstream/run-clients.sh - name: Teardown (by PID, never pkill) if: always() diff --git a/src/tests/downstream/clients.json b/src/tests/downstream/clients.json index 52821dabcf1..82a9c997ae7 100644 --- a/src/tests/downstream/clients.json +++ b/src/tests/downstream/clients.json @@ -2,27 +2,27 @@ { "name": "etherpad-pad", "repo": "https://github.com/ether/pad.git", - "ref": "31176d64ce746d45349e58ee6c0bb043052c6e66", + "ref": "ada8cafd33b4ab31206226b4c3db80b2aa00125a", "kind": "rust", - "enabled": false, + "enabled": true, "vectorTest": "cargo test --test vectors", "smokeCmd": "cargo test --test smoke -- --ignored" }, { "name": "etherpad-cli-client", "repo": "https://github.com/ether/etherpad-cli-client.git", - "ref": "edbe0bb70971e54514ebea672e4ad9b51fc55bff", + "ref": "e4b4643c7185c2059375c430e07ca2e65d01999a", "kind": "node", - "enabled": false, + "enabled": true, "vectorTest": "pnpm run test:vectors", "smokeCmd": "pnpm run test:smoke" }, { "name": "etherpad-desktop", "repo": "https://github.com/ether/etherpad-desktop.git", - "ref": "ad273c119f1926a8390c9908fc91f62fa2cf740f", + "ref": "9e02fd06b2be3f0eeb91d636b7bddc547210399d", "kind": "desktop", - "enabled": false, + "enabled": true, "vectorTest": "pnpm run test:vectors", "smokeCmd": "pnpm run test:smoke" } diff --git a/src/tests/downstream/run-clients.sh b/src/tests/downstream/run-clients.sh new file mode 100755 index 00000000000..4ffa7e9a51c --- /dev/null +++ b/src/tests/downstream/run-clients.sh @@ -0,0 +1,74 @@ +#!/usr/bin/env bash +# +# Runs each enabled downstream client from clients.json against an already-booted +# Etherpad: clone @ pinned ref, set up its toolchain, point it at core's freshly +# generated wire-vectors fixture, then run the client's vectorTest + smokeCmd. +# +# The fixture is injected via $ETHERPAD_WIRE_VECTORS (absolute) so clients test +# against CURRENT core's serialization, not their vendored snapshot. The smoke +# reaches the server via $ETHERPAD_SMOKE_URL + $ETHERPAD_SMOKE_APIKEY. +# +# Env (all optional except APIKEY): +# SMOKE_URL default http://localhost:9003 +# SMOKE_APIKEY required for the live smoke (clients skip cleanly without it) +# MANIFEST default src/tests/downstream/clients.json (relative to repo root) +# WIRE_VECTORS default /src/tests/fixtures/wire-vectors.json +set -euo pipefail + +REPO_ROOT="$(cd "$(dirname "$0")/../../.." && pwd)" +MANIFEST="${MANIFEST:-$REPO_ROOT/src/tests/downstream/clients.json}" +WIRE_VECTORS="${WIRE_VECTORS:-$REPO_ROOT/src/tests/fixtures/wire-vectors.json}" +SMOKE_URL="${SMOKE_URL:-http://localhost:9003}" +SMOKE_APIKEY="${SMOKE_APIKEY:-}" + +[ -f "$WIRE_VECTORS" ] || { echo "::error::fixture not found: $WIRE_VECTORS"; exit 1; } + +WORK="$(mktemp -d)" +trap 'rm -rf "$WORK"' EXIT + +MANIFEST="$MANIFEST" node -e ' + const c = require(process.env.MANIFEST).filter((x) => x.enabled); + for (const x of c) { + process.stdout.write([x.name, x.repo, x.ref, x.kind, x.vectorTest, x.smokeCmd].join("\t") + "\n"); + } +' > "$WORK/clients.tsv" + +if [ ! -s "$WORK/clients.tsv" ]; then + echo "No downstream clients enabled. Nothing to run." + exit 0 +fi + +export ETHERPAD_WIRE_VECTORS="$WIRE_VECTORS" +export ETHERPAD_SMOKE_URL="$SMOKE_URL" +export ETHERPAD_SMOKE_APIKEY="$SMOKE_APIKEY" + +fail=0 +while IFS=$'\t' read -r name repo ref kind vectorTest smokeCmd; do + echo "::group::$name ($kind) @ ${ref:0:12}" + dir="$WORK/$name" + git clone --quiet "$repo" "$dir" + # Fetch the exact pinned commit (works even when it is not a branch tip). + git -C "$dir" fetch --quiet origin "$ref" 2>/dev/null || true + git -C "$dir" checkout --quiet "$ref" + + ( + cd "$dir" + case "$kind" in + rust) + eval "$vectorTest" + eval "$smokeCmd" + ;; + node|desktop) + pnpm install + eval "$vectorTest" + eval "$smokeCmd" + ;; + *) + echo "::error::unknown client kind: $kind"; exit 1 + ;; + esac + ) || { echo "::error::downstream client '$name' failed"; fail=1; } + echo "::endgroup::" +done < "$WORK/clients.tsv" + +exit "$fail"