fix(devops): 发版加版本一致性硬校验,杜绝错版 Windows 包/错版部署

根因:github 模式的 windows 构建按版本名(winstage-vX)拉包,不校验提交,
winstage tag 可能打在错误提交上 → 发出「版本号对但代码错版」的包
(client-v1.1.10 缺扫码功能事故)。

- fetch-windows-staged.sh:比对发版提交与 winstage 提交的 client/ 子树 SHA,
  不一致硬失败并提示从发版提交重建 winstage。
- deploy-client.sh:发版前校验 version.yaml + web version.json 版本==tag,
  发版后实测线上 /version==tag(重试5次),任一不符即部署失败。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Bupi8Kdqkfx2N5acFsHTx5
This commit is contained in:
wangjia
2026-08-26 16:14:07 +08:00
parent fc15a34a77
commit 6d64a9bfbf
2 changed files with 67 additions and 0 deletions
+41
View File
@@ -29,6 +29,28 @@ rm -rf /tmp/jiu-web-new
mkdir -p /tmp/jiu-web-new
tar -xzf dist/web.tar.gz -C /tmp/jiu-web-new --strip-components=1
# --- 版本一致性校验(发版前,本地产物)--------------------------------------
# 部署错版事故的通用防线:确认将要上线的产物版本 == 本次发版 tag 版本。
# ① version.yaml 的 version:(后端 /version 与官网下载页实时读它)
# ② Flutter web 产物 version.json 的 version(自动更新客户端据此判断新版)
# 任一不符即中止发版(exit 1),绝不把错版切上线。
TAG_VER="$(ver_from_tag "$TAG")"
# 解析器均把路径经 argv 传入、用 chr(34)/chr(39) 规避引号字面量,免嵌套引号踩坑。
YAML_VER="$(python3 -c 'import sys
for line in open(sys.argv[1], encoding="utf-8"):
if line.startswith("version:"):
print(line.split(":", 1)[1].strip().strip(chr(34)).strip(chr(39))); break' "$VERSION_YAML")"
WEB_VER="$(python3 -c 'import json,sys; print(json.load(open(sys.argv[1], encoding="utf-8")).get("version", ""))' /tmp/jiu-web-new/version.json 2>/dev/null || echo '')"
echo "==> deploy-client: 版本校验 tag=${TAG_VER} version.yaml=${YAML_VER} web=${WEB_VER}"
if [ "$YAML_VER" != "$TAG_VER" ]; then
echo "ERROR: version.yaml 版本(${YAML_VER}) != 发版 tag(${TAG_VER}),中止发版。" >&2
exit 1
fi
if [ -n "$WEB_VER" ] && [ "$WEB_VER" != "$TAG_VER" ]; then
echo "ERROR: Flutter web 产物版本(${WEB_VER}) != 发版 tag(${TAG_VER}),中止发版。" >&2
exit 1
fi
setup_ssh
RSYNC_SSH="ssh -i ~/.ssh/ec2_deploy.pem -o StrictHostKeyChecking=no"
@@ -94,6 +116,25 @@ rm -f /opt/jiu/downloads/jiu-windows-* /opt/jiu/downloads/jiu-macos-* /opt/jiu/d
echo "Client deploy complete!"
ENDSSH
# --- 版本一致性校验(发版后,线上实测)--------------------------------------
# 切换完成后实测线上 /version(后端每请求实时读 version.yaml),确认真正上线的
# 版本 == 发版 tag。不符即判定部署失败(exit 1)。域名 fronts 当前 active 机器。
VERIFY_URL="${VERIFY_URL:-https://jiu.51yanmei.com}"
LIVE_VER=""
for i in 1 2 3 4 5; do
LIVE_VER="$(curl -fsS --max-time 15 "${VERIFY_URL}/version" 2>/dev/null \
| python3 -c "import json,sys; print(json.load(sys.stdin).get('version',''))" 2>/dev/null || echo '')"
[ "$LIVE_VER" = "$TAG_VER" ] && break
echo "!! 线上 /version=${LIVE_VER:-<空>} 尚未更新到 ${TAG_VER}(第 ${i}/5 次),3s 后重试…" >&2
sleep 3
done
if [ "$LIVE_VER" != "$TAG_VER" ]; then
echo "ERROR: 部署后线上 ${VERIFY_URL}/version 版本(${LIVE_VER:-<空>}) != 发版 tag(${TAG_VER}),部署失败。" >&2
teardown_ssh
exit 1
fi
echo "==> deploy-client: 线上版本校验通过 /version=${LIVE_VER}"
teardown_ssh
rm -rf /tmp/jiu-web-new
echo "==> deploy-client: done"