Files
iOSBuildServer/tests/test_api_config.py
T
shenleiandClaude Opus 4.8 91e9b027e8 feat: 构建号按版本号(App_Ver)独立记录,避免回退旧版本号被 App Store 拒
将 versions.build_ver 单值改为 build_map(每个 App_Ver 独立记录已用到的最大
构建号)。App Store 的构建号唯一性按 MARKETING_VERSION 分别计算,改为单一全局
计数器时回退到打过包的旧版本号会重复(如 2.195.0 已到 .5,切 2.196.0 后再回退,
重置/沿用全局计数都会 < .5 而被拒)。

- config.py: 新增 _ensure_versions 迁移旧 build_ver → build_map;PUT /versions
  不再重置构建号,改版本号仅切换当前 App_Ver,并支持可选手动设置 build_ver;
  GET /versions 返回 build_map 及当前版本号对应的 build_ver
- build_service.py: App_Store 打包时在 build_map[app_ver] 自身上 +1 并回写
- ConfigView.vue: 打包设置页显示可编辑的 Build_Ver,修改 App_Ver 时自动切换为
  该版本号已记录的构建号
- 迁移 config.json;更新前后端相关测试

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-29 16:49:14 +09:00

204 lines
6.7 KiB
Python

"""配置管理接口测试"""
import json
def test_get_full_config(client, tmp_config):
resp = client.get("/api/config")
assert resp.status_code == 200
data = resp.json()
assert "apps" in data
assert "schemes" in data
assert "branches" in data
# ---- Apps ----
def test_get_apps(client, tmp_config):
resp = client.get("/api/config/apps")
assert resp.status_code == 200
assert "1" in resp.json()
def test_create_app(client, tmp_config):
resp = client.post("/api/config/apps", json={
"name": "新App", "server": "测试环境", "AppGuid": "new-guid",
})
assert resp.status_code == 200
assert resp.json()["id"] == "100"
# 验证已创建
apps = client.get("/api/config/apps").json()
assert "100" in apps
assert apps["100"]["name"] == "新App"
def test_create_app_uses_environment_prefix_and_dictionary_exception(client, tmp_config):
official = client.post("/api/config/apps", json={"name": "正式 App", "server": "正式环境"})
dictionary = client.post("/api/config/apps", json={"name": "英汉大词典", "server": "正式环境"})
assert official.status_code == 200
assert official.json()["id"] == "200"
assert dictionary.status_code == 200
assert dictionary.json()["id"] == "100"
def test_create_app_rejects_unknown_environment_id_rule(client, tmp_config):
resp = client.post("/api/config/apps", json={"name": "新 App", "server": "未知环境"})
assert resp.status_code == 400
assert "ID 规则" in resp.json()["detail"]
def test_update_app(client, tmp_config):
resp = client.put("/api/config/apps/1", json={"name": "改名App", "AppGuid": "test-guid"})
assert resp.status_code == 200
assert client.get("/api/config/apps").json()["1"]["name"] == "改名App"
def test_delete_app(client, tmp_config):
resp = client.delete("/api/config/apps/1")
assert resp.status_code == 200
assert "1" not in client.get("/api/config/apps").json()
def test_update_nonexistent_app(client, tmp_config):
resp = client.put("/api/config/apps/999", json={"name": "x"})
assert resp.status_code == 404
# ---- Schemes ----
def test_get_schemes(client, tmp_config):
resp = client.get("/api/config/schemes")
assert resp.status_code == 200
assert "1" in resp.json()
def test_create_scheme(client, tmp_config):
resp = client.post("/api/config/schemes", json={"name": "newScheme", "ossFloder": "new"})
assert resp.status_code == 200
assert resp.json()["id"] == "2"
def test_delete_scheme(client, tmp_config):
resp = client.delete("/api/config/schemes/1")
assert resp.status_code == 200
# ---- Branches ----
def test_get_branches(client, tmp_config):
resp = client.get("/api/config/branches")
assert resp.status_code == 200
branches = resp.json()
assert "main" in branches
assert "dev" in branches
def test_add_branch(client, tmp_config):
resp = client.post("/api/config/branches", json={"name": "release/1.0"})
assert resp.status_code == 200
branches = client.get("/api/config/branches").json()
assert "release/1.0" in branches
def test_add_duplicate_branch(client, tmp_config):
resp = client.post("/api/config/branches", json={"name": "main"})
assert resp.status_code == 400
def test_add_empty_branch(client, tmp_config):
resp = client.post("/api/config/branches", json={"name": ""})
assert resp.status_code == 400
def test_delete_branch(client, tmp_config):
resp = client.delete("/api/config/branches/dev")
assert resp.status_code == 200
branches = client.get("/api/config/branches").json()
assert "dev" not in branches
def test_delete_nonexistent_branch(client, tmp_config):
resp = client.delete("/api/config/branches/notexist")
assert resp.status_code == 404
# ---- Servers ----
def test_get_servers(client, tmp_config):
resp = client.get("/api/config/servers")
assert resp.status_code == 200
assert "测试环境" in resp.json()
def test_create_server(client, tmp_config):
resp = client.post("/api/config/servers", json={
"name": "新环境",
"api": "https://new.api.com",
"assDom": "applinks:new.com",
"universalLink": "https://new.com",
})
assert resp.status_code == 200
servers = client.get("/api/config/servers").json()
assert servers["新环境"]["app_id_prefix"] == 3
client.delete("/api/config/servers/新环境")
second = client.post("/api/config/servers", json={"name": "第二环境", "api": "https://second.api.com"})
assert second.status_code == 200
assert client.get("/api/config/servers").json()["第二环境"]["app_id_prefix"] == 4
def test_delete_server_in_use(client, tmp_config):
# 测试环境被 App 1 使用,应该删除失败
resp = client.delete("/api/config/servers/测试环境")
assert resp.status_code == 400
# ---- Build Settings ----
def test_get_build_settings(client, tmp_config):
resp = client.get("/api/config/build")
assert resp.status_code == 200
data = resp.json()
assert "max_concurrent_builds" in data
assert "build_dir_retention_hours" in data
def test_update_build_settings(client, tmp_config):
resp = client.put("/api/config/build", json={"max_concurrent_builds": 4})
assert resp.status_code == 200
assert client.get("/api/config/build").json()["max_concurrent_builds"] == 4
# ---- Versions ----
def test_update_versions_keeps_per_version_build_number(client, tmp_config):
# 首次设置某版本号,构建号从 .0 起(尚未打包)
resp = client.put("/api/config/versions", json={"app_ver": "2.196.0"})
assert resp.status_code == 200
assert resp.json()["app_ver"] == "2.196.0"
assert resp.json()["build_ver"] == "2.196.0.0"
assert client.get("/api/config/versions").json()["build_ver"] == "2.196.0.0"
def test_update_versions_does_not_reset_used_build_number(client, tmp_config):
# 模拟 2.195.0 已打到 .5、并切到 2.196.0 后,再回退到 2.195.0
import json
with open(tmp_config, "r", encoding="utf-8") as f:
cfg = json.load(f)
cfg["versions"] = {"app_ver": "2.196.0", "build_map": {"2.195.0": 5, "2.196.0": 3}}
with open(tmp_config, "w", encoding="utf-8") as f:
json.dump(cfg, f)
resp = client.put("/api/config/versions", json={"app_ver": "2.195.0"})
assert resp.status_code == 200
# 回退到旧版本号时,构建号保留其自身已用到的最大值,不被重置
assert resp.json()["build_ver"] == "2.195.0.5"
assert client.get("/api/config/versions").json()["build_ver"] == "2.195.0.5"
def test_update_versions_rejects_invalid_app_version(client, tmp_config):
resp = client.put("/api/config/versions", json={"app_ver": "2.196"})
assert resp.status_code == 400
assert "App_Ver" in resp.json()["detail"]