#!/usr/bin/env bash # test-all-apps.sh — End-to-end integration test for all marketplace apps. # Tests each app through: install → health check → UI access → stop → restart → uninstall. # # Usage: SSH to the server and run: # ./scripts/test-all-apps.sh # # Or run remotely: # ssh archipelago@192.168.1.228 "cd ~/archy && bash scripts/test-all-apps.sh" set -euo pipefail # Configuration RPC_URL="http://localhost:5678/rpc/" HEALTH_URL="http://localhost/health" MAX_WAIT=120 # Max seconds to wait for container healthy COOKIE_FILE=$(mktemp) # Colors RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' NC='\033[0m' # Counters PASS=0 FAIL=0 SKIP=0 RESULTS=() # Apps to test with their docker images declare -A APP_IMAGES=( ["filebrowser"]="docker.io/filebrowser/filebrowser:v2-s6" ) # Apps that need archy-net dependencies (skip if dependency not running) declare -A APP_DEPS=( ["electrs"]="bitcoin-knots" ["mempool"]="bitcoin-knots electrs" ["btcpay"]="bitcoin-knots" ["lnd"]="bitcoin-knots" ) log() { echo -e "${GREEN}[TEST]${NC} $*"; } warn() { echo -e "${YELLOW}[WARN]${NC} $*"; } fail() { echo -e "${RED}[FAIL]${NC} $*"; } # Authenticate and get session cookie authenticate() { log "Authenticating..." local response response=$(curl -s -c "$COOKIE_FILE" -X POST "$RPC_URL" \ -H "Content-Type: application/json" \ -d '{"method":"auth.login","params":{"password":"password123"}}') if echo "$response" | grep -q '"error"'; then # Try to get CSRF token from cookies local csrf csrf=$(grep csrf_token "$COOKIE_FILE" 2>/dev/null | awk '{print $NF}') if [ -z "$csrf" ]; then fail "Authentication failed: $response" exit 1 fi fi log "Authenticated" } # RPC call helper rpc() { local method="$1" local params="${2:-null}" local csrf csrf=$(grep csrf_token "$COOKIE_FILE" 2>/dev/null | awk '{print $NF}' || echo "") curl -s -b "$COOKIE_FILE" -X POST "$RPC_URL" \ -H "Content-Type: application/json" \ -H "X-CSRF-Token: $csrf" \ -d "{\"method\":\"$method\",\"params\":$params}" } # Wait for a container to be running wait_for_container() { local app_id="$1" local timeout="$2" local elapsed=0 while [ "$elapsed" -lt "$timeout" ]; do local status status=$(rpc "container-status" "{\"id\":\"$app_id\"}" 2>/dev/null || echo "") if echo "$status" | grep -qi '"running"'; then return 0 fi # Also check via package list local packages packages=$(rpc "container-list" 2>/dev/null || echo "") if echo "$packages" | grep -qi "\"$app_id\".*running"; then return 0 fi sleep 5 elapsed=$((elapsed + 5)) done return 1 } # Test a single app lifecycle test_app() { local app_id="$1" local docker_image="$2" local result="PASS" echo "" log "==========================================" log "Testing: $app_id" log "==========================================" # Check dependencies if [ -n "${APP_DEPS[$app_id]:-}" ]; then for dep in ${APP_DEPS[$app_id]}; do local dep_status dep_status=$(rpc "container-status" "{\"id\":\"$dep\"}" 2>/dev/null || echo "") if ! echo "$dep_status" | grep -qi '"running"'; then warn "Skipping $app_id — dependency $dep not running" SKIP=$((SKIP + 1)) RESULTS+=("SKIP $app_id (needs $dep)") return fi done fi # Step 1: Install log "[$app_id] Installing..." local install_result install_result=$(rpc "package.install" "{\"id\":\"$app_id\",\"dockerImage\":\"$docker_image\"}" 2>/dev/null || echo "error") if echo "$install_result" | grep -qi '"error"'; then # May already be installed if echo "$install_result" | grep -qi "already exists"; then warn "[$app_id] Already installed, continuing..." else fail "[$app_id] Install failed: $install_result" FAIL=$((FAIL + 1)) RESULTS+=("FAIL $app_id (install failed)") return fi fi # Step 2: Wait for healthy log "[$app_id] Waiting for container to be running (max ${MAX_WAIT}s)..." if ! wait_for_container "$app_id" "$MAX_WAIT"; then fail "[$app_id] Container did not start within ${MAX_WAIT}s" result="FAIL" else log "[$app_id] Container is running" fi # Step 3: Stop log "[$app_id] Stopping..." rpc "package.stop" "{\"id\":\"$app_id\"}" > /dev/null 2>&1 sleep 3 # Step 4: Restart log "[$app_id] Restarting..." rpc "package.start" "{\"id\":\"$app_id\"}" > /dev/null 2>&1 sleep 5 if ! wait_for_container "$app_id" 60; then fail "[$app_id] Container did not restart" result="FAIL" else log "[$app_id] Restart successful" fi # Step 5: Uninstall log "[$app_id] Uninstalling..." rpc "package.uninstall" "{\"id\":\"$app_id\"}" > /dev/null 2>&1 sleep 3 # Verify removed local check check=$(rpc "container-status" "{\"id\":\"$app_id\"}" 2>/dev/null || echo "") if echo "$check" | grep -qi '"running"'; then fail "[$app_id] Container still running after uninstall" result="FAIL" fi if [ "$result" = "PASS" ]; then log "[$app_id] PASSED" PASS=$((PASS + 1)) RESULTS+=("PASS $app_id") else FAIL=$((FAIL + 1)) RESULTS+=("FAIL $app_id") fi } # Main echo "" echo "============================================" echo " Archipelago App Integration Test Suite" echo "============================================" echo "" # Check backend health if ! curl -sf "$HEALTH_URL" > /dev/null 2>&1; then fail "Backend not healthy at $HEALTH_URL" exit 1 fi log "Backend is healthy" authenticate # Test each app for app_id in "${!APP_IMAGES[@]}"; do test_app "$app_id" "${APP_IMAGES[$app_id]}" done # Cleanup rm -f "$COOKIE_FILE" # Summary echo "" echo "============================================" echo " Test Results" echo "============================================" for r in "${RESULTS[@]}"; do case "$r" in PASS*) echo -e " ${GREEN}$r${NC}" ;; FAIL*) echo -e " ${RED}$r${NC}" ;; SKIP*) echo -e " ${YELLOW}$r${NC}" ;; esac done echo "" echo " Passed: $PASS Failed: $FAIL Skipped: $SKIP" echo "============================================" if [ "$FAIL" -gt 0 ]; then exit 1 fi