234 lines
6.4 KiB
Bash
Executable File
234 lines
6.4 KiB
Bash
Executable File
#!/bin/bash
|
|
set -euo pipefail
|
|
|
|
# Composable App E2E Test Script
|
|
# Tests the composable monorepo template flow:
|
|
# 1. Create project (skeleton)
|
|
# 2. Add service component
|
|
# 3. Add app component
|
|
# 4. Optionally customize with Claude
|
|
# 5. Deploy and verify
|
|
#
|
|
# Usage: ./cookbooks/scripts/composable-test.sh <command> <project-name>
|
|
# Commands: run, status, teardown
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
source "$SCRIPT_DIR/common.sh"
|
|
|
|
COMMAND="${1:-}"
|
|
PROJECT_NAME="${2:-}"
|
|
|
|
if [[ -z "$COMMAND" || -z "$PROJECT_NAME" ]]; then
|
|
echo "Usage: $0 <command> <project-name>"
|
|
echo "Commands:"
|
|
echo " run - Create project with components and deploy"
|
|
echo " status - Check project and component status"
|
|
echo " diagnose - Deep diagnostic of pipeline and site issues"
|
|
echo " teardown - Delete the project"
|
|
exit 1
|
|
fi
|
|
|
|
# Add a component and verify
|
|
add_component() {
|
|
local comp_type="$1"
|
|
local comp_name="$2"
|
|
local template="${3:-$comp_type}"
|
|
|
|
echo "Adding $comp_type component: $comp_name (template: $template)"
|
|
|
|
local payload
|
|
payload=$(jq -n \
|
|
--arg type "$comp_type" \
|
|
--arg name "$comp_name" \
|
|
--arg template "$template" \
|
|
'{type: $type, name: $name, template: $template}')
|
|
|
|
local result
|
|
result=$(api_call POST "/projects/$PROJECT_NAME/components" "$payload")
|
|
|
|
local path
|
|
path=$(echo "$result" | jq -r '.data.path // .path // ""')
|
|
|
|
if [[ -z "$path" ]]; then
|
|
print_error "Failed to add component"
|
|
echo "$result" | jq '.'
|
|
return 1
|
|
fi
|
|
|
|
local port
|
|
port=$(echo "$result" | jq -r '.data.port // .port // "N/A"')
|
|
print_success "Added $comp_type/$comp_name at $path (port: $port)"
|
|
return 0
|
|
}
|
|
|
|
run_flow() {
|
|
print_header "Composable App E2E Test"
|
|
echo "Project: $PROJECT_NAME"
|
|
|
|
# Step 1: Create project (skeleton)
|
|
print_header "Step 1: Creating project skeleton"
|
|
local create_payload
|
|
create_payload=$(jq -n \
|
|
--arg name "$PROJECT_NAME" \
|
|
--arg desc "Composable app E2E test" \
|
|
'{name: $name, description: $desc}')
|
|
|
|
local create_result
|
|
create_result=$(api_call POST "/project" "$create_payload")
|
|
echo "$create_result" | jq '.'
|
|
|
|
local domain
|
|
domain=$(echo "$create_result" | jq -r '.data.domain // .domain // ""')
|
|
|
|
if [[ -z "$domain" ]]; then
|
|
print_error "Failed to create project"
|
|
exit 1
|
|
fi
|
|
|
|
print_success "Project created with domain: $domain"
|
|
|
|
# Step 2: Add backend service
|
|
print_header "Step 2: Adding backend service"
|
|
if ! add_component "service" "api" "service"; then
|
|
exit 1
|
|
fi
|
|
|
|
# Step 3: Add frontend app
|
|
print_header "Step 3: Adding frontend app"
|
|
if ! add_component "app-react" "web"; then
|
|
exit 1
|
|
fi
|
|
|
|
# Step 4: List components
|
|
print_header "Step 4: Verifying components"
|
|
local components
|
|
components=$(api_call GET "/projects/$PROJECT_NAME/components")
|
|
echo "$components" | jq '.data // .'
|
|
|
|
local comp_count
|
|
comp_count=$(echo "$components" | jq '.data.components | length // 0')
|
|
if [[ "$comp_count" -lt 2 ]]; then
|
|
print_warning "Expected 2 components, got $comp_count"
|
|
else
|
|
print_success "All components added successfully"
|
|
fi
|
|
|
|
# Step 5: Wait for CI pipeline
|
|
print_header "Step 5: Waiting for CI pipeline"
|
|
if ! wait_for_pipeline "$PROJECT_NAME"; then
|
|
print_warning "Pipeline may have issues, continuing to check site..."
|
|
fi
|
|
|
|
# Step 6: Wait for site
|
|
print_header "Step 6: Verifying site is accessible"
|
|
if ! wait_for_site "$domain" 30 5 "$PROJECT_NAME"; then
|
|
print_error "Site not accessible"
|
|
exit 1
|
|
fi
|
|
|
|
# Step 7: Test API endpoint
|
|
print_header "Step 7: Testing API endpoint"
|
|
local api_response
|
|
api_response=$(curl -s "https://$domain/api/health" 2>/dev/null || echo '{"error":"failed"}')
|
|
|
|
if echo "$api_response" | jq -e '.' > /dev/null 2>&1; then
|
|
print_success "API responded with valid JSON"
|
|
echo "$api_response" | jq '.'
|
|
else
|
|
print_warning "API health check returned non-JSON: $api_response"
|
|
fi
|
|
|
|
# Summary
|
|
print_header "E2E Test Results"
|
|
print_success "Project created: $PROJECT_NAME"
|
|
print_success "Components added: $comp_count"
|
|
echo ""
|
|
echo "Site URL: https://$domain"
|
|
echo "Git repo: https://git.threesix.ai/jordan/$PROJECT_NAME"
|
|
echo "CI: https://ci.threesix.ai/jordan/$PROJECT_NAME"
|
|
}
|
|
|
|
check_status() {
|
|
print_header "Project Status: $PROJECT_NAME"
|
|
|
|
# Get project info
|
|
echo "Project:"
|
|
api_call GET "/project/$PROJECT_NAME" | jq '.data // .'
|
|
echo ""
|
|
|
|
# Get components
|
|
echo "Components:"
|
|
api_call GET "/projects/$PROJECT_NAME/components" | jq '.data // .'
|
|
echo ""
|
|
|
|
# Get latest pipelines
|
|
echo "Latest Pipelines:"
|
|
api_call GET "/projects/$PROJECT_NAME/pipelines" | jq '.data[:3] // .'
|
|
}
|
|
|
|
teardown() {
|
|
print_header "Tearing down: $PROJECT_NAME"
|
|
|
|
local result
|
|
result=$(api_call DELETE "/project/$PROJECT_NAME")
|
|
echo "$result" | jq '.'
|
|
|
|
echo ""
|
|
print_success "Project deleted. Gitea repo preserved."
|
|
}
|
|
|
|
diagnose() {
|
|
print_header "Diagnostic: $PROJECT_NAME"
|
|
|
|
# Get project info for domain
|
|
local project
|
|
project=$(api_call GET "/project/$PROJECT_NAME")
|
|
|
|
local domain
|
|
domain=$(echo "$project" | jq -r '.data.domain // ""')
|
|
|
|
if [[ -z "$domain" ]]; then
|
|
print_error "Project not found or no domain assigned"
|
|
echo "$project" | jq '.'
|
|
return 1
|
|
fi
|
|
|
|
echo "Project: $PROJECT_NAME"
|
|
echo "Domain: https://$domain"
|
|
echo "Git: https://git.threesix.ai/$(get_git_owner)/$PROJECT_NAME"
|
|
echo "CI: https://ci.threesix.ai/$(get_git_owner)/$PROJECT_NAME"
|
|
|
|
# Run pipeline diagnostics
|
|
diagnose_pipeline_failure "$PROJECT_NAME"
|
|
|
|
# Run site diagnostics
|
|
diagnose_site_failure "$domain" "$PROJECT_NAME"
|
|
|
|
print_header "Summary"
|
|
echo "To retry the pipeline:"
|
|
print_cmd "Push a commit to trigger CI, or manually trigger from Woodpecker UI"
|
|
echo ""
|
|
echo "To check real-time logs:"
|
|
print_cmd "kubectl logs -n projects -l app=$PROJECT_NAME -f"
|
|
}
|
|
|
|
case "$COMMAND" in
|
|
run)
|
|
run_flow
|
|
;;
|
|
status)
|
|
check_status
|
|
;;
|
|
diagnose)
|
|
diagnose
|
|
;;
|
|
teardown)
|
|
teardown
|
|
;;
|
|
*)
|
|
echo "Unknown command: $COMMAND"
|
|
echo "Valid commands: run, status, diagnose, teardown"
|
|
exit 1
|
|
;;
|
|
esac
|