From a1a3118c88c22fbf4ca20da26b4908f8501f7a05 Mon Sep 17 00:00:00 2001 From: wangjia <809946525@qq.com> Date: Fri, 28 Aug 2026 12:48:17 +0800 Subject: [PATCH] =?UTF-8?q?fix(ci):=20download=5Frelease=5Fassets=20?= =?UTF-8?q?=E6=94=B9=E7=94=A8=20browser=5Fdownload=5Furl=20+=20=E4=B8=8B?= =?UTF-8?q?=E8=BD=BD=E5=90=8E=E5=A4=A7=E5=B0=8F=E6=A0=A1=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Claude-Session: https://claude.ai/code/session_01Bupi8Kdqkfx2N5acFsHTx5 --- scripts/ci/lib-forgejo.sh | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/scripts/ci/lib-forgejo.sh b/scripts/ci/lib-forgejo.sh index ade9a81..3231a47 100644 --- a/scripts/ci/lib-forgejo.sh +++ b/scripts/ci/lib-forgejo.sh @@ -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 到 https,urllib 默认跟随重定向;带上 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 }