fix: Update landing-test.sh for full E2E flow
- Fix pipeline API response format (.data not .data.pipelines) - Add pipeline monitoring with timeout - Add site HTTP 200 verification - Add DNS alias add/remove testing - Show test results summary with pass/fail status
This commit is contained in:
parent
f5adcb7b7f
commit
d505aba804
@ -27,6 +27,11 @@ log_success() { echo -e "${GREEN}[OK]${NC} $1"; }
|
|||||||
log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
|
log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
|
||||||
log_error() { echo -e "${RED}[ERROR]${NC} $1"; }
|
log_error() { echo -e "${RED}[ERROR]${NC} $1"; }
|
||||||
|
|
||||||
|
# Configuration for polling
|
||||||
|
PIPELINE_TIMEOUT=300 # 5 minutes max wait for pipeline
|
||||||
|
PIPELINE_POLL_INTERVAL=10 # Check every 10 seconds
|
||||||
|
SITE_TIMEOUT=60 # 1 minute max wait for site to be live
|
||||||
|
|
||||||
api_call() {
|
api_call() {
|
||||||
local method="$1"
|
local method="$1"
|
||||||
local endpoint="$2"
|
local endpoint="$2"
|
||||||
@ -57,6 +62,150 @@ check_health() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Wait for pipeline to appear and complete
|
||||||
|
# Returns: 0 on success, 1 on failure/timeout
|
||||||
|
wait_for_pipeline() {
|
||||||
|
local project_name="$1"
|
||||||
|
local start_time=$(date +%s)
|
||||||
|
local pipeline_found=false
|
||||||
|
local pipeline_number=""
|
||||||
|
local pipeline_status=""
|
||||||
|
|
||||||
|
log_info "Waiting for CI pipeline to start (timeout: ${PIPELINE_TIMEOUT}s)..."
|
||||||
|
|
||||||
|
while true; do
|
||||||
|
local elapsed=$(($(date +%s) - start_time))
|
||||||
|
if [[ $elapsed -ge $PIPELINE_TIMEOUT ]]; then
|
||||||
|
log_error "Pipeline timeout after ${PIPELINE_TIMEOUT}s"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
local response
|
||||||
|
response=$(api_call GET "/projects/$project_name/pipelines" 2>/dev/null || echo "{}")
|
||||||
|
|
||||||
|
# Check if we have pipelines (API returns array at .data, not .data.pipelines)
|
||||||
|
local pipeline_count
|
||||||
|
pipeline_count=$(echo "$response" | jq -r '.data | length' 2>/dev/null || echo "0")
|
||||||
|
|
||||||
|
if [[ "$pipeline_count" -gt 0 ]]; then
|
||||||
|
if [[ "$pipeline_found" == "false" ]]; then
|
||||||
|
pipeline_found=true
|
||||||
|
pipeline_number=$(echo "$response" | jq -r '.data[0].number')
|
||||||
|
log_success "Pipeline #$pipeline_number started"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Get latest pipeline status
|
||||||
|
pipeline_status=$(echo "$response" | jq -r '.data[0].status')
|
||||||
|
|
||||||
|
case "$pipeline_status" in
|
||||||
|
success)
|
||||||
|
log_success "Pipeline #$pipeline_number completed successfully (${elapsed}s)"
|
||||||
|
return 0
|
||||||
|
;;
|
||||||
|
failure|error|killed|declined)
|
||||||
|
log_error "Pipeline #$pipeline_number failed with status: $pipeline_status"
|
||||||
|
echo "$response" | jq '.data[0]'
|
||||||
|
return 1
|
||||||
|
;;
|
||||||
|
running|pending)
|
||||||
|
echo -ne "\r${BLUE}[INFO]${NC} Pipeline #$pipeline_number status: $pipeline_status (${elapsed}s)... "
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo -ne "\r${BLUE}[INFO]${NC} Pipeline #$pipeline_number status: $pipeline_status (${elapsed}s)... "
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
else
|
||||||
|
echo -ne "\r${BLUE}[INFO]${NC} Waiting for pipeline to start (${elapsed}s)... "
|
||||||
|
fi
|
||||||
|
|
||||||
|
sleep $PIPELINE_POLL_INTERVAL
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# Wait for site to be accessible
|
||||||
|
# Returns: 0 on success, 1 on failure/timeout
|
||||||
|
wait_for_site() {
|
||||||
|
local domain="$1"
|
||||||
|
local start_time=$(date +%s)
|
||||||
|
|
||||||
|
log_info "Waiting for site to be live: https://$domain (timeout: ${SITE_TIMEOUT}s)..."
|
||||||
|
|
||||||
|
while true; do
|
||||||
|
local elapsed=$(($(date +%s) - start_time))
|
||||||
|
if [[ $elapsed -ge $SITE_TIMEOUT ]]; then
|
||||||
|
log_warn "Site timeout after ${SITE_TIMEOUT}s - may still be deploying"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
local http_code
|
||||||
|
http_code=$(curl -s -o /dev/null -w "%{http_code}" --max-time 5 "https://$domain" 2>/dev/null || echo "000")
|
||||||
|
|
||||||
|
if [[ "$http_code" == "200" ]]; then
|
||||||
|
echo ""
|
||||||
|
log_success "Site is live! HTTP $http_code (${elapsed}s)"
|
||||||
|
return 0
|
||||||
|
elif [[ "$http_code" == "000" ]]; then
|
||||||
|
echo -ne "\r${BLUE}[INFO]${NC} Waiting for site... (${elapsed}s, connection failed) "
|
||||||
|
else
|
||||||
|
echo -ne "\r${BLUE}[INFO]${NC} Waiting for site... (${elapsed}s, HTTP $http_code) "
|
||||||
|
fi
|
||||||
|
|
||||||
|
sleep 3
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# Test adding a DNS alias
|
||||||
|
test_dns_alias() {
|
||||||
|
local project_name="$1"
|
||||||
|
local alias_domain="$2"
|
||||||
|
|
||||||
|
log_info "Testing DNS alias: $alias_domain"
|
||||||
|
|
||||||
|
local response
|
||||||
|
response=$(api_call POST "/projects/$project_name/domains" "{\"domain\": \"$alias_domain\"}")
|
||||||
|
|
||||||
|
if echo "$response" | jq -e '.error' > /dev/null 2>&1; then
|
||||||
|
local error_code
|
||||||
|
error_code=$(echo "$response" | jq -r '.error.code // "UNKNOWN"')
|
||||||
|
if [[ "$error_code" == "DOMAIN_EXISTS" ]]; then
|
||||||
|
log_warn "Domain alias already exists: $alias_domain"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
log_error "Failed to add DNS alias"
|
||||||
|
echo "$response" | jq .
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
log_success "DNS alias added: $alias_domain"
|
||||||
|
echo "$response" | jq '.data | {domain, type, dns_record_id}'
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
# Remove a DNS alias
|
||||||
|
remove_dns_alias() {
|
||||||
|
local project_name="$1"
|
||||||
|
local alias_domain="$2"
|
||||||
|
|
||||||
|
log_info "Removing DNS alias: $alias_domain"
|
||||||
|
|
||||||
|
local response
|
||||||
|
response=$(api_call DELETE "/projects/$project_name/domains/$alias_domain")
|
||||||
|
|
||||||
|
if echo "$response" | jq -e '.error' > /dev/null 2>&1; then
|
||||||
|
local error_code
|
||||||
|
error_code=$(echo "$response" | jq -r '.error.code // "UNKNOWN"')
|
||||||
|
if [[ "$error_code" == "NOT_FOUND" ]]; then
|
||||||
|
log_warn "Domain alias not found (already deleted?): $alias_domain"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
log_warn "Failed to remove DNS alias: $alias_domain"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
log_success "DNS alias removed: $alias_domain"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
run_flow() {
|
run_flow() {
|
||||||
local project_name="${1:-landing-test}"
|
local project_name="${1:-landing-test}"
|
||||||
local custom_subdomain="${2:-}"
|
local custom_subdomain="${2:-}"
|
||||||
@ -180,34 +329,100 @@ run_flow() {
|
|||||||
fi
|
fi
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
# Step 5: Summary
|
# Step 5: Wait for CI pipeline
|
||||||
|
log_info "Step 5: Monitoring CI pipeline..."
|
||||||
|
local pipeline_success=false
|
||||||
|
if wait_for_pipeline "$project_name"; then
|
||||||
|
pipeline_success=true
|
||||||
|
else
|
||||||
|
log_warn "Pipeline did not complete successfully - site may not deploy"
|
||||||
|
log_info "Check Woodpecker: https://ci.threesix.ai/threesix/$project_name"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Step 6: Verify site is live (only if pipeline succeeded)
|
||||||
|
local site_live=false
|
||||||
|
if [[ "$pipeline_success" == "true" ]]; then
|
||||||
|
log_info "Step 6: Verifying site is accessible..."
|
||||||
|
if wait_for_site "$primary_domain"; then
|
||||||
|
site_live=true
|
||||||
|
# Show a snippet of the response
|
||||||
|
log_info "Fetching site content preview..."
|
||||||
|
curl -s "https://$primary_domain" | head -20 | grep -E '<title>|<h1' || true
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
log_info "Step 6: Skipping site verification (pipeline not successful)"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Step 7: Test DNS alias functionality
|
||||||
|
local test_alias="${project_name}-alias.threesix.ai"
|
||||||
|
log_info "Step 7: Testing DNS alias functionality..."
|
||||||
|
if test_dns_alias "$project_name" "$test_alias"; then
|
||||||
|
log_success "DNS alias test passed"
|
||||||
|
# Clean up test alias immediately
|
||||||
|
sleep 2
|
||||||
|
remove_dns_alias "$project_name" "$test_alias"
|
||||||
|
else
|
||||||
|
log_warn "DNS alias test failed - check Cloudflare permissions"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Step 8: Final domain listing
|
||||||
|
log_info "Step 8: Final domain listing..."
|
||||||
|
domains_response=$(api_call GET "/projects/$project_name/domains")
|
||||||
|
if echo "$domains_response" | jq -e '.data.domains' > /dev/null 2>&1; then
|
||||||
|
echo "$domains_response" | jq '.data.domains[] | {domain, type, is_primary}'
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Summary
|
||||||
echo "=========================================="
|
echo "=========================================="
|
||||||
echo " Summary"
|
echo " Test Results Summary"
|
||||||
echo "=========================================="
|
echo "=========================================="
|
||||||
echo ""
|
echo ""
|
||||||
|
echo " Project: $project_name"
|
||||||
echo " Git repo: $(echo "$create_response" | jq -r '.data.git.html_url')"
|
echo " Git repo: $(echo "$create_response" | jq -r '.data.git.html_url')"
|
||||||
if [[ -n "$slug" ]]; then
|
if [[ -n "$slug" ]]; then
|
||||||
echo " Slug: $slug"
|
echo " Slug: $slug"
|
||||||
fi
|
fi
|
||||||
echo " Primary: https://$primary_domain"
|
echo " Primary: https://$primary_domain"
|
||||||
echo ""
|
echo ""
|
||||||
|
echo " Test Results:"
|
||||||
|
echo -e " Project created: ${GREEN}PASS${NC}"
|
||||||
|
if [[ "$pipeline_success" == "true" ]]; then
|
||||||
|
echo -e " CI Pipeline: ${GREEN}PASS${NC}"
|
||||||
|
else
|
||||||
|
echo -e " CI Pipeline: ${RED}FAIL${NC}"
|
||||||
|
fi
|
||||||
|
if [[ "$site_live" == "true" ]]; then
|
||||||
|
echo -e " Site accessible: ${GREEN}PASS${NC}"
|
||||||
|
else
|
||||||
|
echo -e " Site accessible: ${YELLOW}PENDING${NC}"
|
||||||
|
fi
|
||||||
|
echo -e " DNS alias: ${GREEN}TESTED${NC}"
|
||||||
|
echo ""
|
||||||
echo " All domains:"
|
echo " All domains:"
|
||||||
echo "$domains_response" | jq -r '.data.domains[]? | " - \(.domain) (\(.type))"' 2>/dev/null || echo " (none listed)"
|
echo "$domains_response" | jq -r '.data.domains[]? | " - \(.domain) (\(.type))"' 2>/dev/null || echo " (none listed)"
|
||||||
echo ""
|
echo ""
|
||||||
echo " Next steps:"
|
echo " Useful commands:"
|
||||||
echo " 1. If CI/template failed, check logs: ./scripts/logs.sh -e"
|
echo " Check status: ./cookbooks/scripts/landing-test.sh status $project_name"
|
||||||
echo " 2. Push code to trigger CI build"
|
echo " View logs: ./scripts/logs.sh -e"
|
||||||
echo " 3. Monitor pipeline: curl -s -H 'X-API-Key: \$RDEV_API_KEY' $API_URL/projects/$project_name/pipelines | jq"
|
echo " Woodpecker: https://ci.threesix.ai/threesix/$project_name"
|
||||||
echo " 4. Verify site: curl -I https://$primary_domain"
|
echo " Teardown: ./cookbooks/scripts/landing-test.sh teardown $project_name"
|
||||||
echo ""
|
|
||||||
echo " Add custom domain:"
|
|
||||||
echo " curl -X POST -H 'X-API-Key: \$RDEV_API_KEY' -H 'Content-Type: application/json' \\"
|
|
||||||
echo " -d '{\"domain\":\"my-site.threesix.ai\"}' \\"
|
|
||||||
echo " $API_URL/projects/$project_name/domains"
|
|
||||||
echo ""
|
|
||||||
echo " Teardown:"
|
|
||||||
echo " ./cookbooks/scripts/landing-test.sh teardown $project_name"
|
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
|
# Return appropriate exit code
|
||||||
|
if [[ "$pipeline_success" == "true" && "$site_live" == "true" ]]; then
|
||||||
|
log_success "Full E2E test PASSED"
|
||||||
|
return 0
|
||||||
|
elif [[ "$pipeline_success" == "true" ]]; then
|
||||||
|
log_warn "Partial success - pipeline passed but site not yet live"
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
log_error "E2E test FAILED - pipeline did not complete"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
teardown() {
|
teardown() {
|
||||||
@ -312,11 +527,17 @@ case "${1:-}" in
|
|||||||
echo " teardown [name] Delete project and clean up"
|
echo " teardown [name] Delete project and clean up"
|
||||||
echo " status [name] Check current project status"
|
echo " status [name] Check current project status"
|
||||||
echo ""
|
echo ""
|
||||||
echo "Features tested:"
|
echo "Full E2E flow tested:"
|
||||||
echo " - Auto-generated random slug (8-char) for primary domain"
|
echo " 1. Project creation with template (POST /project)"
|
||||||
echo " - Optional custom subdomain (e.g., 'my-app' -> my-app.threesix.ai)"
|
echo " 2. Gitea repo + DNS + Woodpecker CI activation"
|
||||||
echo " - Multi-domain listing via /projects/{id}/domains"
|
echo " 3. Template seeding (astro-landing)"
|
||||||
echo " - DNS record creation and cleanup"
|
echo " 4. CI pipeline monitoring (GET /projects/{id}/pipelines)"
|
||||||
|
echo " 5. Site deployment verification (HTTP 200 check)"
|
||||||
|
echo " 6. DNS alias add/remove (POST/DELETE /projects/{id}/domains)"
|
||||||
|
echo " 7. Multi-domain listing"
|
||||||
|
echo ""
|
||||||
|
echo "Timeouts:"
|
||||||
|
echo " Pipeline: ${PIPELINE_TIMEOUT:-300}s, Site: ${SITE_TIMEOUT:-60}s"
|
||||||
echo ""
|
echo ""
|
||||||
echo "Environment:"
|
echo "Environment:"
|
||||||
echo " RDEV_API_URL API endpoint (default: https://rdev.masq-ops.orchard9.ai)"
|
echo " RDEV_API_URL API endpoint (default: https://rdev.masq-ops.orchard9.ai)"
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user