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
+20 -9
View File
@@ -601,29 +601,40 @@ async def generate_config(task_id: str, task, build_dir: Path) -> dict:
"""生成打包配置"""
await log_streamer.emit_step(task_id, "生成配置")
from ..routers.config import load_config, _config_lock
from ..routers.config import (
load_config, _config_lock, get_track, get_track_name, track_build_ver,
TRACK_RELEASE, _new_track,
)
config = load_config()
apps = config.get("apps", {})
schemes = config.get("schemes", {})
versions = config.get("versions", {})
app = apps.get(task.app_id, {})
scheme = schemes.get(task.scheme_id, {})
# 版本号由当前服务配置统一管理,不读取分支源码中的手动打包脚本。
app_ver = versions.get("app_ver", "2.180.0")
# 按分支所属轨道取版本号:master/develop 走 release 轨(上架用),feature 走 feature 轨(自测用),
# 两条轨道的 App_Ver 各自独立。
track_name = get_track_name(config, task.branch)
track = get_track(config, track_name)
app_ver = track.get("app_ver") or "2.180.0"
# 构建号按版本号独立记录:build_map[app_ver] 为该版本号已用到的最大第四位。
build_map = versions.get("build_map", {}) or {}
build_ver = f"{app_ver}.{int(build_map.get(app_ver, 0))}"
build_ver = track_build_ver(track)
await log_streamer.emit(
task_id,
f"版本轨道: {track_name}{'上架,App_Store 打包自增' if track_name == TRACK_RELEASE else '自测,构建号不自增'}",
)
# App_Store 打包,在该版本号自己的构建号上 +1(回退到旧版本号也从它自己的最大值继续)
if task.build_type == "App_Store":
# release 轨的 App_Store 打包,在该版本号自己的构建号上 +1
# (回退到旧版本号也从它自己的最大值继续);feature 轨始终使用手动设定的构建号。
if track_name == TRACK_RELEASE and task.build_type == "App_Store":
async with _config_lock:
config = load_config()
versions = config.setdefault("versions", {"app_ver": app_ver, "build_map": {}})
build_map = versions.setdefault("build_map", {})
tracks = config.setdefault("versions", {}).setdefault("tracks", {})
track = tracks.setdefault(track_name, _new_track(app_ver))
build_map = track.setdefault("build_map", {})
n = int(build_map.get(app_ver, 0)) + 1
build_map[app_ver] = n
build_ver = f"{app_ver}.{n}"