fix(ci): download_release_assets 改用 browser_download_url + 下载后大小校验

Forgejo 的 /releases/{id}/assets/{asset_id} API 端点返回 JSON 元数据(约245字节)
而非二进制,导致下载到坏 web.tar.gz、部署时 tar 报 Unrecognized archive format。
改用 asset.browser_download_url(http→https 跟随重定向 + token)拉真正的文件,
并在下载后校验字节数与声明 size 一致,不符即当场失败。

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-28 12:48:17 +08:00
parent 2797c998f8
commit a1a3118c88
+14 -6
View File
@@ -115,15 +115,23 @@ ctx.check_hostname = False
ctx.verify_mode = ssl.CERT_NONE
rel = json.load(open('/tmp/release-info.json'))
token = os.environ['FORGEJO_TOKEN']
url = os.environ['FORGEJO_URL']
repo = os.environ['GITEA_REPOSITORY']
rid = rel['id']
# 用每个 asset 的 browser_download_url 拉真正的二进制。
# 注意:Forgejo 的 /releases/{id}/assets/{asset_id} API 端点返回的是 JSON
# 元数据(几百字节)而非文件本身——曾导致下载到 245B 的坏 web.tar.gz、
# 部署时 tar 报 "Unrecognized archive format"。browser_download_url 是
# http,会 301 到 httpsurllib 默认跟随重定向;带上 token 以防私有仓 401。
for a in rel.get('assets', []):
u = f"{url}/api/v1/repos/{repo}/releases/{rid}/assets/{a['id']}"
req = urllib.request.Request(u, headers={'Authorization': f'token {token}'})
dl = a.get('browser_download_url')
if not dl:
raise SystemExit(f"asset {a.get('name')} 缺 browser_download_url")
req = urllib.request.Request(dl, headers={'Authorization': f'token {token}'})
with urllib.request.urlopen(req, context=ctx) as r, open(f"dist/{a['name']}", 'wb') as o:
o.write(r.read())
print('Downloaded:', a['name'])
got = os.path.getsize(f"dist/{a['name']}")
exp = a.get('size', 0)
print(f"Downloaded: {a['name']} ({got} bytes)")
if exp and got != exp:
raise SystemExit(f"下载大小不符: {a['name']} 期望 {exp} 实得 {got}")
PYEOF
}