diff --git a/cookbooks/scripts/landing-test.sh b/cookbooks/scripts/landing-test.sh index 7ea8253..d4cda13 100755 --- a/cookbooks/scripts/landing-test.sh +++ b/cookbooks/scripts/landing-test.sh @@ -27,6 +27,11 @@ log_success() { echo -e "${GREEN}[OK]${NC} $1"; } log_warn() { echo -e "${YELLOW}[WARN]${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() { local method="$1" local endpoint="$2" @@ -57,6 +62,150 @@ check_health() { 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() { local project_name="${1:-landing-test}" local custom_subdomain="${2:-}" @@ -180,34 +329,100 @@ run_flow() { fi 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 '