93d33ecb0c
SLICE-08 (devops-engineer): .env.example updated with Proxmox deployment vars (documented, sourced from ~/coreci/.env.secrets per D-026), PRAXIS_CLIENT_DIST for StaticFiles, PRAXIS_SCENARIO. config.json secrets.scopes already extended in SPECIFY (proxmox + voice scopes). SLICE-09 (devops-engineer): 10 bats test files (G-106 fix: 10 not 9) covering all proxmox scripts — 121 tests, 114 pass + 7 skipped (e2e). Mocked curl/pct/ssh; no live cluster needed for unit tests. SLICE-10 (devops-engineer): e2e-deploy.sh — sources secrets from both coreci + praxis .env.secrets, runs full deploy, verifies /health + client HTML serving. REQ-DEPLOY-15 covered. All 6 grill binding decisions addressed: G-101 MUST: GITEA_TOKEN baked into snippet (stage-snippet.sh) G-102 MUST: PRAXIS_DB_PATH env read (db/store.py + db/migrate.py) G-103 FIX: all 16 env vars in injection list (install-service.sh) G-104 FIX: health-check timeout 600s (health-check.sh) G-105 FIX: Dockerfile copy ordering (pyproject before source) G-106 FIX: bats test count = 10 REQ-DEPLOY-12, 14, 15 covered. All 20 REQ-IDs now implemented. ---ci--- project: praxis phase: 1 milestone: v0.2 status: execute slice: 08-10 wave: 4 ---/ci---
116 lines
4.2 KiB
Bash
Executable File
116 lines
4.2 KiB
Bash
Executable File
#!/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
|
|
*"<html"*|*"<!DOCTYPE"*)
|
|
echo "e2e: client served (HTML returned) ✓" >&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" |