diff --git a/.gitea/workflows/cd.yaml b/.gitea/workflows/cd.yaml index ecd356d..11e18fc 100644 --- a/.gitea/workflows/cd.yaml +++ b/.gitea/workflows/cd.yaml @@ -291,8 +291,12 @@ jobs: echo "ℹ️ Monitoring 設定未變更,略過重新載入" fi - # ── 健康檢查(H3: HTTP + 三容器狀態雙重驗證) ───────────────────────── + # ── 健康檢查(H3: HTTP + 三容器 + Phase 34 SPA Shadow 偵測) ────────── - name: 健康檢查 + env: + COMMIT_SHA: ${{ steps.commit.outputs.short_sha }} + TELEGRAM_BOT_TOKEN: ${{ secrets.TELEGRAM_BOT_TOKEN }} + TELEGRAM_CHAT_ID: ${{ secrets.TELEGRAM_CHAT_ID }} run: | echo "⏳ 等待服務啟動(30s)..." sleep 30 @@ -320,6 +324,40 @@ jobs: echo "✅ 三容器均正常運行($RUNNING/3)"; \ fi' + # ── Phase 34 SPA Shadow 偵測 — 防 nginx fallback 偽綠 ─────────────── + # 過去 5 個 deploy(run 273-277)全 success 但 prod 上 Flask 從未接到請求, + # 因為 nginx 對 /admin/* 等路徑全 fallback 到 SPA index.html(7480 byte)。 + # 三條 fingerprint 任一不符 SPA = Flask 真接到: + # (a) Content-Length != 7480 + # (b) etag != e167a58a1baf907f55a2925a2e8665d1 + # (c) x-process-time header 存在(Flask middleware) + echo "🔍 SPA Shadow 偵測(驗 Flask 真接到請求)..." + SPA_ETAG='e167a58a1baf907f55a2925a2e8665d1' + SPA_LEN='7480' + # 用 /health(純 Flask,不會被 SPA 路徑攔)做基準探針 + HDR=$(curl -sS -D - -o /dev/null --max-time 10 https://mo.wooo.work/health 2>/dev/null || echo "") + ETAG=$(echo "$HDR" | grep -i '^etag:' | tr -d '"\r' | awk '{print $2}' | tr 'A-Z' 'a-z') + CLEN=$(echo "$HDR" | grep -i '^content-length:' | awk '{print $2}' | tr -d '\r') + XPT=$(echo "$HDR" | grep -i '^x-process-time:' | awk '{print $2}' | tr -d '\r') + FLASK_OK=0 + [ -n "$XPT" ] && [ "$XPT" != "0" ] && FLASK_OK=1 + [ -n "$ETAG" ] && [ "$ETAG" != "$SPA_ETAG" ] && FLASK_OK=1 + [ -n "$CLEN" ] && [ "$CLEN" != "$SPA_LEN" ] && FLASK_OK=1 + if [ "$FLASK_OK" != "1" ]; then + echo "❌ SPA Shadow 偵測:/health 看似 200 但 nginx fallback 攔截" + echo " etag=$ETAG (SPA=$SPA_ETAG)" + echo " content-length=$CLEN (SPA=$SPA_LEN)" + echo " x-process-time=$XPT (Flask 應 > 0)" + # Telegram 告警(如 secrets 已設) + if [ -n "${TELEGRAM_BOT_TOKEN}" ] && [ -n "${TELEGRAM_CHAT_ID}" ]; then + MSG="🚨 EwoooC SPA Shadow 偵測警告%0A├ commit ${COMMIT_SHA}%0A├ /health 被 nginx SPA fallback 攔截%0A└ 立即查 nginx upstream / Flask container" + curl -sS -m 5 -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendMessage" \ + -d "chat_id=${TELEGRAM_CHAT_ID}" -d "text=${MSG}" -d "parse_mode=HTML" >/dev/null || true + fi + exit 1 + fi + echo "✅ SPA Shadow OK — Flask 真接到請求(etag=$ETAG xpt=$XPT clen=$CLEN)" + # ── 觸發 Post-Deploy Code Review ───────────────────────────────────── - name: 觸發 AI Code Review if: success()