From b7950249a71b30181707e8367303030a02ebc878 Mon Sep 17 00:00:00 2001 From: opsBot Date: Tue, 15 Sep 2026 17:04:22 +0800 Subject: [PATCH] =?UTF-8?q?fix(deploy):=20=E5=86=92=E7=83=9F=E5=B0=B1?= =?UTF-8?q?=E7=BB=AA=E8=BD=AE=E8=AF=A2=E5=88=A4=E6=8D=AE=20HTTP200+status?= =?UTF-8?q?=3Dok=EF=BC=8C=E6=9B=BF=E4=BB=A3=E5=9B=BA=E5=AE=9A=20sleep?= =?UTF-8?q?=EF=BC=88=E6=B6=88=E9=99=A4=E5=86=B7=E5=90=AF=E5=8A=A8=E5=81=87?= =?UTF-8?q?=E5=91=8A=E8=AD=A6=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - deploy.sh: 轮询块(0.5s 间隔 / 默认 30s 上限),超时明确报错 + exit 非 0; SMOKE_HEALTH_URL/SMOKE_READY_MAX 可覆盖供离线演练;带 >>> cma-readiness-poll 标记便于抽取复用 - .woodpecker/main.yml backend-deploy: 同样去掉固定 sleep 3,改就绪轮询 - 验收: 离线演练 A(冷启动6s成功)/B(空端口超时非0)/C(200+degraded不误判) - task: t2-cma-deploy-readiness-poll-20260915 --- .woodpecker/main.yml | 3 ++- deploy.sh | 40 ++++++++++++++++++++++++++++------------ 2 files changed, 30 insertions(+), 13 deletions(-) diff --git a/.woodpecker/main.yml b/.woodpecker/main.yml index 63beecb8..6f3068e9 100644 --- a/.woodpecker/main.yml +++ b/.woodpecker/main.yml @@ -68,6 +68,7 @@ steps: - SSH_DEPLOY_KEY commands: - *ssh_setup - - ssh root@git.sxbh.ltd 'set -e; cd /root/cma-management; DIRTY=$(git status --porcelain 2>/dev/null | grep -v "__pycache__" | head -10); if [ -n "$DIRTY" ]; then echo "❌ 宿主机有未提交修改,中止部署:"; echo "$DIRTY"; exit 1; fi; git pull origin main; cd backend; pip install -r requirements.txt --quiet --no-cache-dir; systemctl restart cma-backend; sleep 3; curl -sf http://127.0.0.1:8010/health' + - | + ssh root@git.sxbh.ltd 'set -e; cd /root/cma-management; DIRTY=$(git status --porcelain 2>/dev/null | grep -v "__pycache__" | head -10); if [ -n "$DIRTY" ]; then echo "❌ 宿主机有未提交修改,中止部署:"; echo "$DIRTY"; exit 1; fi; git pull origin main; cd backend; pip install -r requirements.txt --quiet --no-cache-dir; systemctl restart cma-backend; SMOKE_READY_MAX="${SMOKE_READY_MAX:-30}"; READY_TRY=0; READY_OK=0; READY_BODY=/tmp/cma-ci-ready-body.json; while [ "$READY_TRY" -lt $(( SMOKE_READY_MAX * 2 )) ]; do CODE=$(curl -s -o "$READY_BODY" -w "%{http_code}" --max-time 2 http://127.0.0.1:8010/health || echo 000); if [ "$CODE" = "200" ] && grep -q "\"status\":\"ok\"" "$READY_BODY" 2>/dev/null; then READY_OK=1; break; fi; sleep 0.5; READY_TRY=$(( READY_TRY + 1 )); done; if [ "$READY_OK" != "1" ]; then echo "🚨 后端就绪超时 ${SMOKE_READY_MAX}s(未达 HTTP200 + status=ok)"; cat "$READY_BODY" 2>/dev/null; exit 1; fi; echo "✅ 后端就绪(轮询 ${READY_TRY} 次,上限 ${SMOKE_READY_MAX}s)"; cat "$READY_BODY"' when: - path: backend/** diff --git a/deploy.sh b/deploy.sh index b43d68e0..83ab5317 100755 --- a/deploy.sh +++ b/deploy.sh @@ -70,28 +70,44 @@ echo " ✓ 服务重启完成" # ── 部署后冒烟测试 ── echo "" echo "===== 冒烟测试 =====" -# 就绪轮询(2026-09-14 cma-defaultcred-code-fix):journalctl 实测冷启动就绪间隔 2/2/3/3/5s, -# 固定 sleep 3 会让贴边/超时的冷启动误判为冒烟红;改为每 0.5s 探一次 /health,命中即进入判据。 -# 轮询用尽仍不健康 → 下面的健康判据照常判 ❌(不静默放行)。 -# 探测上限可由 SMOKE_READY_MAX 覆盖(离线演练用短上限,生产不设即 30s)。 +# 就绪轮询(2026-09-15 t2-cma-deploy-readiness-poll):journalctl 实测冷启动就绪间隔 2/2/3/3/5s, +# 固定 sleep 3 会让贴边/超时的冷启动误判为冒烟 ❌(假告警,污染后续判断)。 +# 判据 = HTTP 200 **且** 响应体含 {"status":"ok"};每 0.5s 探一次,上限 SMOKE_READY_MAX 秒(默认 30)。 +# 超时 → 明确报错 + exit 非 0(既不静默放行,也不让后续 4 项冒烟产出次生噪音掩盖根因)。 +# SMOKE_HEALTH_URL / SMOKE_READY_MAX 可覆盖,供离线演练(桩服务 / 空端口 / 短上限)。 +# >>> cma-readiness-poll(最小可抽取块:scripts/tests 按行首标记 awk 抽取后原样执行,改结构请沿用标记) SMOKE_READY_MAX="${SMOKE_READY_MAX:-30}" -HEALTH_URL="http://127.0.0.1:8010/health" +HEALTH_URL="${SMOKE_HEALTH_URL:-http://127.0.0.1:8010/health}" READY_TRIES=$(( SMOKE_READY_MAX * 2 )) READY_TRY=0 READY_T0=$(date +%s) +READY_OK=0 +READY_BODY_FILE="$(mktemp -t cma-ready-body.XXXXXX)" while [ "$READY_TRY" -lt "$READY_TRIES" ]; do - if curl -sf "$HEALTH_URL" > /dev/null 2>&1; then break; fi + READY_CODE=$(curl -s -o "$READY_BODY_FILE" -w '%{http_code}' --max-time 2 "$HEALTH_URL" 2>/dev/null || echo 000) + if [ "$READY_CODE" = "200" ] && grep -q '"status"[[:space:]]*:[[:space:]]*"ok"' "$READY_BODY_FILE" 2>/dev/null; then + READY_OK=1 + break + fi sleep 0.5 READY_TRY=$((READY_TRY + 1)) done READY_ELAPSED=$(( $(date +%s) - READY_T0 )) -echo " ⏱ 就绪探测: 耗时 ${READY_ELAPSED}s / 轮询 ${READY_TRY} 次(上限 ${SMOKE_READY_MAX}s,命中健康即停)" -SMOKE_FAIL=0 -if curl -sf http://127.0.0.1:8010/health > /dev/null 2>&1; then - echo " ✅ 后端健康检查通过" -else - echo " ❌ 后端健康检查失败"; SMOKE_FAIL=1 +if [ "$READY_OK" -ne 1 ]; then + READY_LAST=$(head -c 200 "$READY_BODY_FILE" 2>/dev/null) + rm -f "$READY_BODY_FILE" + echo " ⏱ 就绪探测: 耗时 ${READY_ELAPSED}s / 轮询 ${READY_TRY} 次(上限 ${SMOKE_READY_MAX}s)→ ❌ 未就绪" + echo "" + echo "🚨 后端就绪超时(${SMOKE_READY_MAX}s):$HEALTH_URL 未返回 HTTP 200 + {\"status\":\"ok\"}" + echo " 最近响应: ${READY_LAST:-<无响应>}" + echo " 请检查后端日志: journalctl -u cma-backend -n 50" + exit 1 fi +rm -f "$READY_BODY_FILE" +# <<< cma-readiness-poll +echo " ⏱ 就绪探测: 耗时 ${READY_ELAPSED}s / 轮询 ${READY_TRY} 次(上限 ${SMOKE_READY_MAX}s,命中就绪即停)" +SMOKE_FAIL=0 +echo " ✅ 后端健康检查通过(${HEALTH_URL} → status=ok)" if curl -sf http://127.0.0.1:8010/api/cma/bot/ping > /dev/null 2>&1; then echo " ✅ BOT桥接API通过" else