Files
jiu/scripts/ci/fetch-windows-staged.sh
T
wangjia 6d64a9bfbf 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
2026-08-26 16:14:07 +08:00

87 lines
4.5 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env bash
# fetch-windows-staged.sh <tag> — 发版时从 GitHub Release 拉 Windows 安装器。
#
# 用途:deploy-client.yml 的 build-windows-ci job(仅当 WINDOWS_SOURCE=github 时启用)
# 调用此脚本,按发版 tag(client-vX.Y.Z) 的**同一版本号**去 GitHub 找 `winstage-vX.Y.Z`
# 把 jiu-windows-x64-setup.exe 下到 dist/,供后续 upload-artifact → release/deploy 使用。
#
# **为什么从 GitHub 而不是 NAS**mac-runner 常在 off-LANNAS 只能经 ali frps(慢又易断)
# Windows 包本就是 GitHub 云构建的,直接从 github.com 拉最稳、不过 frps。
#
# **版本强匹配**:找不到对应版本的 GitHub Release → 硬失败并提示先构建该版本,
# 绝不静默发出旧版/错版 Windows 包。
#
# 需要 envGH_TOKEN(github PAT,私有库拉 release 需 auth)GH_REPO(默认 bj-wangjia/jiu)。
set -euo pipefail
TAG="$1"
VER="${TAG#client-v}"; VER="${VER#v}"
STAGE_TAG="winstage-v${VER}"
NAME="jiu-windows-x64-setup.exe"
GH_REPO="${GH_REPO:-bj-wangjia/jiu}"
: "${GH_TOKEN:?需要 GH_TOKEN(github PAT)}"
echo "==> fetch-windows-staged: 发版版本=${VER},从 GitHub 找 ${STAGE_TAG}repo ${GH_REPO}"
api="https://api.github.com/repos/${GH_REPO}"
mkdir -p dist
if ! info=$(curl -fsSL -H "Authorization: Bearer ${GH_TOKEN}" -H "Accept: application/vnd.github+json" "${api}/releases/tags/${STAGE_TAG}" 2>/dev/null); then
cat >&2 <<MSG
ERROR: GitHub 上找不到 Release ${STAGE_TAG}。
WINDOWS_SOURCE=github 需要先在 GitHub 构建**版本 ${VER}** 的 Windows 包:
gh workflow run windows.yml -f ver=${VER} (仓库 ${GH_REPO})
构建完成会发布 Windows Release,再重跑本次发版即可。
MSG
exit 1
fi
# --- client/ 子树 SHA 强校验(根因防线)---------------------------------------
# winstage 的 GitHub Release 是**构建当时** github HEAD 上打的轻量 tag,只按版本名
# 匹配无法保证它构建自本次发版的同一提交。历史事故(client-v1.1.10)winstage-v1.1.10
# 打在了扫码提交的父提交上 → 发出「版本号对但缺扫码功能」的错版 Windows 包。
# 这里比对**发版提交**与**winstage 提交**的 `client/` 子树 SHA(git 内容寻址,同源提交
# 必然同 tree),不一致直接硬失败,逼迫先从发版提交重建 winstage,绝不发出错版。
REL_TREE=$(git rev-parse HEAD:client)
git fetch --depth=1 "https://x-access-token:${GH_TOKEN}@github.com/${GH_REPO}.git" \
"refs/tags/${STAGE_TAG}" >/dev/null 2>&1 || {
echo "ERROR: 无法从 GitHub 拉取 ${STAGE_TAG} 提交以校验 client/ 子树。" >&2
exit 1
}
WIN_TREE=$(git rev-parse FETCH_HEAD:client)
if [ "$REL_TREE" != "$WIN_TREE" ]; then
cat >&2 <<MSG
ERROR: ${STAGE_TAG} 的 Windows 包构建自**错误的提交**,client/ 子树与本次发版不一致:
发版提交(${TAG}) client/ tree = ${REL_TREE}
winstage 提交 client/ tree = ${WIN_TREE}
→ winstage-v${VER} 是在别的提交上打的 tag,发出去会是「版本号对但代码错版」的包。
修复:在 GitHub 用**本次发版的提交**重建 Windows 包,再重跑发版:
gh workflow run windows.yml -f ver=${VER} (仓库 ${GH_REPO},确保其 main 已含本次发版提交)
MSG
exit 1
fi
echo "==> fetch-windows-staged: client/ 子树校验通过(tree ${REL_TREE}),winstage 与发版同源。"
# 取同名资产的 GitHub API asset url(用 Accept: octet-stream 拉二进制,302 跳 codeload,走 github.com 不过 frps
aid=$(printf '%s' "$info" | python3 -c "import sys,json; print(next((a['id'] for a in json.load(sys.stdin).get('assets',[]) if a['name']=='${NAME}'), ''))")
if [ -z "$aid" ]; then
echo "ERROR: ${STAGE_TAG} 存在但缺少 ${NAME} 资产(GitHub 构建可能失败)。" >&2
exit 1
fi
echo "==> fetch-windows-staged: 下载 asset id=${aid}(GitHub)→ dist/${NAME}"
# 重试 + 断点续传(-C -)+ 低速/超时上限:断了自动续传重来,不会一次瞬断就整个失败。
curl -fSL \
--retry 30 --retry-delay 5 --retry-all-errors -C - \
--connect-timeout 15 --speed-time 60 --speed-limit 1024 --max-time 900 \
-H "Authorization: Bearer ${GH_TOKEN}" -H "Accept: application/octet-stream" \
"${api}/releases/assets/${aid}" -o "dist/${NAME}"
ls -lh "dist/${NAME}"
# 完整性校验:安装器至少应有 1MB,防重定向页/截断被当成有效包发出去。
sz=$(wc -c < "dist/${NAME}")
if [ "$sz" -lt 1000000 ]; then
echo "ERROR: 下载的 ${NAME}${sz} 字节,疑似损坏,拒绝发版。" >&2
exit 1
fi
echo "==> fetch-windows-staged: done(版本 ${VER} 匹配,源=GitHub"