open-standards/wai/quickstart/test/clean-machine.sh
Transaction Science 783689c6be The release's macOS leg has node on its PATH, each quickstart runs every binary, and the release check reads commands
The aarch64 leg ran npm with only cargo added to launchd's PATH, which omits node. Both clean-machine
scripts said every binary runs and only looked for wai-pack and wai-remote-host: each now runs alone
and says its usage. check-wai-release-quickstart.py read a step's lines for the script's path, so an
echo of the path or a `|| true` after it passed; it now requires the script as the line's command,
the step's exit status to be the script's, and the Windows throw after it.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-07 10:56:00 -05:00

90 lines
4.8 KiB
Shell
Executable file

#!/usr/bin/env bash
# The quickstart as a new user runs it, from the archive alone, timed step by step:
#
# bash wai/quickstart/test/clean-machine.sh <archive.tar.gz> [--browser]
#
# A machine with nothing of WAI on it: a fresh HOME and working directory, a PATH of the system's
# own directories, no cargo and no repository. The steps are the quickstart's:
# 1. check the archive against its .sha256 beside it, and unpack it;
# 2. the archive holds what `wai dev` and the quickstart name: bin/ with wai, wai-relay,
# wai-room, wai-ingest, wai-remote-host, wai-pack and wai-quantum, each of which runs (the
# last four here, the first three in the steps below), and share/wai/web/ and
# share/wai/studio/ (Studio's page and its core);
# 3. wai hello; 4. wai verify; 5. wai create my-room --template video-room;
# 6. wai dev --check in the project: the relay, the room service, the page and WAI Studio at
# /_wai/ on one origin, each checked through it;
# 7. with --browser (BROWSER_BIN and PLAYWRIGHT_HOST set): the project's page joined in two
# browser pages, each decoding the other (the video-room example's test).
# It prints each step's time, the total, and a JSON line; it exits non-zero when a step fails,
# naming it. Downloading the archive is not timed: the archive is given. Its PowerShell twin,
# clean-machine.ps1, runs the same steps from the Windows archive.
set -uo pipefail
[ $# -ge 1 ] || { sed -n '2,20p' "$0"; exit 2; }
ARCHIVE=$(cd "$(dirname "$1")" && pwd)/$(basename "$1")
BROWSER=0; [ "${2:-}" = --browser ] && BROWSER=1
HERE=$(cd "$(dirname "$0")" && pwd)
ROOT=$(mktemp -d)
export HOME="$ROOT/home" TMPDIR="$ROOT/tmp"
mkdir -p "$HOME" "$TMPDIR" "$ROOT/work"
export PATH=/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
[ "$(uname -s)" = Darwin ] && [ "$BROWSER" = 1 ] && export PATH="/opt/homebrew/bin:$PATH" # node, for the browser step alone
cd "$ROOT/work"
now() { python3 -c 'import time; print(time.monotonic())'; }
T0=$(now)
steps=() failed=""
step() { # <name> <command...>
local name="$1"; shift
local s; s=$(now)
if "$@" > "$ROOT/$name.log" 2>&1; then
steps+=("$name $(python3 -c "print(round($(now) - $s, 2))")")
else
steps+=("$name FAILED")
failed="$name"
echo "FAIL $name:"; tail -15 "$ROOT/$name.log"
fi
}
unpack() {
local want; want=$(cut -d' ' -f1 "$ARCHIVE.sha256")
local got; got=$( (command -v sha256sum > /dev/null && sha256sum "$ARCHIVE" || shasum -a 256 "$ARCHIVE") | cut -d' ' -f1)
[ "$got" = "$want" ] || { echo "SHA-256 $got, not $want"; return 1; }
tar -xzf "$ARCHIVE"
}
step unpack unpack
BIN=$(ls -d "$ROOT"/work/wai-*/bin 2>/dev/null | head -1)
export PATH="$BIN:$PATH"
says_usage() { # <program> <its exit status>: run alone, it says how it is run
local s=0; "$1" > /dev/null 2> "$ROOT/$1.err" || s=$?
[ "$s" = "$2" ] && grep -q usage "$ROOT/$1.err" && grep -q "$1 " "$ROOT/$1.err"
}
contents() {
local b missing=""
for b in wai wai-relay wai-room wai-ingest wai-remote-host wai-pack wai-quantum; do
[ -x "$BIN/$b" ] || missing="$missing bin/$b"
done
for f in share/wai/web/room/index.html share/wai/studio/index.html share/wai/studio/pkg/wai_studio_core_bg.wasm; do
[ -f "$BIN/../$f" ] || missing="$missing $f"
done
[ -z "$missing" ] || { echo "the archive lacks:$missing"; return 1; }
wai-quantum --version || return 1
# wai-ingest and wai-pack alone say how they are run and exit 2; wai-remote-host, 1.
says_usage wai-ingest 2 || return 1
says_usage wai-pack 2 || return 1
says_usage wai-remote-host 1
}
[ -z "$failed" ] && step contents contents
[ -z "$failed" ] && step hello wai hello
[ -z "$failed" ] && step verify wai verify wai-hello
[ -z "$failed" ] && step create wai create my-room --template video-room
# Every piece held, Studio among them: the archive's share/wai/studio, found beside wai.
[ -z "$failed" ] && step dev-check bash -c 'cd my-room && { wai dev --check --port 0 > ../dev-check.out; s=$?; cat ../dev-check.out; [ "$s" = 0 ] && grep -q "ok WAI Studio at /_wai/" ../dev-check.out; }'
if [ -z "$failed" ] && [ "$BROWSER" = 1 ]; then
step two-tabs env WAI_BIN="$BIN/wai" node "$HERE/../../examples/video-room/test/video-room.test.mjs"
fi
TOTAL=$(python3 -c "print(round($(now) - $T0, 2))")
echo "the quickstart from $(basename "$ARCHIVE") on $(uname -sm), a fresh HOME and directory:"
for s in "${steps[@]}"; do set -- $s; if [ "$2" = FAILED ]; then printf ' %-10s FAILED\n' "$1"; else printf ' %-10s %s s\n' "$1" "$2"; fi; done
grep -h 'checks held' "$ROOT/dev-check.log" 2>/dev/null | sed 's/^/ /'
echo " total $TOTAL s${failed:+ (stopped at $failed)}"
python3 -c 'import json,sys; s=sys.argv[3:]; print(json.dumps({"archive": sys.argv[1], "total_s": float(sys.argv[2]), "steps": dict((x.split()[0], x.split()[1]) for x in s), "ok": all("FAILED" not in x for x in s)}))' "$(basename "$ARCHIVE")" "$TOTAL" "${steps[@]}"
rm -rf "$ROOT"
[ -z "$failed" ]