test: improve parallels smoke defaults

This commit is contained in:
Peter Steinberger
2026-03-22 21:34:27 +00:00
parent 9e0d298a08
commit f0dc42a9c5
3 changed files with 61 additions and 3 deletions

View File

@@ -20,7 +20,8 @@ Use this skill for Parallels guest workflows and smoke interpretation. Do not lo
## macOS flow ## macOS flow
- Preferred entrypoint: `pnpm test:parallels:macos` - Preferred entrypoint: `pnpm test:parallels:macos`
- Target the snapshot closest to `macOS 26.3.1 fresh`. - Default to the snapshot closest to `macOS 26.3.1 latest`.
- On Peter's Tahoe VM, `fresh-latest-march-2026` can hang in `prlctl snapshot-switch`; if restore times out there, rerun with `--snapshot-hint 'macOS 26.3.1 latest'` before blaming auth or the harness.
- `prlctl exec` is fine for deterministic repo commands, but use the guest Terminal or `prlctl enter` when installer parity or shell-sensitive behavior matters. - `prlctl exec` is fine for deterministic repo commands, but use the guest Terminal or `prlctl enter` when installer parity or shell-sensitive behavior matters.
- On the fresh Tahoe snapshot, `brew` exists but `node` may be missing from PATH in noninteractive exec. Use `/opt/homebrew/bin/node` when needed. - On the fresh Tahoe snapshot, `brew` exists but `node` may be missing from PATH in noninteractive exec. Use `/opt/homebrew/bin/node` when needed.
- Fresh host-served tgz installs should install as guest root with `HOME=/var/root`, then run onboarding as the desktop user via `prlctl exec --current-user`. - Fresh host-served tgz installs should install as guest root with `HOME=/var/root`, then run onboarding as the desktop user via `prlctl exec --current-user`.
@@ -39,11 +40,13 @@ Use this skill for Parallels guest workflows and smoke interpretation. Do not lo
- Preferred entrypoint: `pnpm test:parallels:linux` - Preferred entrypoint: `pnpm test:parallels:linux`
- Use the snapshot closest to fresh `Ubuntu 24.04.3 ARM64`. - Use the snapshot closest to fresh `Ubuntu 24.04.3 ARM64`.
- If that exact VM is missing on the host, fall back to the closest Ubuntu guest with a fresh poweroff snapshot. On Peter's host today, that is `Ubuntu 25.10`.
- Use plain `prlctl exec`; `--current-user` is not the right transport on this snapshot. - Use plain `prlctl exec`; `--current-user` is not the right transport on this snapshot.
- Fresh snapshots may be missing `curl`, and `apt-get update` can fail on clock skew. Bootstrap with `apt-get -o Acquire::Check-Date=false update` and install `curl ca-certificates`. - Fresh snapshots may be missing `curl`, and `apt-get update` can fail on clock skew. Bootstrap with `apt-get -o Acquire::Check-Date=false update` and install `curl ca-certificates`.
- Fresh `main` tgz smoke still needs the latest-release installer first because the snapshot has no Node or npm before bootstrap. - Fresh `main` tgz smoke still needs the latest-release installer first because the snapshot has no Node or npm before bootstrap.
- This snapshot does not have a usable `systemd --user` session; managed daemon install is unsupported. - This snapshot does not have a usable `systemd --user` session; managed daemon install is unsupported.
- `prlctl exec` reaps detached Linux child processes on this snapshot, so detached background gateway runs are not trustworthy smoke signals. - `prlctl exec` reaps detached Linux child processes on this snapshot, so detached background gateway runs are not trustworthy smoke signals.
- Treat `gateway=skipped-no-detached-linux-gateway` plus `daemon=systemd-user-unavailable` as baseline on that Linux lane, not a regression.
## Discord roundtrip ## Discord roundtrip

View File

