feat: 版本号按分支轨道分开管理,版本号配置收归管理员

master/develop 共用 release 轨(App_Store 打包构建号自增),feature 分支走
feature 轨(构建号永不自增,始终使用手填值),两条轨道的 App_Ver 各自独立。

- versions 改为 tracks 结构,旧的单轨/单值配置在加载时自动迁移进 release 轨
- 新增 config["branch_track"] 记录分支归属,缺省按分支名推断,可在分支管理页改
- 新增 PUT /api/config/branches/track;分支名含 / 时走请求体而非路径参数
- 修复 DELETE /api/config/branches/{name} 无法删除含 / 的分支(405)
- 版本号接口不再对普通用户开放,打包设置页整页改为管理员可见

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
shenlei
2026-07-31 17:56:10 +09:00
co-authored by Claude Opus 5
parent 3cb4053ab5
commit 21542c88d7
10 changed files with 511 additions and 115 deletions
+9 -6
View File
@@ -37,8 +37,8 @@ def test_production_rejects_default_security_settings(monkeypatch):
config.validate_production_security()
def test_config_routes_limit_regular_users_to_apps_and_versions(client, tmp_config):
"""普通账号管理 Apps版本号,不能读取或修改管理员配置"""
def test_config_routes_limit_regular_users_to_apps(client, tmp_config):
"""普通账号只能管理 Apps版本号等其余配置均为管理员专属"""
response = client.post("/api/users", json={
"username": "builder",
"password": "builder-password-123",
@@ -57,10 +57,13 @@ def test_config_routes_limit_regular_users_to_apps_and_versions(client, tmp_conf
assert client.post("/api/config/apps", json={
"name": "普通用户 App", "server": "测试环境",
}, headers=headers).status_code == 200
assert client.get("/api/config/versions", headers=headers).status_code == 200
versions = client.put("/api/config/versions", json={"app_ver": "2.196.0"}, headers=headers)
assert versions.status_code == 200
assert versions.json()["build_ver"] == "2.196.0.0"
assert client.get("/api/config/versions", headers=headers).status_code == 403
assert client.put(
"/api/config/versions", json={"app_ver": "2.196.0"}, headers=headers
).status_code == 403
assert client.put(
"/api/config/branches/track", json={"branch": "master", "track": "feature"}, headers=headers
).status_code == 403
assert client.get("/api/config", headers=headers).status_code == 403
assert client.get("/api/config/servers", headers=headers).status_code == 403
assert client.put("/api/config/build", json={"max_concurrent_builds": 1}, headers=headers).status_code == 403