feat: 版本轨道按分支彻底分开,自测分支不再共用 feature 轨
每个分支各有一条独立轨道(轨道名即分支名,master/main 沿用历史名 release), 轨道类型 kind 只决定构建号行为:release 上架自增、feature 自测不自增。 - branch_track 映射分支 → 轨道名,新增分支自动建同名轨道 - 迁移:旧的共用 release / feature 轨按分支拆开并复制已用构建号, 拆完没有分支引用的旧共用轨直接删除;无自测分支时保留 feature 轨作模板 - 分支管理页的下拉只改轨道类型(是否自增),不再影响版本号归属 - 打包设置页按分支分块填写版本号 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BJaZ913U5GVdTkYHiRpvDU
This commit is contained in:
@@ -30,8 +30,7 @@ function mockFetch(url) {
|
||||
primary_track: 'release',
|
||||
tracks: {
|
||||
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: {} },
|
||||
dev: { kind: 'feature', app_ver: '2.100.0', build_ver: '2.100.0.0', build_map: {} },
|
||||
},
|
||||
branch_track: { main: 'release', dev: 'dev' },
|
||||
},
|
||||
@@ -193,7 +192,7 @@ describe('ConfigView.vue', () => {
|
||||
expect(fetch.mock.calls.map(c => c[0])).toEqual(['/api/config/apps'])
|
||||
})
|
||||
|
||||
it('每个上架分支与自测轨各自独立展示与保存', async () => {
|
||||
it('每个分支的版本号各自独立展示与保存', async () => {
|
||||
const calls = []
|
||||
fetch.mockImplementation((url, opts) => {
|
||||
if (url === '/api/config/versions' && opts?.method === 'PUT') {
|
||||
@@ -214,17 +213,20 @@ describe('ConfigView.vue', () => {
|
||||
await buildMenu.trigger('click')
|
||||
await wrapper.vm.$nextTick()
|
||||
|
||||
const inputs = wrapper.findAll('input[type="text"]')
|
||||
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
|
||||
// 每个分支一块:main(上架,release 轨)、dev(自测,dev 轨)
|
||||
expect(wrapper.text()).toContain('上架版本号(main)')
|
||||
expect(wrapper.text()).toContain('自测版本号(dev)')
|
||||
|
||||
await inputs[4].setValue('2.101.0')
|
||||
const saveBtn = wrapper.findAll('.btn-primary').find(b => b.text() === '保存自测版本号')
|
||||
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.100.0') // dev 分支 App_Ver
|
||||
|
||||
await inputs[2].setValue('2.101.0')
|
||||
const saveBtn = wrapper.findAll('.btn-primary').find(b => b.text() === '保存 dev 版本号')
|
||||
await saveBtn.trigger('click')
|
||||
await flushPromises()
|
||||
|
||||
expect(calls).toEqual([{ track: 'feature', app_ver: '2.101.0', build_ver: '2.101.0.0' }])
|
||||
expect(calls).toEqual([{ track: 'dev', app_ver: '2.101.0', build_ver: '2.101.0.0' }])
|
||||
})
|
||||
|
||||
it('分支管理可切换版本轨道', async () => {
|
||||
@@ -245,7 +247,7 @@ describe('ConfigView.vue', () => {
|
||||
await wrapper.vm.$nextTick()
|
||||
|
||||
const select = wrapper.find('.config-table select')
|
||||
expect(select.element.value).toBe('release')
|
||||
expect(select.element.value).toBe('release') // main → release 轨(上架)
|
||||
await select.setValue('feature')
|
||||
await flushPromises()
|
||||
|
||||
|
||||
@@ -172,8 +172,8 @@
|
||||
<td><strong>{{ b }}</strong></td>
|
||||
<td>
|
||||
<select :value="branchKind(b)" style="width: auto; padding: 4px 8px;" @change="setBranchTrack(b, $event.target.value)">
|
||||
<option value="release">上架(本分支独立版本号)</option>
|
||||
<option value="feature">自测(共用 feature 版本号)</option>
|
||||
<option value="release">上架(App_Store 打包构建号自增)</option>
|
||||
<option value="feature">自测(构建号不自增)</option>
|
||||
</select>
|
||||
</td>
|
||||
<td class="action-btns">
|
||||
@@ -289,39 +289,30 @@
|
||||
<div v-if="tab === 'build'">
|
||||
<h2>打包设置</h2>
|
||||
<div style="max-width: 500px;">
|
||||
<template v-for="t in releaseTracks" :key="t.name">
|
||||
<h4 class="section-title">上架版本号({{ t.branches.join(' / ') }})</h4>
|
||||
<template v-for="t in branchTracks" :key="t.name">
|
||||
<h4 class="section-title">
|
||||
{{ t.kind === 'release' ? '上架版本号' : '自测版本号' }}({{ t.branches.join(' / ') }})
|
||||
</h4>
|
||||
<div class="form-group">
|
||||
<label>App_Ver(应用版本)</label>
|
||||
<input type="text" v-model="versions[t.name].app_ver" placeholder="2.180.0" @input="onAppVerInput(t.name)">
|
||||
<div style="font-size: 12px; color: #999; margin-top: 4px;">格式:主版本.次版本.修订号。该版本号只用于 {{ t.branches.join(' / ') }} 分支(轨道 {{ t.name }}),与其它分支互不影响。</div>
|
||||
<div style="font-size: 12px; color: #999; margin-top: 4px;">
|
||||
格式:主版本.次版本.修订号。该版本号只用于 {{ t.branches.join(' / ') }} 分支(轨道 {{ t.name }}),与其它分支互不影响。
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Build_Ver(构建号)</label>
|
||||
<input type="text" v-model="versions[t.name].build_ver" placeholder="2.180.0.0">
|
||||
<div style="font-size: 12px; color: #999; margin-top: 4px;">
|
||||
<div v-if="t.kind === 'release'" style="font-size: 12px; color: #999; margin-top: 4px;">
|
||||
四段数字,前三位须与 App_Ver 一致。修改 App_Ver 会自动切换为该版本号已记录的构建号;
|
||||
每个版本号的构建号独立递增,App_Store 打包时自动 +1。一般无需手动修改。
|
||||
</div>
|
||||
</div>
|
||||
<button class="btn btn-primary" style="width: auto; padding: 10px 32px; margin-bottom: 24px;" @click="saveVersions(t.name)">保存 {{ t.branches.join(' / ') }} 版本号</button>
|
||||
</template>
|
||||
|
||||
<template v-if="versions.feature">
|
||||
<h4 class="section-title">自测版本号(feature 分支)</h4>
|
||||
<div class="form-group">
|
||||
<label>App_Ver(应用版本)</label>
|
||||
<input type="text" v-model="versions.feature.app_ver" placeholder="2.180.0" @input="onAppVerInput('feature')">
|
||||
<div style="font-size: 12px; color: #999; margin-top: 4px;">所有自测分支共用,与上架版本号各自独立,互不影响。</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Build_Ver(构建号)</label>
|
||||
<input type="text" v-model="versions.feature.build_ver" placeholder="2.180.0.0">
|
||||
<div style="font-size: 12px; color: #999; margin-top: 4px;">
|
||||
仅供自测,打包时<strong>不会自动递增</strong>,始终使用这里填写的值(默认 .0)。需要区分时请手动修改。
|
||||
<div v-else style="font-size: 12px; color: #999; margin-top: 4px;">
|
||||
四段数字,前三位须与 App_Ver 一致。自测轨打包时<strong>不会自动递增</strong>,
|
||||
始终使用这里填写的值(默认 .0)。需要区分时请手动修改。
|
||||
</div>
|
||||
</div>
|
||||
<button class="btn btn-primary" style="width: auto; padding: 10px 32px; margin-bottom: 24px;" @click="saveVersions('feature')">保存自测版本号</button>
|
||||
<button class="btn btn-primary" style="width: auto; padding: 10px 32px; margin-bottom: 24px;" @click="saveVersions(t.name)">保存 {{ t.branches.join(' / ') }} 版本号</button>
|
||||
</template>
|
||||
|
||||
<template v-if="isAdmin">
|
||||
@@ -658,8 +649,8 @@ const servers = ref({})
|
||||
const branches = ref([])
|
||||
const newBranch = ref('')
|
||||
const buildSettings = ref({})
|
||||
// 版本轨道:每个上架分支(master、develop 等)一条独立轨道,轨道名即分支名;
|
||||
// 自测分支共用固定的 feature 轨。各轨道的版本号互不影响。
|
||||
// 版本轨道:每个分支一条独立轨道,轨道名即分支名(master/main 沿用历史名 release)。
|
||||
// 轨道类型 kind 决定构建号行为:release=上架、App_Store 打包自增;feature=自测、不自增。
|
||||
const versions = ref({}) // 轨道名 -> { app_ver, build_ver }
|
||||
const buildMap = ref({}) // 轨道名 -> { App_Ver: 已用构建号 }
|
||||
const trackKind = ref({}) // 轨道名 -> release | feature
|
||||
@@ -684,14 +675,15 @@ const applyVersions = (data) => {
|
||||
// 分支所属轨道的类型(供分支管理里的下拉框显示)
|
||||
const branchKind = (branch) => trackKind.value[branchTrack.value[branch]] || 'feature'
|
||||
|
||||
// 打包设置里按上架轨道分块展示;多个分支共用一条轨道时只显示一块
|
||||
const releaseTracks = computed(() => {
|
||||
// 打包设置里按分支分块展示版本号;多个分支共用一条轨道时只显示一块
|
||||
const branchTracks = computed(() => {
|
||||
const seen = new Set()
|
||||
return branches.value
|
||||
.map(b => branchTrack.value[b])
|
||||
.filter(name => name && trackKind.value[name] === 'release' && !seen.has(name) && seen.add(name))
|
||||
.filter(name => name && versions.value[name] && !seen.has(name) && seen.add(name))
|
||||
.map(name => ({
|
||||
name,
|
||||
kind: trackKind.value[name] || 'release',
|
||||
branches: branches.value.filter(b => branchTrack.value[b] === name),
|
||||
}))
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user