Files
hermes-agent/scripts/launch_capture_probe.sh
ethernet 0f903e14a3 test(install-e2e): hermes-desktop-app-update goes live on the script driver
Playwright must own the spawn (it needs the inspection pipe), but
hermes desktop is not just build+launch - stamp checks, integrity
gates, sandbox fixups, and a constructed child environment. So the
driver intercepts the product's own launch: a sitecustomize.py on
PYTHONPATH (opt-in via HERMES_E2E_CAPTURE_LAUNCH) wraps subprocess.run,
captures argv/cwd/env at the spawn site, and fakes success instead of
spawning; launch-from-spec.mjs then _electron.launch-es exactly that
spec and clicks Settings -> About -> Update now. Completion is product
state, not a Playwright event: the handoff result file or the checkout
reaching the expected sha (source installs write no result file).

Ships with the driver, so it works unchanged on every sampled OLD ref
- no product flag, no pre-flag fallback split. Both launch shapes are
matched (npm exec electron / packaged exe under apps/desktop/release);
npm BUILD calls pass through untouched. Exit 0 without a capture fails
the leg: a version that never reached its launch must not pass.

Probe-the-probe: scripts/launch_capture_probe.sh runs control rows
(no opt-in, non-launch argv) and both treatment shapes - all green
locally. Gate flips on the shared run workflow for linux/macos;
windows adopts the same path with the driver restructuring.
2026-08-12 04:20:56 -04:00

81 lines
3.3 KiB
Bash
Executable File

#!/usr/bin/env bash
# Probe-the-probe for launch-capture/sitecustomize.py, no real install needed.
# Control rows FIRST: without the opt-in env var, and for non-launch argv
# shapes, subprocess.run must behave untouched. Then treatment rows: both
# launch shapes must be captured without spawning.
set -euo pipefail
CAP_DIR="$(cd "$(dirname "$0")" && pwd)/../tests/install/e2e-assets/launch-capture"
WORK="$(mktemp -d)"
trap 'rm -rf "$WORK"' EXIT
run_py() {
# $1: with_var (yes/no); rest: python -c payload
local with_var="$1"; shift
if [ "$with_var" = yes ]; then
PYTHONPATH="$CAP_DIR${PYTHONPATH:+:$PYTHONPATH}" \
HERMES_E2E_CAPTURE_LAUNCH="$WORK/spec.json" python3 "$@"
else
PYTHONPATH="$CAP_DIR${PYTHONPATH:+:$PYTHONPATH}" python3 "$@"
fi
}
fail() { echo "PROBE FAILED: $*" >&2; exit 1; }
echo "--- control 1: no env var -> run() untouched, real spawn happens"
out="$(run_py no -c 'import subprocess; print(subprocess.run(["echo","real-spawn"],capture_output=True,text=True).stdout.strip())')"
[ "$out" = "real-spawn" ] || fail "control 1: expected real-spawn, got '$out'"
[ ! -e "$WORK/spec.json" ] || fail "control 1: spec written without opt-in"
echo "OK"
echo "--- control 2: env var set, NON-launch argv (npm run pack) -> passthrough"
rm -f "$WORK"/spec.json*
out="$(run_py yes -c 'import subprocess; r=subprocess.run(["echo","npm-build-ran"],capture_output=True,text=True); print(r.stdout.strip())')"
[ "$out" = "npm-build-ran" ] || fail "control 2: echo did not run"
# and an actual npm-shaped BUILD argv (argv[0]=npm but no electron token):
run_py yes -c 'import subprocess,sys; r=subprocess.run(["npm","run","pack"],capture_output=True); sys.exit(0)' 2>/dev/null || true
[ ! -e "$WORK/spec.json" ] || fail "control 2: build argv was wrongly captured"
echo "OK"
echo "--- treatment 1: source shape (npm exec -- electron .) captured, not spawned"
rm -f "$WORK"/spec.json*
run_py yes -c '
import subprocess
r = subprocess.run(["npm", "exec", "--", "electron", "."], cwd="/tmp", env={"HERMES_DESKTOP_CWD": "/tmp", "PATH": "/usr/bin"})
assert r.returncode == 0, r
'
[ -e "$WORK/spec.json" ] || fail "treatment 1: no spec written"
[ "$(cat "$WORK/spec.json.captured")" = "source" ] || fail "treatment 1: wrong shape"
python3 - "$WORK/spec.json" <<'EOF'
import json, sys
spec = json.load(open(sys.argv[1]))
assert spec["argv"] == ["npm", "exec", "--", "electron", "."], spec["argv"]
assert spec["cwd"] == "/tmp", spec["cwd"]
assert spec["env"]["HERMES_DESKTOP_CWD"] == "/tmp", "env= kwarg not captured"
assert spec["matchedShape"] == "source"
print("spec contents OK")
EOF
echo "OK"
echo "--- treatment 2: packaged shape captured, not spawned"
rm -f "$WORK"/spec.json*
run_py yes -c '
import subprocess
exe = "/x/apps/desktop/release/linux-unpacked/Hermes"
r = subprocess.run([exe, "--no-sandbox"], cwd="/tmp", env={"PATH": "/usr/bin"})
assert r.returncode == 0, r # a real spawn of this path would ENOENT
'
[ "$(cat "$WORK/spec.json.captured")" = "packaged" ] || fail "treatment 2: wrong shape"
echo "OK"
echo "--- treatment 3: windows-style packaged argv matches too"
rm -f "$WORK"/spec.json*
run_py yes -c '
import subprocess
r = subprocess.run(["C:\\x\\apps\\desktop\\release\\win-unpacked\\Hermes.exe"], env={})
assert r.returncode == 0
'
[ "$(cat "$WORK/spec.json.captured")" = "packaged" ] || fail "treatment 3: wrong shape"
echo "OK"
echo "ALL PROBES PASSED"