#!/bin/sh # Praxis — E2E deploy verification script. # # Runs the full deploy against a live Proxmox cluster, then verifies # the deployed CT is healthy and serving the praxis client + API. # # This is the integration test that proves the deploy pipeline works # end-to-end. It sources secrets from both ~/coreci/.ciagent/.env.secrets # (proxmox) and .ciagent/.env.secrets (GITEA_TOKEN, DEEPGRAM_API_KEY). # # Usage: ./scripts/proxmox/e2e-deploy.sh [--recreate] # Exit: 0 on success, 1 on failure set -eu SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" PROJ_ROOT="$(cd "${SCRIPT_DIR}/../.." && pwd)" CORECI_SECRETS="${HOME}/coreci/.ciagent/.env.secrets" PRAXIS_SECRETS="${PROJ_ROOT}/.ciagent/.env.secrets" echo "e2e: praxis LXC deploy verification" >&2 # ── Load secrets ─────────────────────────────────────────────────── if [ ! -f "$CORECI_SECRETS" ]; then echo "e2e: ERROR — coreci secrets not found at ${CORECI_SECRETS}" >&2 exit 1 fi if [ ! -f "$PRAXIS_SECRETS" ]; then echo "e2e: ERROR — praxis secrets not found at ${PRAXIS_SECRETS}" >&2 exit 1 fi # Source proxmox secrets from coreci (D-026). set -a . "$CORECI_SECRETS" # Source praxis secrets (GITEA_TOKEN, DEEPGRAM_API_KEY). . "$PRAXIS_SECRETS" set +a # Validate required secrets. for var in PROXMOX_API_URL PROXMOX_API_TOKEN PROXMOX_NODE \ PROXMOX_STORAGE PROXMOX_TEMPLATE_VOLID GITEA_TOKEN; do eval "val=\"\${${var}:-}\"" if [ -z "$val" ]; then echo "e2e: ERROR — ${var} is not set" >&2 exit 1 fi done echo "e2e: secrets loaded (proxmox from coreci, gitea+deepgram from praxis)" >&2 # ── Run the deploy ───────────────────────────────────────────────── echo "e2e: running lxc-deploy.sh $*..." >&2 VMID_OUTPUT=$("${SCRIPT_DIR}/lxc-deploy.sh" "$@" 2>&1) || { echo "e2e: lxc-deploy.sh FAILED" >&2 printf '%s\n' "$VMID_OUTPUT" >&2 exit 1 } VMID=$(printf '%s\n' "$VMID_OUTPUT" | grep '^VMID=' | cut -d= -f2) if [ -z "$VMID" ]; then echo "e2e: ERROR — could not parse VMID from deploy output" >&2 printf '%s\n' "$VMID_OUTPUT" >&2 exit 1 fi echo "e2e: deployed VMID=${VMID}" >&2 # ── Verify the deployed CT ───────────────────────────────────────── echo "e2e: verifying deployed CT..." >&2 # 1. Health-check (already ran inside lxc-deploy.sh, but re-verify) "${SCRIPT_DIR}/health-check.sh" "$VMID" || { echo "e2e: health-check FAILED for VMID ${VMID}" >&2 exit 1 } # 2. Fetch the /health endpoint and check the response shape HEALTH_URL="${PRAXIS_HEALTH_URL:-}" if [ -z "$HEALTH_URL" ]; then # Resolve bridge IP like health-check.sh does ifaces=$(curl -sS --insecure ${PROXMOX_TLS_SKIP_VERIFY:+--insecure} \ -H "Authorization: PVEAPIToken=${PROXMOX_API_TOKEN}" \ "${PROXMOX_API_URL}/nodes/${PROXMOX_NODE}/lxc/${VMID}/interfaces" 2>/dev/null | jq -r '.data') ip=$(printf '%s' "$ifaces" | jq -r '.[] | select(.name != "lo") | (.inet? // .ip? // empty)' 2>/dev/null | grep -v '^$' | head -1) HEALTH_URL="http://${ip}:8789/health" fi echo "e2e: polling ${HEALTH_URL}..." >&2 HEALTH_RESP=$(curl -fsS --connect-timeout 5 "$HEALTH_URL" 2>&1) || { echo "e2e: /health endpoint unreachable at ${HEALTH_URL}" >&2 exit 1 } STATUS=$(printf '%s' "$HEALTH_RESP" | jq -r '.status' 2>/dev/null) if [ "$STATUS" != "ok" ]; then echo "e2e: /health status is '${STATUS}' (expected 'ok')" >&2 exit 1 fi echo "e2e: /health returned status=ok ✓" >&2 # 3. Verify the client is served (GET / should return HTML) CLIENT_URL="${HEALTH_URL%/health}/" CLIENT_RESP=$(curl -fsS --connect-timeout 5 "$CLIENT_URL" 2>&1) || { echo "e2e: client endpoint unreachable at ${CLIENT_URL}" >&2 exit 1 } case "$CLIENT_RESP" in *"&2 ;; *) echo "e2e: client endpoint did not return HTML" >&2 exit 1 ;; esac echo "e2e: ALL CHECKS PASSED — praxis deployed and serving on VMID ${VMID}" >&2 printf 'VMID=%s\nHEALTH_URL=%s\n' "$VMID" "$HEALTH_URL"