#!/usr/bin/env bash set -euo pipefail BASE_URL="${1:-http://localhost:8080}" COOKIE_FILE="$(mktemp)" WORK_DIR="$(mktemp -d)" TOKEN="$(date +%s)${RANDOM}" SKILL_NAME="suite-smoke-member-${TOKEN}" SUITE_SLUG="suite-smoke-${TOKEN}" SKILL_ID="" SKILL_VERSION_ID="" SUITE_ID="" SMOKE_ADMIN_USERNAME="${SMOKE_ADMIN_USERNAME:-}" SMOKE_ADMIN_PASSWORD="${SMOKE_ADMIN_PASSWORD:-}" AUTH_HEADERS=() json_field() { JSON_INPUT="$1" python3 - "$2" <<'PY' import json import os import sys value = json.loads(os.environ["JSON_INPUT"]) for part in sys.argv[1].split("."): value = value[int(part)] if part.isdigit() else value[part] print(json.dumps(value, ensure_ascii=False) if isinstance(value, (dict, list)) else value) PY } assert_code() { local description="$1" local body="$2" local expected="$3" local actual actual="$(json_field "$body" code)" if [[ "$actual" != "$expected" ]]; then echo "FAIL: $description (expected code $expected, got $actual)" exit 1 fi echo "PASS: $description" } assert_suite_availability() { local description="$1" local expected_available="$2" local expected_reason="${3:-}" local response response="$(curl -sS -b "$COOKIE_FILE" -c "$COOKIE_FILE" \ "${AUTH_HEADERS[@]}" \ "$BASE_URL/api/web/suites/global/$SUITE_SLUG?version=1.0.0")" assert_code "$description" "$response" 0 JSON_INPUT="$response" EXPECTED_AVAILABLE="$expected_available" EXPECTED_REASON="$expected_reason" \ python3 - <<'PY' import json import os data = json.loads(os.environ["JSON_INPUT"])["data"] expected_available = os.environ["EXPECTED_AVAILABLE"] == "true" expected_reason = os.environ["EXPECTED_REASON"] or None reasons = {member.get("blockingReason") for member in data["members"]} if data["available"] is not expected_available: raise SystemExit(1) if expected_reason is not None and expected_reason not in reasons: raise SystemExit(1) PY echo "PASS: $description has the expected availability" } assert_install_plan_rejected() { local description="$1" local key="$2" local status status="$(curl -sS -o "$WORK_DIR/blocked-plan.json" -w '%{http_code}' \ -b "$COOKIE_FILE" -c "$COOKIE_FILE" "${AUTH_HEADERS[@]}" \ -H "X-XSRF-TOKEN: $CSRF_TOKEN" -H "Idempotency-Key: $key" -X POST \ "$BASE_URL/api/web/suites/global/$SUITE_SLUG/install-plan?version=1.0.0")" if [[ "$status" != "400" ]]; then echo "FAIL: $description should return HTTP 400, got $status" exit 1 fi echo "PASS: $description" } assert_install_plan_available() { local description="$1" local key="$2" local response response="$(curl -sS -b "$COOKIE_FILE" -c "$COOKIE_FILE" \ "${AUTH_HEADERS[@]}" -H "X-XSRF-TOKEN: $CSRF_TOKEN" \ -H "Idempotency-Key: $key" -X POST \ "$BASE_URL/api/web/suites/global/$SUITE_SLUG/install-plan?version=1.0.0")" assert_code "$description" "$response" 0 } cleanup() { if [[ -n "$SUITE_ID" && -n "${CSRF_TOKEN:-}" ]]; then curl -sS -o /dev/null -b "$COOKIE_FILE" -c "$COOKIE_FILE" \ "${AUTH_HEADERS[@]}" -H "X-XSRF-TOKEN: $CSRF_TOKEN" \ -X DELETE "$BASE_URL/api/web/suites/$SUITE_ID" || true fi if [[ -n "$SKILL_ID" && -n "${CSRF_TOKEN:-}" ]]; then curl -sS -o /dev/null -b "$COOKIE_FILE" -c "$COOKIE_FILE" \ "${AUTH_HEADERS[@]}" -H "X-XSRF-TOKEN: $CSRF_TOKEN" \ -X DELETE "$BASE_URL/api/v1/skills/id/$SKILL_ID" || true fi rm -f "$COOKIE_FILE" rm -rf "$WORK_DIR" } trap cleanup EXIT echo "=== Skill Suite Smoke Test ===" echo "Target: $BASE_URL" echo "Suite: @global/$SUITE_SLUG" if [[ -n "$SMOKE_ADMIN_USERNAME" || -n "$SMOKE_ADMIN_PASSWORD" ]]; then if [[ -z "$SMOKE_ADMIN_USERNAME" || -z "$SMOKE_ADMIN_PASSWORD" ]]; then echo "FAIL: SMOKE_ADMIN_USERNAME and SMOKE_ADMIN_PASSWORD must be set together" exit 1 fi curl -sS -c "$COOKIE_FILE" "$BASE_URL/api/v1/auth/me" >/dev/null else AUTH_HEADERS=(-H "X-Mock-User-Id: local-admin") curl -sS -c "$COOKIE_FILE" "${AUTH_HEADERS[@]}" \ "$BASE_URL/api/v1/auth/providers" >/dev/null fi CSRF_TOKEN="$(awk '$6 == "XSRF-TOKEN" { print $7 }' "$COOKIE_FILE" | tail -n 1)" if [[ -z "$CSRF_TOKEN" ]]; then echo "FAIL: could not bootstrap CSRF token" exit 1 fi if [[ -n "$SMOKE_ADMIN_USERNAME" ]]; then LOGIN_PAYLOAD="$(SMOKE_ADMIN_USERNAME="$SMOKE_ADMIN_USERNAME" SMOKE_ADMIN_PASSWORD="$SMOKE_ADMIN_PASSWORD" \ python3 - <<'PY' import json import os print(json.dumps({ "username": os.environ["SMOKE_ADMIN_USERNAME"], "password": os.environ["SMOKE_ADMIN_PASSWORD"], })) PY )" LOGIN_STATUS="$(curl -sS -o "$WORK_DIR/login.json" -w '%{http_code}' \ -b "$COOKIE_FILE" -c "$COOKIE_FILE" -H "X-XSRF-TOKEN: $CSRF_TOKEN" \ -H "Content-Type: application/json" -X POST \ "$BASE_URL/api/v1/auth/local/login" -d "$LOGIN_PAYLOAD")" if [[ "$LOGIN_STATUS" != "200" ]]; then echo "FAIL: local administrator login returned HTTP $LOGIN_STATUS" exit 1 fi CSRF_TOKEN="$(awk '$6 == "XSRF-TOKEN" { print $7 }' "$COOKIE_FILE" | tail -n 1)" echo "PASS: authenticated with the local administrator account" else echo "PASS: authenticated with the local mock administrator" fi cat > "$WORK_DIR/SKILL.md" <