Files
ModelRouter/packaging/upload-release.sh
JianFeeeee 6fe6014d92 chore: 清理 emoji 与修正发布脚本仓库名
产品代码统一为纯文本风格(照参考实现),去掉 emoji:billing/quota/usage 插件、
channels 的提示文案、WebUI 文案,以及 go 测试、docs、packaging 脚本中的
注意/OK/FAIL 等符号化写法。第三方目录(vendor、node_modules、.probe)不动。

另:packaging/upload-release.sh 的仓库名改为真实全名
JianFeeeee/ModelRouter → HeNanMU-EEA/ModelRouter(前者是重定向,POST/PUT 不跟随
会 404)。
2026-10-13 13:42:57 +08:00

72 lines
2.6 KiB
Bash
Executable File

#!/usr/bin/env bash
# Upload release assets to a GitCode release.
#
# The endpoint shapes are asymmetric and both differ from the "obvious" guess:
#
# GET /releases/tags/{tag} → read a release
# GET /releases/{tag}/upload_url → get a presigned PUT (NO "tags/")
# PUT {presigned url} → upload, REPLAYING the headers verbatim
#
# Two mistakes cost real time on v1.9.5 before this script existed:
#
# 1. POSTing straight to /releases/{tag}/assets returns 404 — that endpoint
# does not exist. It reads as "authentication failed" if you only check
# the status code.
# 2. PUTting without the headers fails with an opaque storage error, not a
# permission one, so it looks like a size limit or a corrupt file.
#
# The x-obs-* headers are part of the signature: dropping any one of them turns
# the request into an unsigned one.
set -uo pipefail
TOKEN="$(tr -d '\n\r' < /tmp/gc_token)"
REPO="HeNanMU-EEA/ModelRouter"
TAG="${1:?usage: upload-release.sh <tag> <file>...}"
shift
API="https://gitcode.com/api/v5/repos/${REPO}"
for f in "$@"; do
name="$(basename "$f")"
size="$(stat -c%s "$f")"
printf ' %-46s %10s bytes ' "$name" "$size"
# 1) presigned upload location. The file name must be URL-encoded; the v1.9.4
# assets show "~" surviving in a stored name, so encoding is per-component.
enc="$(python3 -c 'import urllib.parse,sys; print(urllib.parse.quote(sys.argv[1]))' "$name")"
resp="$(curl -sS -m 60 -H "Authorization: Bearer ${TOKEN}" \
"${API}/releases/${TAG}/upload_url?file_name=${enc}" 2>&1)"
url="$(printf '%s' "$resp" | python3 -c 'import json,sys
try:
d = json.load(sys.stdin)
print(d.get("url") or d.get("uploadUrl") or "")
except Exception:
print("")' 2>/dev/null)"
if [ -z "$url" ]; then
echo "FAIL 取得上传地址失败: ${resp:0:140}"
continue
fi
# 2) PUT with the headers replayed exactly as returned.
code="$(printf '%s' "$resp" | python3 -c 'import json,sys
try:
print(json.dumps(json.load(sys.stdin).get("headers") or {}))
except Exception:
print("{}")' 2>/dev/null | python3 -c '
import json, subprocess, sys
headers = json.load(sys.stdin)
args = ["curl", "-sS", "-o", "/dev/null", "-w", "%{http_code}", "-X", "PUT"]
for k, v in headers.items():
args += ["-H", f"{k}: {v}"]
args += ["--data-binary", "@" + sys.argv[1], sys.argv[2]]
print(subprocess.run(args, capture_output=True, text=True).stdout)
' "$f" "$url" 2>/dev/null)"
if [ "$code" = "200" ] || [ "$code" = "201" ] || [ "$code" = "204" ]; then
echo "OK HTTP=$code"
else
echo "FAIL HTTP=$code"
fi
sleep 1
done