#!/usr/bin/env bash set -euo pipefail ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" cd "$ROOT" export E2E_BACKEND_PORT="${E2E_BACKEND_PORT:-18079}" export MESHCHAT_NO_HTTPS=1 # E2E exercises /api/v1/self-test (subprocess + bots). Keep Landlock off so # uv-managed interpreters and temp paths are not a sandbox variable. export MESHCHAT_LANDLOCK=0 BACKEND_PORT="$E2E_BACKEND_PORT" VITE_HOST="${E2E_VITE_HOST:-127.0.0.1}" VITE_PORT="${E2E_VITE_PORT:-5173}" TMPDIR="$(mktemp -d -t meshchat-e2e-XXXXXX)" export MESHCHAT_LOG_DIR="$TMPDIR/logs" mkdir -p "$MESHCHAT_LOG_DIR" cleanup() { if [[ -n "${BACK_PID:-}" ]] && kill -0 "$BACK_PID" 2>/dev/null; then kill "$BACK_PID" 2>/dev/null || true wait "$BACK_PID" 2>/dev/null || true fi rm -rf "$TMPDIR" } trap cleanup EXIT INT TERM echo "E2E: starting MeshChat backend on 127.0.0.1:${BACKEND_PORT} (isolated storage under ${TMPDIR})" uv run python -m meshchatx.meshchat \ --headless \ --no-https \ --host 127.0.0.1 \ --port "${BACKEND_PORT}" \ --storage-dir "$TMPDIR/storage" \ --reticulum-config-dir "$TMPDIR/rns" \ & BACK_PID=$! echo "E2E: waiting for /api/v1/status network_ready..." ready=0 for i in $(seq 1 240); do if ! kill -0 "$BACK_PID" 2>/dev/null; then echo "E2E: backend process exited before becoming ready" exit 1 fi if body="$(curl -sf "http://127.0.0.1:${BACKEND_PORT}/api/v1/status" 2>/dev/null)"; then if printf '%s' "$body" | python3 -c 'import json,sys; d=json.load(sys.stdin); sys.exit(0 if d.get("status")=="ok" or d.get("network_ready") else 1)'; then ready=1 echo "E2E: backend ready after ${i}s" break fi fi sleep 1 done if [[ "$ready" -ne 1 ]]; then echo "E2E: backend did not respond on :${BACKEND_PORT} within 240s" exit 1 fi echo "E2E: starting Vite on ${VITE_HOST}:${VITE_PORT}" # Vue DevTools overlay intercepts clicks and is not part of the product UI. export MESHCHAT_VUE_DEVTOOLS=0 pnpm exec vite --host "${VITE_HOST}" --port "${VITE_PORT}" & VITE_PID=$! wait "$VITE_PID"