ci(downstream): robust per-client error handling in run-clients.sh (#7927)

* ci(downstream): robust per-client error handling in run-clients.sh (Qodo)

- Move clone/fetch/checkout inside the per-client guarded block with explicit
  '|| exit 1' on every step. set -e is suspended inside a subshell used as an
  '||' operand, so relying on it silently swallowed clone/checkout failures
  (and continued from the wrong cwd); explicit guards make one client's failure
  a per-client fail=1 while the loop continues, and the run exits non-zero.
- Stop suppressing fetch errors; fetch only when the pinned commit isn't already
  reachable, and surface the real error.
- Run manifest commands via 'bash -c' instead of 'eval' (trusted in-repo
  allowlist; avoids double-parsing / leaking into this script's shell).

Verified: two bogus clients -> both reported, loop continues, exit 1; happy
path (cli, no server) -> vectors pass, smoke skips, exit 0.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* ci(downstream): pin clients to their merged-commit SHAs

The three client Phase-2 PRs merged; bump each manifest ref from its
pre-merge PR-branch tip (now deleted / unfetchable) to its squash-merge
commit on main:
  etherpad-pad        -> 91620c6 (ether/pad#1)
  etherpad-cli-client -> ebc516e (ether/etherpad-cli-client#136)
  etherpad-desktop    -> ab83da6 (ether/etherpad-desktop#78)

Verified each merged main carries the test entry points
(vectors.rs/smoke.rs; test:vectors/test:smoke scripts).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* ci(downstream): run manifest commands under bash strict mode (Qodo)

bash -c spawns a fresh shell without -e/-u/-o pipefail, so a pipeline-stage
failure inside a client's vectorTest/smokeCmd could be masked. Use
'bash -euo pipefail -c' so those failures surface as a non-zero exit.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
John McLear 2026-06-09 14:31:05 +01:00 committed by GitHub
parent e56a33efd0
commit b420cf4850
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 27 additions and 15 deletions

View file

@ -2,7 +2,7 @@
{
"name": "etherpad-pad",
"repo": "https://github.com/ether/pad.git",
"ref": "ada8cafd33b4ab31206226b4c3db80b2aa00125a",
"ref": "91620c67c49536bb77e90b39f298ea70ae93c4a0",
"kind": "rust",
"enabled": true,
"vectorTest": "cargo test --test vectors",
@ -11,7 +11,7 @@
{
"name": "etherpad-cli-client",
"repo": "https://github.com/ether/etherpad-cli-client.git",
"ref": "e4b4643c7185c2059375c430e07ca2e65d01999a",
"ref": "ebc516ef1a4e7a0c97ccd7a3f2db65e99f8e177c",
"kind": "node",
"enabled": true,
"vectorTest": "pnpm run test:vectors",
@ -20,7 +20,7 @@
{
"name": "etherpad-desktop",
"repo": "https://github.com/ether/etherpad-desktop.git",
"ref": "9e02fd06b2be3f0eeb91d636b7bddc547210399d",
"ref": "ab83da645b8683afbbc203e4a3fa6f3622a55709",
"kind": "desktop",
"enabled": true,
"vectorTest": "pnpm run test:vectors",

View file

@ -46,28 +46,40 @@ 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"
# Everything — clone, checkout, AND the tests — runs inside one guarded
# subshell so a single client's failure becomes a per-client failure (fail=1)
# and the loop continues to the rest. NOTE: `set -e` is suspended inside a
# subshell used as an `||` operand, so every step is guarded with an explicit
# `|| exit 1` rather than relying on `set -e`. The manifest commands are a
# trusted in-repo allowlist; running them via `bash -euo pipefail -c` (not
# `eval`) keeps them out of this script's own shell and applies strict mode
# (pipeline-stage failures surface) inside the child.
(
cd "$dir"
git clone --quiet "$repo" "$dir" || exit 1
# A default clone has all branch heads; fetch the pinned commit only if it
# is not already reachable (e.g. a non-branch-tip SHA). Fetch errors are
# NOT suppressed so the real cause surfaces instead of a vague checkout fail.
if ! git -C "$dir" cat-file -e "${ref}^{commit}" 2>/dev/null; then
git -C "$dir" fetch --quiet origin "$ref" || exit 1
fi
git -C "$dir" checkout --quiet "$ref" || exit 1
cd "$dir" || exit 1
case "$kind" in
rust)
eval "$vectorTest"
eval "$smokeCmd"
bash -euo pipefail -c "$vectorTest" || exit 1
bash -euo pipefail -c "$smokeCmd" || exit 1
;;
node|desktop)
pnpm install
eval "$vectorTest"
eval "$smokeCmd"
pnpm install || exit 1
bash -euo pipefail -c "$vectorTest" || exit 1
bash -euo pipefail -c "$smokeCmd" || exit 1
;;
*)
echo "::error::unknown client kind: $kind"; exit 1
;;
esac
) || { echo "::error::downstream client '$name' failed"; fail=1; }
) || { echo "::error::downstream client '$name' failed (clone/checkout/test)"; fail=1; }
echo "::endgroup::"
done < "$WORK/clients.tsv"