# skills 详细内容 ## 回滚策略 ### iOS TestFlight 回滚 TestFlight **无法真正回滚**已安装的版本,但有以下应急手段: | 手段 | 说明 | API | |------|------|-----| | 停止分发 | 将 build 从测试中移除,用户不再收到更新 | `PATCH /v1/builds/{id}` 设置 `expired: true` | | 过期 build | 强制过期有问题的 build | 同上 | | 紧急热修 | 构建新版本覆盖上线 | 常规部署流程 | ```bash # 通过 ASC API 停止分发某个 build curl -X PATCH "https://api.appstoreconnect.apple.com/v1/builds/$BUILD_ID" \ -H "Authorization: Bearer $JWT_TOKEN" \ -H "Content-Type: application/json" \ -d '{"data":{"type":"builds","id":"'$BUILD_ID'","attributes":{"expired":true}}}' ``` ### Docker 回滚 Docker 回滚相对简单,拉取上一个正常版本的镜像重新部署即可: ```bash # 1. 确定上一个正常的 tag PREVIOUS_TAG= REGISTRY=crpi-q4nnuivosic0zc98.cn-beijing.personal.cr.aliyuncs.com # 2. 在服务器上回滚 ssh -i ~/.ssh/xiaoqu.pem root@39.104.87.246 " cd /opt/xiaoqu/production # 或 /opt/xiaoqu/staging export IMAGE_TAG=$PREVIOUS_TAG docker compose pull docker compose up -d " # 3. 验证回滚成功 curl -sf http://39.104.87.246/health && echo 'Rollback OK' ``` ### 数据库回滚注意事项 | 场景 | 策略 | |------|------| | 可逆 migration(加列、加表) | 部署回滚后数据库无需回滚,旧代码忽略新列 | | 不可逆 migration(删列、改类型) | **必须先回滚 migration 再回滚代码**,否则旧代码报错 | | 数据 migration | 评估是否需要补偿脚本,建议 migration 前做备份快照 | ```bash # 数据库 migration 回滚示例(如果使用 golang-migrate) ssh -i ~/.ssh/xiaoqu.pem root@39.104.87.246 " docker compose exec gateway migrate -path /migrations -database \$DATABASE_URL down 1 " ``` --- ## 部署监控 ### Post-deploy 健康检查模式 ```bash # 通用部署后验证函数 post_deploy_verify() { local url=$1 local max_retries=${2:-5} local interval=${3:-10} echo "Verifying deployment at $url ..." for i in $(seq 1 $max_retries); do local status status=$(curl -sf -o /dev/null -w "%{http_code}" "$url" 2>/dev/null || echo "000") if [ "$status" = "200" ]; then echo "Health check passed (attempt $i/$max_retries)" return 0 fi echo "Attempt $i/$max_retries: status=$status, retrying in ${interval}s..." sleep $interval done echo "Health check FAILED after $max_retries attempts" return 1 } # 使用示例 post_deploy_verify "http://39.104.87.246/health" 5 10 ``` ### 飞书通知模板 部署完成后通过飞书 Webhook 发送通知: ```bash # 部署成功通知 send_feishu_deploy_notification() { local env=$1 # staging / production local version=$2 # 版本号或 tag local status=$3 # success / failure local detail=$4 # 额外说明 local WEBHOOK_URL="<飞书群 Webhook 地址>" if [ "$status" = "success" ]; then local color="green" local emoji="✅" else local color="red" local emoji="❌" fi curl -s -X POST "$WEBHOOK_URL" \ -H "Content-Type: application/json" \ -d '{ "msg_type": "interactive", "card": { "header": { "title": {"tag": "plain_text", "content": "'"$emoji"' 部署通知 - '"$env"'"}, "template": "'"$color"'" }, "elements": [ {"tag": "div", "text": {"tag": "lark_md", "content": "**环境**: '"$env"'\n**版本**: '"$version"'\n**状态**: '"$status"'\n**时间**: '"$(date '+%Y-%m-%d %H:%M:%S')"'\n**详情**: '"$detail"'"}} ] } }' } # 使用示例 send_feishu_deploy_notification "production" "v1.2.3" "success" "Gateway + Web 部署完成" send_feishu_deploy_notification "staging" "abc12345" "failure" "Health check 超时" ``` ### iOS TestFlight 构建状态监控 通过 ASC API 持续监控 build 处理状态: ```bash # 监控 TestFlight build 处理状态 monitor_testflight_build() { local build_id=$1 local jwt_token=$2 local max_wait=600 # 最长等待 10 分钟 local elapsed=0 while [ $elapsed -lt $max_wait ]; do local response response=$(curl -s "https://api.appstoreconnect.apple.com/v1/builds/$build_id" \ -H "Authorization: Bearer $jwt_token") local state state=$(echo "$response" | python3 -c "import sys,json; print(json.load(sys.stdin)['data']['attributes']['processingState'])" 2>/dev/null) echo "[$(date '+%H:%M:%S')] Build $build_id: $state" case "$state" in VALID) echo "Build 处理完成,可用于测试" return 0 ;; FAILED|INVALID) echo "Build 处理失败: $state" return 1 ;; PROCESSING) sleep 30 ((elapsed+=30)) ;; *) sleep 15 ((elapsed+=15)) ;; esac done echo "Build 处理超时(${max_wait}s)" return 1 } ``` ---