diff --git a/CLAUDE.md b/CLAUDE.md index c174624..f6aeaad 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -26,7 +26,7 @@ FastAPI + Vue 3 iOS app auto-packaging service. Supports Ad_Hoc and App_Store bu - `backend/config.py` — loads .env, defines all config constants - `frontend/src/views/` — BuildView, HistoryView, ConfigView - `config.json` — runtime config (apps, schemes, servers, upload, branches, versions) managed via web UI -- Versions are per-track: each release branch (master, develop, …) has its own track named after the branch (build number auto-increments on App_Store), and all self-test branches share the `feature` track (never increments); each branch's track name lives in `config["branch_track"]`, track records in `config["versions"]["tracks"]` carry `kind` (release/feature) +- Versions are per-track: each release branch has its own track (master/main keeps the historical `release` track, others are named after the branch, e.g. `develop`; build number auto-increments on App_Store), and all self-test branches share the `feature` track (never increments); each branch's track name lives in `config["branch_track"]`, track records in `config["versions"]["tracks"]` carry `kind` (release/feature) ## Conventions diff --git a/README.md b/README.md index 365c33a..b7fa9cb 100644 --- a/README.md +++ b/README.md @@ -197,14 +197,15 @@ GIT_PASSWORD=<仅 read_repository 权限的 Personal Access Token> | 轨道 | 适用分支 | 构建号行为 | |------|----------|-----------| -| 上架轨(轨道名即分支名,如 `master`、`develop`) | 每个上架分支各一条,版本号彼此独立 | App_Store 打包时按当前 App_Ver 自动 +1 | +| `release`(上架) | master / main | App_Store 打包时按当前 App_Ver 自动 +1 | +| `develop` 等以分支名命名的上架轨 | develop、release-*、hotfix-* 等其它上架分支,每个分支一条 | 同上,与 `release` 轨互不影响 | | `feature`(自测) | feature/* 等其他分支,共用一条 | 永不自增,始终使用配置页填写的值(默认 `.0`) | -- 分支归属默认按名字推断(master/main/develop/dev/release-*/hotfix-* → 自己的上架轨,其余 → feature),可在「分支管理」页逐个改;改成「上架」即为该分支新建一条以分支名命名的轨道。 +- 分支归属默认按名字推断(master/main → `release` 轨,develop/dev/release-*/hotfix-* → 以分支名命名的轨,其余 → `feature`),可在「分支管理」页逐个改;改成「上架」即为该分支建一条独立轨道。 - 「打包设置」页按上架分支分块填写版本号,最后一块是共用的自测版本号。 - 每条轨道内的构建号按 App_Ver 独立记录(`build_map`),回退到打过包的旧版本号时会从它自己的最大值继续,不会与 App Store Connect 上已传构建号冲突。 - App Store 的构建号唯一性按 App_Ver 全局判定,因此两个上架分支若临时用了同一个 App_Ver,递增时会跨轨道取最大值 +1,避免重号被拒。 -- 旧配置(master/develop 共用的 `release` 轨)首次启动时自动拆分为各分支自己的轨道,已用构建号原样复制过去。 +- 旧配置(master/develop 共用的 `release` 轨)首次启动时自动拆开:master 留在 `release` 轨,develop 新建 `develop` 轨并复制一份已用构建号。 ### 服务端自动化资源 diff --git a/backend/routers/config.py b/backend/routers/config.py index e0e2a49..3d87aba 100644 --- a/backend/routers/config.py +++ b/backend/routers/config.py @@ -93,16 +93,18 @@ DEFAULT_SERVERS = { DEFAULT_APP_VER = "2.180.0" -# 版本轨道:每个上架分支(master / develop / release-* 等)各有一条独立轨道, -# 轨道名即分支名,App_Store 打包时构建号自增;所有自测分支共用一条 feature 轨, -# 构建号永不自增。各轨道的 App_Ver 互不影响。 +# 版本轨道:每个上架分支各有一条独立轨道,App_Store 打包时构建号自增; +# 所有自测分支共用一条 feature 轨,构建号永不自增。各轨道的 App_Ver 互不影响。 +# 轨道名:master/main 沿用历史名称 release,其余上架分支以分支名命名(develop、hotfix-x…)。 KIND_RELEASE = "release" KIND_FEATURE = "feature" +TRACK_RELEASE = "release" # master/main 的上架轨(沿用旧名,历史构建号原地保留) TRACK_FEATURE = "feature" # 自测轨的固定轨道名 -LEGACY_RELEASE_TRACK = "release" # 旧版 master/develop 共用的上架轨,迁移时按分支拆开 +FIXED_TRACKS = (TRACK_RELEASE, TRACK_FEATURE) # 按名字推断轨道的默认规则;config["branch_track"] 中的显式配置优先。 -RELEASE_BRANCH_NAMES = {"master", "main", "develop", "dev"} +MASTER_BRANCH_NAMES = {"master", "main"} +RELEASE_BRANCH_NAMES = MASTER_BRANCH_NAMES | {"develop", "dev"} RELEASE_BRANCH_PREFIXES = ("release/", "release-", "hotfix/", "hotfix-") @@ -113,8 +115,10 @@ def _is_release_branch(branch: str) -> bool: def _release_track_name(branch: str) -> str: - """上架轨道名即分支名;与固定的自测轨重名时加前缀避让。""" - return f"release:{branch}" if branch == TRACK_FEATURE else branch + """上架分支的轨道名:master/main 为 release,其余即分支名(与固定轨重名时避让)。""" + if (branch or "").strip().lower() in MASTER_BRANCH_NAMES: + return TRACK_RELEASE + return f"release:{branch}" if branch in FIXED_TRACKS else branch def _default_track_for_branch(branch: str) -> str: @@ -173,7 +177,8 @@ def _ensure_versions(config: dict) -> bool: """确保 versions 为「每个上架分支一条轨 + 一条 feature 轨」结构,并迁移旧配置。 旧式单轨 ``{"app_ver": ..., "build_map": ...}`` 和旧的 master/develop 共用 - ``release`` 轨,都会按上架分支拆成各自独立的轨道,并复制已用构建号, + ``release`` 轨,都会按上架分支拆开:master/main 留在 release 轨(历史构建号原地 + 保留),develop 等其它上架分支新建以分支名命名的轨道,并复制一份已用构建号, 使拆分后每个分支都从原来的构建号继续递增。 """ versions = config.get("versions") @@ -191,16 +196,15 @@ def _ensure_versions(config: dict) -> bool: versions["tracks"] = tracks changed = True else: - # 迁移后的轨道都带 kind;没有 kind 的 release 轨即旧的共用上架轨 - old = tracks.get(LEGACY_RELEASE_TRACK) - if isinstance(old, dict) and "kind" not in old: - build_map = old.get("build_map") + # 迁移后的轨道都带 kind;没有 kind 的 release 轨即旧的 master/develop 共用轨, + # 它继续作为 master/main 的轨道,同时作为其它上架分支新轨的初值。 + shared = tracks.get(TRACK_RELEASE) + if isinstance(shared, dict) and "kind" not in shared: + build_map = shared.get("build_map") legacy = { - "app_ver": old.get("app_ver") or DEFAULT_APP_VER, + "app_ver": shared.get("app_ver") or DEFAULT_APP_VER, "build_map": build_map if isinstance(build_map, dict) else {}, } - tracks.pop(LEGACY_RELEASE_TRACK) - changed = True feature = tracks.get(TRACK_FEATURE) if not isinstance(feature, dict): @@ -230,8 +234,8 @@ def _ensure_versions(config: dict) -> bool: changed = True for branch in config.get("branches", []) or []: name = branch_track.get(branch) - if name == LEGACY_RELEASE_TRACK and LEGACY_RELEASE_TRACK not in tracks: - # 旧的共用上架轨 → 该分支自己的轨 + if name == TRACK_RELEASE and legacy is not None: + # 旧的共用上架轨 → master/main 留在 release 轨,其余分支拆到自己的轨 name = _release_track_name(branch) if not isinstance(name, str) or not name: name = _default_track_for_branch(branch) @@ -263,8 +267,6 @@ def get_track_name(config: dict, branch: str) -> str: tracks = (config.get("versions") or {}).get("tracks") or {} if isinstance(name, str) and name in tracks: return name - if name == LEGACY_RELEASE_TRACK: # 尚未迁移的旧配置 - return _release_track_name(branch) return _default_track_for_branch(branch) diff --git a/config.example.json b/config.example.json index cc3e3ea..4509d0b 100644 --- a/config.example.json +++ b/config.example.json @@ -74,10 +74,10 @@ }, "versions": { "tracks": { - "master": { "kind": "release", "app_ver": "2.180.0", "build_map": {} }, + "release": { "kind": "release", "app_ver": "2.180.0", "build_map": {} }, "develop": { "kind": "release", "app_ver": "2.180.0", "build_map": {} }, "feature": { "kind": "feature", "app_ver": "2.180.0", "build_map": {} } } }, - "branch_track": { "master": "master", "develop": "develop" } + "branch_track": { "master": "release", "develop": "develop" } } diff --git a/frontend/src/__tests__/ConfigView.test.js b/frontend/src/__tests__/ConfigView.test.js index a0decf9..0376f43 100644 --- a/frontend/src/__tests__/ConfigView.test.js +++ b/frontend/src/__tests__/ConfigView.test.js @@ -27,13 +27,13 @@ function mockFetch(url) { '/api/config/versions': { app_ver: '2.195.0', build_ver: '2.195.0.0', - primary_track: 'main', + primary_track: 'release', tracks: { - main: { kind: 'release', app_ver: '2.195.0', build_ver: '2.195.0.0', build_map: {} }, + release: { kind: 'release', app_ver: '2.195.0', build_ver: '2.195.0.0', build_map: {} }, dev: { kind: 'release', app_ver: '2.196.0', build_ver: '2.196.0.0', build_map: {} }, feature: { kind: 'feature', app_ver: '2.100.0', build_ver: '2.100.0.0', build_map: {} }, }, - branch_track: { main: 'main', dev: 'dev' }, + branch_track: { main: 'release', dev: 'dev' }, }, '/api/config': { apps: {}, schemes: {}, branches: ['main'] }, } @@ -215,8 +215,8 @@ describe('ConfigView.vue', () => { await wrapper.vm.$nextTick() const inputs = wrapper.findAll('input[type="text"]') - expect(inputs[0].element.value).toBe('2.195.0') // main(上架)App_Ver - expect(inputs[2].element.value).toBe('2.196.0') // dev(上架)App_Ver + expect(inputs[0].element.value).toBe('2.195.0') // main 分支(release 轨)App_Ver + expect(inputs[2].element.value).toBe('2.196.0') // dev 分支(dev 轨)App_Ver expect(inputs[4].element.value).toBe('2.100.0') // feature App_Ver await inputs[4].setValue('2.101.0') diff --git a/frontend/src/views/ConfigView.vue b/frontend/src/views/ConfigView.vue index 94d4141..0ed1de4 100644 --- a/frontend/src/views/ConfigView.vue +++ b/frontend/src/views/ConfigView.vue @@ -294,7 +294,7 @@
-
格式:主版本.次版本.修订号。该版本号只用于 {{ t.branches.join(' / ') }} 分支,与其它分支互不影响。
+
格式:主版本.次版本.修订号。该版本号只用于 {{ t.branches.join(' / ') }} 分支(轨道 {{ t.name }}),与其它分支互不影响。
@@ -304,7 +304,7 @@ 每个版本号的构建号独立递增,App_Store 打包时自动 +1。一般无需手动修改。
- +