mirror of
https://gitcode.com/JianFeeeee/ModelRouter.git
synced 2026-11-07 09:47:23 +00:00
按发布纪律回流。**注意这是内容对齐而非 merge**,理由与依据:
1. 纪律禁止 merge 回主干,因为 merge 会把发布分支的**版本号变更**带进 main。
本项目版本号**只由 `git describe --tags` 推导**(Makefile VERSION),
仓库里没有任何文件存放版本号 ⇒ 回流不存在版本污染风险。
2. 逐项核对确认 **main 是 release 的内容严格子集**:
- `main` 独有的**文件**:0 个;
- `internal/lua/plugins.go` / `internal/core/kernel_actions.go` 等内核文件
main 独有行数:0;
- `deploy.sh` 那 14 行只是 emoji 清理(release 刻意去掉了 emoji);
- `channels.lua` 那 333 行是**旧版内容**(旧 exports 表、旧模型名单)。
- main 独有的 9 个提交按 patch-id **全部已在 release 中等效存在**
(`git cherry` 逐条列出均为 `-`,即已合入)。
3. 故回流 = 把 release 的内容带到 main,等价于"只捡拾修复、不带版本号",
且不会丢任何 main 独有的修复。
本次带回 v2.0.12 的全部内容(37 个提交):
- 源串行 + 按模型节流(照 model-gate)
- 已失效模型存储 + 远端目录闸门
- 余额分档选号
- 模型能力元数据(models.dev,isFree 权威判定)
- **凭据续期修复**(此前恒报 ok:true 却一个请求都不发)
- 通用件 TTL 缓存 + 串行锁;account_test/account_adopt/account_delete 修正
- 内核级:出站授权持久化重启后不生效、`__llmsproxy_plugin_dir` ground truth
校验:`git diff release/v2.0.x` = 0 行;`go build -tags luajit ./...` 通过。
72 lines
2.6 KiB
Bash
Executable File
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
|