All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
- Make postgres and redis provisioning idempotent: return success when already provisioned with credentials stored, allowing cookbook trees to safely include explicit add-db/add-redis steps alongside auto-provisioned project creation - Update tests to reflect new idempotent behavior - Consolidate docs CI into single multi-stage Docker build (remove separate build-docs step; Dockerfile.nginx now builds Slate then serves with nginx) - Delete redundant skeleton docs/Dockerfile (replaced by multi-stage nginx image) - Add watch verb to woodpecker-deployer RBAC (required by kubectl rollout status) - Aeries Daeya cookbook: add public discovery feed (/) + character profiles (/c/:handle), characters.published/handle/tagline fields, dark pink design system, /studio/* routes, verify-public-discovery + verify-otp-endpoint smoke test steps - Fix Input.tsx: remove non-existent --border-hover CSS variable hover effect
173 lines
6.9 KiB
Bash
Executable File
173 lines
6.9 KiB
Bash
Executable File
#!/bin/bash
|
|
set -euo pipefail
|
|
|
|
# Aeries Daeya E2E Test Script
|
|
# Privacy-first avatar social platform: character creation, AI styling from photos,
|
|
# mutation explorer, album management.
|
|
#
|
|
# Usage: ./cookbooks/scripts/aeries-daeya-test.sh <command> <project-name>
|
|
# Commands: run, status, diagnose, teardown
|
|
#
|
|
# Examples:
|
|
# ./cookbooks/scripts/aeries-daeya-test.sh run my-daeya
|
|
# ./cookbooks/scripts/aeries-daeya-test.sh run my-daeya --auto-teardown
|
|
# AUTO_TEARDOWN=true ./cookbooks/scripts/aeries-daeya-test.sh run my-daeya
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
source "$SCRIPT_DIR/common.sh"
|
|
|
|
# Parse --auto-teardown flag from args
|
|
ARGS=("$@")
|
|
for i in "${!ARGS[@]}"; do
|
|
if [[ "${ARGS[$i]}" == "--auto-teardown" ]]; then
|
|
AUTO_TEARDOWN="true"
|
|
unset 'ARGS[$i]'
|
|
fi
|
|
done
|
|
ARGS=("${ARGS[@]}")
|
|
|
|
COMMAND="${ARGS[0]:-}"
|
|
PROJECT_NAME="${ARGS[1]:-}"
|
|
|
|
register_cleanup_trap
|
|
|
|
if [[ -z "$COMMAND" || -z "$PROJECT_NAME" ]]; then
|
|
echo "Usage: $0 <command> <project-name>"
|
|
echo "Commands:"
|
|
echo " run - Deploy full aeries-daeya platform via tree runner"
|
|
echo " status - Check project and component status"
|
|
echo " diagnose - Deep diagnostic of pipeline and site issues"
|
|
echo " teardown - Delete the project and all resources"
|
|
exit 1
|
|
fi
|
|
|
|
run_flow() {
|
|
print_header "Aeries Daeya: Privacy-First Avatar Platform"
|
|
|
|
echo "Running tree: aeries-daeya for project: $PROJECT_NAME"
|
|
echo ""
|
|
echo " Phase 1 — Infrastructure (DB + Redis + service + worker + app)"
|
|
echo " Phase 2 — Avatar & Look Data Model (characters + public discovery endpoints)"
|
|
echo " Phase 3 — AI Generation Pipeline (portrait gen, outfit styling, mutation explorer)"
|
|
echo " Phase 4 — Studio UI (public feed + character profiles + studio + dark pink theme)"
|
|
echo ""
|
|
|
|
"$SCRIPT_DIR/tree-runner.sh" run aeries-daeya \
|
|
--project-name "$PROJECT_NAME" \
|
|
$([[ "$AUTO_TEARDOWN" == "true" ]] && echo "--auto-teardown")
|
|
|
|
DOMAIN=$(api_call GET "/project/$PROJECT_NAME" | jq -r '.data.domain // empty')
|
|
|
|
if [[ -n "$DOMAIN" ]]; then
|
|
print_success "Aeries Daeya is live at https://$DOMAIN"
|
|
echo ""
|
|
echo " Discovery: https://$DOMAIN (public — no login)"
|
|
echo " Studio: https://$DOMAIN/studio (requires login)"
|
|
echo " API health: https://$DOMAIN/api/daeya-api/health"
|
|
echo " Public feed: https://$DOMAIN/api/daeya-api/characters/public"
|
|
echo ""
|
|
echo " Flow:"
|
|
echo " 1. Open https://$DOMAIN → browse published characters (no login needed)"
|
|
echo " 2. Click 'Create Your Character' → OTP login → /studio"
|
|
echo " 3. Create Character → 4-step wizard (describe, shape, soul, generate)"
|
|
echo " 4. In studio: toggle 'Public' → character appears on discovery feed"
|
|
echo " 5. Open Character → Mutation Explorer (skin tone, background, lighting, style)"
|
|
echo " 6. Add Look → upload a photo of an outfit to style on your character"
|
|
fi
|
|
}
|
|
|
|
check_status() {
|
|
print_header "Project Status: $PROJECT_NAME"
|
|
|
|
local project
|
|
project=$(api_call GET "/project/$PROJECT_NAME")
|
|
local domain
|
|
domain=$(echo "$project" | jq -r '.data.domain // "unknown"')
|
|
local status
|
|
status=$(echo "$project" | jq -r '.data.status // "unknown"')
|
|
|
|
echo " Domain: $domain"
|
|
echo " Status: $status"
|
|
echo ""
|
|
|
|
print_header "Components"
|
|
api_call GET "/projects/$PROJECT_NAME/components" | jq -r '.data[] | " \(.name) (\(.type)): \(.status)"' 2>/dev/null || echo " (no components)"
|
|
|
|
echo ""
|
|
print_header "Recent Pipelines"
|
|
api_call GET "/projects/$PROJECT_NAME/pipelines" | jq -r '.data[0:3][] | " [\(.status)] \(.number) — \(.created_at)"' 2>/dev/null || echo " (no pipelines)"
|
|
|
|
echo ""
|
|
if [[ "$domain" != "unknown" ]]; then
|
|
local health_status
|
|
health_status=$(curl -sf "https://$domain/api/daeya-api/health" 2>/dev/null | jq -r '.data.status // "unreachable"' || echo "unreachable")
|
|
echo " daeya-api health: $health_status"
|
|
fi
|
|
}
|
|
|
|
diagnose() {
|
|
print_header "Diagnostic: $PROJECT_NAME"
|
|
|
|
local domain
|
|
domain=$(api_call GET "/project/$PROJECT_NAME" | jq -r '.data.domain // empty')
|
|
|
|
diagnose_pipeline_failure "$PROJECT_NAME"
|
|
|
|
if [[ -n "$domain" ]]; then
|
|
diagnose_site_failure "$domain" "$PROJECT_NAME"
|
|
fi
|
|
|
|
print_diagnostic_header "Notify / Email Checks"
|
|
echo ""
|
|
echo " If OTP email never arrives:"
|
|
print_fix "Check NOTIFY_API_KEY is injected into the daeya-api pod"
|
|
print_cmd "kubectl exec -n projects deploy/$PROJECT_NAME-daeya-api -- env | grep NOTIFY"
|
|
echo ""
|
|
print_fix "If NOTIFY_API_KEY is empty, notify provisioning failed during project creation"
|
|
print_cmd "curl -s -H 'X-API-Key: \$RDEV_API_KEY' \$RDEV_API_URL/projects/$PROJECT_NAME/notify/status | jq"
|
|
echo ""
|
|
print_fix "Test OTP endpoint directly (200/202/429 = notify working; 404/500 = broken)"
|
|
print_cmd "curl -s -o /dev/null -w '%{http_code}' -X POST https://$domain/api/daeya-api/auth/otp/send -H 'Content-Type: application/json' -d '{\"email\":\"test@example.com\"}'"
|
|
|
|
print_diagnostic_header "AI Generation Checks"
|
|
echo ""
|
|
echo " If characters are stuck in 'pending' status:"
|
|
print_fix "media-worker may not be running or Redis connection may be broken"
|
|
print_cmd "kubectl logs -n projects -l project=$PROJECT_NAME,component=media-worker --tail=50"
|
|
echo ""
|
|
echo " If mutation explorer generates but never shows result:"
|
|
print_fix "SSE channel:daeya subscription may not be connected"
|
|
print_cmd "curl -N -H 'Authorization: Bearer <token>' https://$domain/api/daeya-api/events/channel:daeya"
|
|
echo ""
|
|
echo " If look generation fails with photo upload:"
|
|
print_fix "GEMINI_API_KEY may not be injected or vision endpoint unreachable"
|
|
print_cmd "kubectl exec -n projects deploy/$PROJECT_NAME-media-worker -- env | grep GEMINI"
|
|
|
|
print_diagnostic_header "Public Discovery Checks"
|
|
echo ""
|
|
echo " If /characters/public returns 404:"
|
|
print_fix "implement-avatar-model build may not have created public endpoints"
|
|
print_cmd "curl -s https://$domain/api/daeya-api/characters/public | jq"
|
|
echo ""
|
|
echo " If published characters don't show on the discovery feed:"
|
|
print_fix "Character may not be toggled to published=true in the studio"
|
|
print_cmd "curl -s -H 'Authorization: Bearer <token>' https://$domain/api/daeya-api/characters | jq '.[].published'"
|
|
}
|
|
|
|
teardown() {
|
|
print_header "Tearing down: $PROJECT_NAME"
|
|
|
|
local result
|
|
result=$(api_call DELETE "/project/$PROJECT_NAME")
|
|
print_success "Project $PROJECT_NAME deleted"
|
|
echo "$result" | jq -r '.message // empty' 2>/dev/null || true
|
|
}
|
|
|
|
case "$COMMAND" in
|
|
run) run_flow ;;
|
|
status) check_status ;;
|
|
diagnose) diagnose ;;
|
|
teardown) teardown ;;
|
|
*) echo "Unknown command: $COMMAND"; exit 1 ;;
|
|
esac
|