Sentry Integration (補強 SignOz): - Add @sentry/nextjs for frontend error tracking + session replay - Add sentry-sdk[fastapi] for backend error tracking - Create sentry.client/server/edge.config.ts - Integrate with next.config.js + instrumentation.ts - Add Sentry exception capture in FastAPI error handler - Create deployment scripts for Self-Hosted @ 192.168.0.110 CI/CD Fixes: - Fix F821 Undefined name 'Field' in incidents.py - Add NEXT_PUBLIC_API_URL env var to CI build step - Add build-arg to Docker build verification E2E Test Improvements: - Fix strict mode violations in dashboard-acceptance tests - Add timeout increase for Phase 4 demo tests - Make tests more resilient to UI variations Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
120 lines
5.2 KiB
Bash
Executable File
120 lines
5.2 KiB
Bash
Executable File
#!/bin/bash
|
||
# =============================================================================
|
||
# AWOOOI 終極全域自動化 QA 處決矩陣 - 正式環境版 (Prod Zero-Touch QA)
|
||
# 目標: awoooi.wooo.work & awoooi-prod Kubernetes Namespace
|
||
# =============================================================================
|
||
# 嚴格模式:任何錯誤立即終止,未定義變數報錯,管線錯誤不被掩蓋
|
||
set -euo pipefail
|
||
|
||
RED='\033[0;31m'
|
||
GREEN='\033[0;32m'
|
||
YELLOW='\033[1;33m'
|
||
CYAN='\033[0;36m'
|
||
NC='\033[0m'
|
||
|
||
# 正式環境專屬變數配置
|
||
PROD_API_URL=${PROD_API_URL:-"https://awoooi.wooo.work"}
|
||
K8S_NAMESPACE=${K8S_NAMESPACE:-"awoooi-prod"}
|
||
LOG_TAIL_LINES=50
|
||
|
||
echo -e "${CYAN}======================================================${NC}"
|
||
echo -e "${CYAN}🚀 AWOOOI 統帥部:正式環境 (PRODUCTION) QA 處決矩陣啟動...${NC}"
|
||
echo -e "${CYAN}目標端點: ${PROD_API_URL}${NC}"
|
||
echo -e "${CYAN}叢集命名空間: ${K8S_NAMESPACE}${NC}"
|
||
echo -e "${CYAN}======================================================${NC}\n"
|
||
|
||
# -----------------------------------------------------------------------------
|
||
# Phase 1: 基礎設施與 API 數據真實性自檢 (HTTPS & Prod DB)
|
||
# -----------------------------------------------------------------------------
|
||
echo -e "${YELLOW}[Phase 1] 實施正式環境基礎設施與 API 數據自檢...${NC}"
|
||
|
||
echo -n " -> 測試 Prod API 骨幹存活度與 Redis/DB 連線: "
|
||
# 使用 -k 略過本地開發可能的憑證問題,但正式環境應保持嚴格校驗,此處不加 -k
|
||
HEALTH_RESPONSE=$(curl -s -w "\n%{http_code}" "${PROD_API_URL}/api/v1/health" || echo -e "\n500")
|
||
HTTP_BODY=$(echo "$HEALTH_RESPONSE" | sed '$d')
|
||
HTTP_CODE=$(echo "$HEALTH_RESPONSE" | tail -n1)
|
||
|
||
if [ "$HTTP_CODE" -ne 200 ]; then
|
||
echo -e "${RED}FAILED (HTTP $HTTP_CODE)${NC}"
|
||
echo -e "${RED}❌ Prod API Server 未就緒或拒絕連線!${NC}"
|
||
exit 1
|
||
fi
|
||
|
||
# 檢查 API 回傳 status: "healthy" 且所有 components 都 "up"
|
||
if echo "$HTTP_BODY" | grep -q '"status":"healthy"'; then
|
||
echo -e "${GREEN}PASSED (HTTP 200 & status=healthy)${NC}"
|
||
else
|
||
echo -e "${RED}FAILED${NC}"
|
||
echo -e "${RED}❌ API 回傳 200,但正式環境 JSON 數據狀態異常!Raw Data: $HTTP_BODY${NC}"
|
||
exit 1
|
||
fi
|
||
|
||
# -----------------------------------------------------------------------------
|
||
# Phase 2: 全鏈路 E2E 驗證 (Playwright targeting Prod)
|
||
# -----------------------------------------------------------------------------
|
||
echo -e "\n${YELLOW}[Phase 2] 啟動 Playwright E2E 視覺憲法與邏輯測試...${NC}"
|
||
cd apps/web || { echo -e "${RED}❌ 找不到 apps/web 目錄!${NC}"; exit 1; }
|
||
|
||
echo " -> 執行依賴檢查 (pnpm install)..."
|
||
pnpm install --silent
|
||
|
||
echo " -> 執行 Playwright 測試矩陣 (指向正式環境)..."
|
||
# 注入 BASE_URL 環境變數,強迫 Playwright 打向正式環境而非 localhost
|
||
if BASE_URL="${PROD_API_URL}" pnpm exec playwright test --reporter=list,html; then
|
||
echo -e "${GREEN} ✅ Prod 前端 E2E 視覺與互動測試全數通過!${NC}"
|
||
else
|
||
echo -e "${RED} ❌ Playwright 正式環境測試遭遇失敗!${NC}"
|
||
echo -e " 🔍 請打開 apps/web/playwright-report/index.html 進行詳細視覺診斷!"
|
||
exit 1
|
||
fi
|
||
|
||
cd ../../ # 回到根目錄
|
||
|
||
# -----------------------------------------------------------------------------
|
||
# Phase 3: K8s 雙端日誌深層稽核 (Kubernetes Log Verification)
|
||
# -----------------------------------------------------------------------------
|
||
echo -e "\n${YELLOW}[Phase 3] 執行開發憲法鐵律:Kubernetes Pod 雙端日誌稽核...${NC}"
|
||
|
||
has_error=0
|
||
|
||
check_k8s_logs() {
|
||
local app_label=$1
|
||
echo -n " -> 掃描 Deployment [$app_label] 歷史日誌是否有隱性崩潰: "
|
||
|
||
# 檢查該 Label 的 Pod 是否存在且 Running
|
||
POD_COUNT=$(kubectl get pods -n "$K8S_NAMESPACE" -l "app=$app_label" --field-selector=status.phase=Running --no-headers 2>/dev/null | wc -l || echo "0")
|
||
|
||
if [ "$POD_COUNT" -eq 0 ]; then
|
||
echo -e "${YELLOW}SKIPPED (No Running Pods found for app=$app_label)${NC}"
|
||
return
|
||
fi
|
||
|
||
# 使用 kubectl logs 抓取該 label 下所有 Pod 的最後 N 行日誌
|
||
LOG_ERRORS=$(kubectl logs -n "$K8S_NAMESPACE" -l "app=$app_label" --tail="$LOG_TAIL_LINES" --all-containers 2>&1 | grep -iE "error|exception|traceback|critical" || true)
|
||
|
||
if [ -n "$LOG_ERRORS" ]; then
|
||
echo -e "${RED}FAILED${NC}"
|
||
echo -e "${RED}❌ 警告!在 Prod [$app_label] 發現隱性錯誤日誌:${NC}"
|
||
echo -e "$LOG_ERRORS" | head -n 5
|
||
has_error=1
|
||
else
|
||
echo -e "${GREEN}CLEAN (無隱性異常)${NC}"
|
||
fi
|
||
}
|
||
|
||
# 檢查 K8s 中的 API 與 Worker (使用 Label Selector)
|
||
check_k8s_logs "awoooi-api"
|
||
check_k8s_logs "awoooi-worker"
|
||
|
||
if [ "$has_error" -eq 1 ]; then
|
||
echo -e "\n${RED}☠️ 正式環境深層稽核失敗!前端雖正常,但 K8s 底層日誌存在致命錯誤。請立即介入調查!${NC}"
|
||
exit 1
|
||
fi
|
||
|
||
# -----------------------------------------------------------------------------
|
||
# Phase 4: 戰果總結
|
||
# -----------------------------------------------------------------------------
|
||
echo -e "\n${CYAN}======================================================${NC}"
|
||
echo -e "${GREEN}🎉 統帥,awoooi.wooo.work 正式環境全鏈路與 K8s 日誌稽核完美通關!系統堅如磐石。${NC}"
|
||
echo -e "${CYAN}======================================================${NC}"
|
||
exit 0 |