Files
2026-07-13 13:20:22 +08:00

213 lines
6.8 KiB
Bash
Executable File

#!/bin/bash
set -e
TARBALL_PATH=$1
if [ -z "$TARBALL_PATH" ]; then
echo "Usage: $0 <tarball-path>"
exit 1
fi
echo "========================================"
echo "Smoke test for web-cli tarball"
echo "========================================"
echo "Tarball: $TARBALL_PATH"
# 1. Extract tarball
echo ""
echo "1. Extracting tarball..."
TEMP_DIR=$(mktemp -d)
tar -xzf "$TARBALL_PATH" -C "$TEMP_DIR"
# 2. Verify directory structure
echo ""
echo "2. Verifying directory structure..."
if [ ! -d "$TEMP_DIR/aionui-web" ]; then
echo "❌ Missing aionui-web directory"
exit 1
fi
cd "$TEMP_DIR/aionui-web"
# New layout (bun compile standalone binary):
# aionui-web/
# ├── aionui-web ← single compiled executable (no bin/, no dist/, no node_modules)
# ├── package.json ← for version lookup
# ├── static/ ← SPA assets
# └── bundled-aioncore/<plat-arch>/...
for dir in static bundled-aioncore; do
if [ ! -d "$dir" ]; then
echo "❌ Missing $dir directory"
exit 1
fi
echo "✓ Found $dir/"
done
if [ ! -f "package.json" ]; then
echo "❌ Missing package.json"
exit 1
fi
echo "✓ Found package.json"
# 3. Check executable
echo ""
echo "3. Checking executable..."
if [ ! -x "aionui-web" ]; then
echo "❌ aionui-web is not executable"
exit 1
fi
echo "✓ aionui-web is executable"
# 4. Test version command
echo ""
echo "4. Testing version command..."
VERSION=$(./aionui-web version)
if [ -z "$VERSION" ]; then
echo "❌ version command returned empty"
exit 1
fi
echo "✓ Version: $VERSION"
# 5. Test backend binary
echo ""
echo "5. Checking backend binary..."
BACKEND_DIR="bundled-aioncore/$(uname -s | tr '[:upper:]' '[:lower:]')-$(uname -m | sed 's/aarch64/arm64/; s/x86_64/x64/')"
BACKEND_BINARY="$BACKEND_DIR/aioncore"
if [ ! -x "$BACKEND_BINARY" ]; then
echo "❌ Backend binary missing or not executable: $BACKEND_BINARY"
exit 1
fi
# aioncore has no --version flag. Read the pinned version from manifest.json
# (which prepareAioncore writes at pack time) and use --help to confirm the
# binary loads successfully on this platform's GLIBC / libstdc++ / etc.
if [ -f "$BACKEND_DIR/manifest.json" ]; then
BACKEND_VERSION=$(grep -o '"version"[[:space:]]*:[[:space:]]*"[^"]*"' "$BACKEND_DIR/manifest.json" | head -1 | sed 's/.*"\([^"]*\)"$/\1/')
echo "✓ Backend version (from manifest): ${BACKEND_VERSION:-unknown}"
fi
if ! "$BACKEND_BINARY" --help > /dev/null 2>&1; then
echo "❌ Backend binary failed to exec (--help returned non-zero)"
"$BACKEND_BINARY" --help 2>&1 | head -5
exit 1
fi
echo "✓ Backend binary loads on this platform"
# 6. HTTP-level smoke: start web-cli, curl the root, check for SPA shell
echo ""
echo "6. Testing HTTP server responds with SPA index..."
HTTP_PORT=25899
DATA_DIR="$(mktemp -d)/aionui-web-data"
# Full-stack start: backend is bundled, so we can also exercise /login below.
# If the bundled backend is missing the CLI falls back to frontend-only mode
# and later login probe is skipped.
./aionui-web start --port "$HTTP_PORT" --data-dir "$DATA_DIR" > /tmp/aionui-web.log 2>&1 &
SERVER_PID=$!
# Wait up to 30s for HTTP to come up. With backend spawned, first start spends
# time on SQLite migrations on slower CI runners.
for i in $(seq 1 30); do
if curl -sf "http://127.0.0.1:${HTTP_PORT}/" > /tmp/aionui-web.html 2>/dev/null; then
break
fi
sleep 1
done
if [ ! -s /tmp/aionui-web.html ]; then
kill "$SERVER_PID" 2>/dev/null || true
wait "$SERVER_PID" 2>/dev/null || true
echo "❌ HTTP probe failed — no response body. Server log:"
cat /tmp/aionui-web.log
exit 1
fi
# Look for the SPA shell signature — <html + <div id="root" or similar marker
if grep -q '<html' /tmp/aionui-web.html && grep -qE '<(div id="root"|script)' /tmp/aionui-web.html; then
echo "✓ HTTP root returns SPA index ($(wc -c < /tmp/aionui-web.html) bytes)"
else
kill "$SERVER_PID" 2>/dev/null || true
wait "$SERVER_PID" 2>/dev/null || true
echo "❌ HTTP root response does not look like SPA index:"
head -20 /tmp/aionui-web.html
echo "---server log---"
cat /tmp/aionui-web.log
exit 1
fi
# 7. Auth-setup smoke: verify stdout announces a generated admin password on
# first launch, then POST it to /login and check for success + session cookie.
# Skip when the bundled backend was unavailable — there's no /login to call.
echo ""
echo "7. Testing first-launch admin password seeding + login..."
if grep -q 'Backend binary not found' /tmp/aionui-web.log; then
echo "⚠️ frontend-only mode detected (no bundled backend) — skipping login probe"
kill "$SERVER_PID" 2>/dev/null || true
wait "$SERVER_PID" 2>/dev/null || true
else
# Wait up to 20s for the "Generated initial admin password" line — the backend
# needs to finish migrations before /api/auth/status replies.
PASSWORD=""
for i in $(seq 1 20); do
PASSWORD=$(grep -oE 'Generated initial admin password: [^ ]+' /tmp/aionui-web.log | head -1 | sed 's/^Generated initial admin password: //')
if [ -n "$PASSWORD" ]; then
break
fi
sleep 1
done
if [ -z "$PASSWORD" ]; then
kill "$SERVER_PID" 2>/dev/null || true
wait "$SERVER_PID" 2>/dev/null || true
echo "❌ Never saw 'Generated initial admin password: ...' in stdout."
echo "---server log---"
cat /tmp/aionui-web.log
exit 1
fi
echo "✓ Captured initial admin password from stdout"
# POST /login — static server proxies to backend. Expect 200, success:true,
# and at least one Set-Cookie header containing a session cookie.
LOGIN_BODY=$(printf '{"username":"admin","password":"%s","remember":false}' "$PASSWORD")
LOGIN_RESP_HEADERS=$(mktemp)
LOGIN_RESP_BODY=$(mktemp)
HTTP_CODE=$(curl -sS -o "$LOGIN_RESP_BODY" -D "$LOGIN_RESP_HEADERS" -w '%{http_code}' \
-X POST "http://127.0.0.1:${HTTP_PORT}/login" \
-H 'Content-Type: application/json' \
--data "$LOGIN_BODY" || echo "000")
# Stop the server before asserting so we don't leak a process on failure.
kill "$SERVER_PID" 2>/dev/null || true
wait "$SERVER_PID" 2>/dev/null || true
if [ "$HTTP_CODE" != "200" ]; then
echo "❌ /login returned HTTP $HTTP_CODE"
echo "---headers---"
cat "$LOGIN_RESP_HEADERS"
echo "---body---"
cat "$LOGIN_RESP_BODY"
echo "---server log---"
cat /tmp/aionui-web.log
exit 1
fi
if ! grep -q '"success":[[:space:]]*true' "$LOGIN_RESP_BODY"; then
echo "❌ /login returned 200 but body had no success:true"
cat "$LOGIN_RESP_BODY"
exit 1
fi
if ! grep -iq '^set-cookie:' "$LOGIN_RESP_HEADERS"; then
echo "❌ /login returned success but no Set-Cookie header"
cat "$LOGIN_RESP_HEADERS"
exit 1
fi
echo "✓ Login with printed password succeeded (HTTP 200 + Set-Cookie present)"
fi
# Cleanup
cd -
rm -rf "$TEMP_DIR"
echo ""
echo "========================================"
echo "✅ Smoke test passed!"
echo "========================================"