34336b2907
CI/CD Pipeline / Validate Code Quality And Tests (pull_request) Successful in 39s
CI/CD Pipeline / Unit Tests (pull_request) Successful in 1m12s
CI/CD Pipeline / Frontend Lint (pull_request) Successful in 1m51s
CI/CD Pipeline / Build & Push Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Build Production Runtime Images (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / Integration Tests (pull_request) Successful in 1m25s
- release.sh: 一键发布脚本(打tag + 触发CI构建 + 灰度提示) - gray_deploy.sh: 灰度发布脚本(canary容器 + nginx权重切流) - rollback_gray.sh: 灰度回滚脚本(nginx回滚 + canary清理) - 更新 rollback.sh 占位符为生产环境适配版 灰度范围:API + Web(Nginx upstream 权重) Worker 暂不支持灰度(队列消费无法按比例切流)
78 lines
2.5 KiB
Bash
Executable File
78 lines
2.5 KiB
Bash
Executable File
#!/bin/bash
|
|
# 灰度回滚脚本:切回全量稳定版本,停止 canary 容器
|
|
# 用法: ./scripts/rollback_gray.sh
|
|
|
|
set -euo pipefail
|
|
|
|
NGINX_CONF="${NGINX_CONF:-/etc/nginx/sites-enabled/00-xiaoxia-saas}"
|
|
CANARY_API="${CANARY_API:-xiaoxia-api-canary}"
|
|
CANARY_WEB="${CANARY_WEB:-xiaoxia-web-canary}"
|
|
|
|
echo "============================================"
|
|
echo " 灰度回滚"
|
|
echo " 目标: 全量切回稳定版本"
|
|
echo "============================================"
|
|
|
|
# 1. 找最近的灰度备份
|
|
echo ""
|
|
echo ">>> 查找最近的灰度备份..."
|
|
LATEST_BAK=$(ls -t "${NGINX_CONF}".bak.gray.* 2>/dev/null | head -1 || true)
|
|
|
|
if [[ -z "$LATEST_BAK" ]]; then
|
|
echo " 未找到灰度备份,尝试手动移除 upstream 配置..."
|
|
|
|
# 手动回滚:移除 upstream 块,把 proxy_pass 改回 127.0.0.1
|
|
TMP_CONF=$(mktemp)
|
|
|
|
# 移除 upstream 块(从 "# Gray release upstreams" 到空行结束)
|
|
awk '
|
|
/^# Gray release upstreams/ { skip=1; next }
|
|
skip && /^$/ && !found_first_empty { found_first_empty=1; next }
|
|
skip && found_first_empty && /^$/ { skip=0; found_first_empty=0; next }
|
|
skip { next }
|
|
{ print }
|
|
' "$NGINX_CONF" > "$TMP_CONF"
|
|
|
|
# 把 upstream 名改回 IP
|
|
sed -i 's|proxy_pass http://saas_api_backend|proxy_pass http://127.0.0.1:8001|g' "$TMP_CONF"
|
|
sed -i 's|proxy_pass http://saas_web_backend/|proxy_pass http://127.0.0.1:3002/|g' "$TMP_CONF"
|
|
|
|
mv "$TMP_CONF" "$NGINX_CONF"
|
|
else
|
|
echo " 从备份恢复: $LATEST_BAK"
|
|
cp "$LATEST_BAK" "$NGINX_CONF"
|
|
fi
|
|
|
|
# 2. 测试并 reload nginx
|
|
echo ""
|
|
echo ">>> Nginx 测试 & reload..."
|
|
if ! nginx -t 2>&1; then
|
|
echo " ❌ Nginx 配置测试失败!请检查"
|
|
exit 1
|
|
fi
|
|
nginx -s reload
|
|
echo " ✅ Nginx 已回滚,全量切回稳定版本"
|
|
|
|
# 3. 停止 canary 容器(延迟停止,保留30分钟便于排查)
|
|
echo ""
|
|
echo ">>> Canary 容器将在30分钟后停止(便于排查)"
|
|
echo " 立即停止请执行: docker rm -f $CANARY_API $CANARY_WEB"
|
|
|
|
# 30分钟后停止(后台执行,不阻塞脚本)
|
|
(
|
|
sleep 1800
|
|
for c in "$CANARY_API" "$CANARY_WEB"; do
|
|
if docker ps --format '{{.Names}}' | grep -q "^${c}$"; then
|
|
docker stop "$c" >/dev/null 2>&1 && docker rm "$c" >/dev/null 2>&1
|
|
echo "[$(date)] 已停止 canary 容器: $c"
|
|
fi
|
|
done
|
|
) &
|
|
|
|
echo ""
|
|
echo "============================================"
|
|
echo " ✅ 灰度回滚完成"
|
|
echo " 流量已全部切回稳定版本"
|
|
echo " Canary 容器: 30分钟后自动清理"
|
|
echo "============================================"
|