@@ -2,6 +2,7 @@
set -euo pipefail set -euo pipefail
VM_NAME="Ubuntu 24.04.3 ARM64" VM_NAME="Ubuntu 24.04.3 ARM64"
VM_NAME_EXPLICIT=0
SNAPSHOT_HINT="fresh" SNAPSHOT_HINT="fresh"
MODE="both" MODE="both"
OPENAI_API_KEY_ENV="OPENAI_API_KEY" OPENAI_API_KEY_ENV="OPENAI_API_KEY"
@@ -78,6 +79,7 @@ Usage: bash scripts/e2e/parallels-linux-smoke.sh [options]
Options: Options:
--vm <name> Parallels VM name. Default: "Ubuntu 24.04.3 ARM64" --vm <name> Parallels VM name. Default: "Ubuntu 24.04.3 ARM64"
Falls back to the closest Ubuntu VM when omitted and unavailable.
--snapshot-hint <name> Snapshot name substring/fuzzy match. Default: "fresh" --snapshot-hint <name> Snapshot name substring/fuzzy match. Default: "fresh"
--mode <fresh|upgrade|both> --mode <fresh|upgrade|both>
--openai-api-key-env <var> Host env var name for OpenAI API key. Default: OPENAI_API_KEY --openai-api-key-env <var> Host env var name for OpenAI API key. Default: OPENAI_API_KEY
@@ -99,6 +101,7 @@ while [[ $# -gt 0 ]]; do
case "$1" in case "$1" in
--vm) --vm)
VM_NAME="$2" VM_NAME="$2"
VM_NAME_EXPLICIT=1
shift 2 shift 2
;; ;;
--snapshot-hint) --snapshot-hint)
@@ -166,6 +169,42 @@ esac
OPENAI_API_KEY_VALUE="${!OPENAI_API_KEY_ENV:-}" OPENAI_API_KEY_VALUE="${!OPENAI_API_KEY_ENV:-}"
[[ -n "$OPENAI_API_KEY_VALUE" ]] || die "$OPENAI_API_KEY_ENV is required" [[ -n "$OPENAI_API_KEY_VALUE" ]] || die "$OPENAI_API_KEY_ENV is required"
resolve_vm_name() {
local json requested explicit
json="$(prlctl list --all --json)"
requested="$VM_NAME"
explicit="$VM_NAME_EXPLICIT"
PRL_VM_JSON="$json" REQUESTED_VM_NAME="$requested" VM_NAME_EXPLICIT="$explicit" python3 - <<'PY'
import difflib
import json
import os
import sys
payload = json.loads(os.environ["PRL_VM_JSON"])
requested = os.environ["REQUESTED_VM_NAME"].strip()
requested_lower = requested.lower()
explicit = os.environ["VM_NAME_EXPLICIT"] == "1"
names = [str(item.get("name", "")).strip() for item in payload if str(item.get("name", "")).strip()]
if requested in names:
print(requested)
raise SystemExit(0)
if explicit:
sys.exit(f"vm not found: {requested}")
ubuntu_names = [name for name in names if "ubuntu" in name.lower()]
if not ubuntu_names:
sys.exit(f"default vm not found and no Ubuntu fallback available: {requested}")
best_name = max(
ubuntu_names,
key=lambda name: difflib.SequenceMatcher(None, requested_lower, name.lower()).ratio(),
)
print(best_name)
PY
}
resolve_snapshot_info() { resolve_snapshot_info() {
local json hint local json hint
json="$(prlctl snapshot-list "$VM_NAME" --json)" json="$(prlctl snapshot-list "$VM_NAME" --json)"
@@ -646,6 +685,12 @@ run_upgrade_lane() {
UPGRADE_AGENT_STATUS="pass" UPGRADE_AGENT_STATUS="pass"
} }
RESOLVED_VM_NAME="$(resolve_vm_name)"
if [[ "$RESOLVED_VM_NAME" != "$VM_NAME" ]]; then
warn "requested VM $VM_NAME not found; using $RESOLVED_VM_NAME"
VM_NAME="$RESOLVED_VM_NAME"
fi
IFS=$'\t' read -r SNAPSHOT_ID SNAPSHOT_STATE SNAPSHOT_NAME <<<"$(resolve_snapshot_info)" IFS=$'\t' read -r SNAPSHOT_ID SNAPSHOT_STATE SNAPSHOT_NAME <<<"$(resolve_snapshot_info)"
[[ -n "$SNAPSHOT_ID" ]] || die "failed to resolve snapshot id" [[ -n "$SNAPSHOT_ID" ]] || die "failed to resolve snapshot id"
[[ -n "$SNAPSHOT_NAME" ]] || SNAPSHOT_NAME="$SNAPSHOT_HINT" [[ -n "$SNAPSHOT_NAME" ]] || SNAPSHOT_NAME="$SNAPSHOT_HINT"

View File

@@ -4,7 +4,7 @@ set -euo pipefail
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
VM_NAME="macOS Tahoe" VM_NAME="macOS Tahoe"
SNAPSHOT_HINT="macOS 26.3.1 fresh" SNAPSHOT_HINT="macOS 26.3.1 latest"
MODE="both" MODE="both"
OPENAI_API_KEY_ENV="OPENAI_API_KEY" OPENAI_API_KEY_ENV="OPENAI_API_KEY"
INSTALL_URL="https://openclaw.ai/install.sh" INSTALL_URL="https://openclaw.ai/install.sh"
@@ -102,7 +102,7 @@ Usage: bash scripts/e2e/parallels-macos-smoke.sh [options]
Options: Options:
--vm <name> Parallels VM name. Default: "macOS Tahoe" --vm <name> Parallels VM name. Default: "macOS Tahoe"
--snapshot-hint <name> Snapshot name substring/fuzzy match. --snapshot-hint <name> Snapshot name substring/fuzzy match.
Default: "macOS 26.3.1 fresh" Default: "macOS 26.3.1 latest"
--mode <fresh|upgrade|both> --mode <fresh|upgrade|both>
fresh = fresh snapshot -> target package/current main tgz -> onboard smoke fresh = fresh snapshot -> target package/current main tgz -> onboard smoke
upgrade = fresh snapshot -> latest release -> target package/current main tgz -> onboard smoke upgrade = fresh snapshot -> latest release -> target package/current main tgz -> onboard smoke
@@ -903,6 +903,13 @@ show_log_excerpt() {
tail -n 80 "$log_path" >&2 || true tail -n 80 "$log_path" >&2 || true
} }
show_restore_timeout_diagnostics() {
warn "restore diagnostics for $VM_NAME"
prlctl status "$VM_NAME" >&2 || true
warn "snapshot list for $VM_NAME"
prlctl snapshot-list "$VM_NAME" >&2 || true
}
phase_run() { phase_run() {
local phase_id="$1" local phase_id="$1"
local timeout_s="$2" local timeout_s="$2"
@@ -938,6 +945,9 @@ phase_run() {
if (( timed_out )); then if (( timed_out )); then
warn "$phase_id timed out after ${timeout_s}s" warn "$phase_id timed out after ${timeout_s}s"
printf 'timeout after %ss\n' "$timeout_s" >>"$log_path" printf 'timeout after %ss\n' "$timeout_s" >>"$log_path"
if [[ "$phase_id" == *.restore-snapshot ]]; then
show_restore_timeout_diagnostics
fi
show_log_excerpt "$log_path" show_log_excerpt "$log_path"
return 124 return 124
fi fi