✨ feat(vscode): 同一天再切发布直接把 main 新提交推进到当天分支,不再另起编号分支

This commit is contained in:
cruldra committed 2026-09-17 17:57:47 +08:00
1 parent 4aae4df1f1
commit 17570749dd
4 files changed
+128 -94

No files matched your search

+30 -22
View File
@@ -11,11 +11,11 @@ import {
indexUnreleasedByMergePr,
listReleaseBranches,
listUnreleasedCommits,
nextReleaseBranch,
normalizeReleasePrefix,
parseAlembicRevision,
parseGiteaMergeSubject,
pickCurrentRelease,
todayReleaseBranch,
} from '../../src/git/release'
const gitEnv = { ...process.env, GIT_CONFIG_NOSYSTEM: '1', GIT_CONFIG_GLOBAL: '/dev/null', GIT_TERMINAL_PROMPT: '0', GIT_AUTHOR_NAME: 't', GIT_AUTHOR_EMAIL: 't@t', GIT_COMMITTER_NAME: 't', GIT_COMMITTER_EMAIL: 't@t' }
@@ -59,19 +59,11 @@ describe('纯函数', () => {
expect(normalizeReleasePrefix(' rel ')).toBe('rel/')
expect(normalizeReleasePrefix('release/')).toBe('release/')
})
it('nextReleaseBranch 当天首次不带序号,再切从 .2 起,取最大序号加一', () => {
expect(nextReleaseBranch('release/', ['main'], AUG31)).toBe('release/2026-08-31')
expect(nextReleaseBranch('release/', ['release/2026-08-30', 'release/2026-08-30.2'], AUG31)).toBe('release/2026-08-31')
expect(nextReleaseBranch('release/', ['release/2026-08-31'], AUG31)).toBe('release/2026-08-31.2')
expect(nextReleaseBranch('release/', ['release/2026-08-31', 'release/2026-08-31.2'], AUG31)).toBe('release/2026-08-31.3')
expect(nextReleaseBranch('release/', ['release/2026-08-31.3'], AUG31)).toBe('release/2026-08-31.4')
expect(nextReleaseBranch('release/', ['release/2026-08-31.x'], AUG31)).toBe('release/2026-08-31')
it('todayReleaseBranch', () => {
expect(todayReleaseBranch('release/', AUG31)).toBe('release/2026-08-31')
})
it('pickCurrentRelease 先按日期再按同日序号,.10 排在 .9 后', () => {
it('pickCurrentRelease 取前缀内字典序最大', () => {
expect(pickCurrentRelease('release/', ['main', 'release/2026-08-01', 'release/2026-08-31', 'hotfix/2027'])).toBe('release/2026-08-31')
expect(pickCurrentRelease('release/', ['release/2026-08-31.2', 'release/2026-08-31'])).toBe('release/2026-08-31.2')
expect(pickCurrentRelease('release/', ['release/2026-08-31.10', 'release/2026-08-31.9'])).toBe('release/2026-08-31.10')
expect(pickCurrentRelease('release/', ['release/2026-08-31.3', 'release/2026-09-01'])).toBe('release/2026-09-01')
expect(pickCurrentRelease('release/', ['main'])).toBeUndefined()
})
it('parseGiteaMergeSubject 认 Gitea 合并说明', () => {
@@ -108,16 +100,33 @@ describe('集成', () => {
expect(s).toMatchObject({ devBranch: 'main', current: undefined, unreleased: 0 })
expect(s.unavailable).toBeUndefined()
})
it('cutRelease 纯远端切分支,不建本地分支;同一天再切得到 .2', async () => {
it('cutRelease 纯远端切分支,不建本地分支;同一天再切 = 快进到 main,不另起分支', async () => {
fx = await setup()
const { repo, origin } = fx
expect(await cutRelease({ cwd: repo, devBranch: 'main', prefix: 'release/', now: AUG31 })).toEqual({ branch: 'release/2026-08-31', count: 0 })
const { repo, origin, peer } = fx
expect(await cutRelease({ cwd: repo, devBranch: 'main', prefix: 'release/', now: AUG31 })).toEqual({ kind: 'created', branch: 'release/2026-08-31', count: 0 })
expect(git(origin, ['rev-parse', 'release/2026-08-31'])).toBe(git(origin, ['rev-parse', 'main']))
expect(() => git(repo, ['rev-parse', '--verify', 'refs/heads/release/2026-08-31'])).toThrow()
expect(await cutRelease({ cwd: repo, devBranch: 'main', prefix: 'release/', now: AUG31 })).toEqual({ branch: 'release/2026-08-31.2', count: 0 })
expect(git(origin, ['rev-parse', 'release/2026-08-31.2'])).toBe(git(origin, ['rev-parse', 'main']))
const s = await getReleaseStatus({ cwd: repo, devBranch: 'main', prefix: 'release/' })
expect(s.current).toBe('release/2026-08-31.2')
expect(await cutRelease({ cwd: repo, devBranch: 'main', prefix: 'release/', now: AUG31 })).toEqual({ kind: 'advanced', branch: 'release/2026-08-31', count: 0 })
commit(peer, 'b.txt', 'b', 'feat b')
git(peer, ['push', 'origin', 'main'])
expect(await cutRelease({ cwd: repo, devBranch: 'main', prefix: 'release/', now: AUG31 })).toEqual({ kind: 'advanced', branch: 'release/2026-08-31', count: 1 })
expect(git(origin, ['rev-parse', 'release/2026-08-31'])).toBe(git(origin, ['rev-parse', 'main']))
expect(git(origin, ['for-each-ref', '--format=%(refname:short)', 'refs/heads/release/'])).toBe('release/2026-08-31')
})
it('同一天再切但发布分支上已有单独摘的提交 → diverged,远端不动', async () => {
fx = await setup()
const { repo, origin, peer } = fx
await cutRelease({ cwd: repo, devBranch: 'main', prefix: 'release/', now: AUG31 })
const fix = commit(peer, 'b.txt', 'b', 'fix b')
commit(peer, 'c.txt', 'c', 'feat c')
git(peer, ['push', 'origin', 'main'])
git(peer, ['fetch', 'origin'])
git(peer, ['checkout', '-b', 'rel', 'origin/release/2026-08-31'])
git(peer, ['cherry-pick', '-x', fix])
git(peer, ['push', 'origin', 'HEAD:release/2026-08-31'])
const before = git(origin, ['rev-parse', 'release/2026-08-31'])
expect(await cutRelease({ cwd: repo, devBranch: 'main', prefix: 'release/', now: AUG31 })).toEqual({ kind: 'diverged', branch: 'release/2026-08-31' })
expect(git(origin, ['rev-parse', 'release/2026-08-31'])).toBe(before)
})
it('unreleased 计数忽略已 cherry-pick 的提交;cherryPickToRelease 推远端并清理 worktree', async () => {
fx = await setup()
@@ -178,13 +187,12 @@ describe('集成', () => {
await expect(cherryPickToRelease({ cwd: fx.repo, branch: 'release/2026-08-31', shas: [fix], worktreePath: fx.repo })).rejects.toThrow(/工作区本身/)
expect(git(fx.repo, ['status', '--porcelain'])).toBe('')
})
it('listReleaseBranches 新→旧,同日序号大的在前', async () => {
it('listReleaseBranches 新→旧', async () => {
fx = await setup()
await cutRelease({ cwd: fx.repo, devBranch: 'main', prefix: 'release/', now: AUG01 })
await cutRelease({ cwd: fx.repo, devBranch: 'main', prefix: 'release/', now: AUG31 })
await cutRelease({ cwd: fx.repo, devBranch: 'main', prefix: 'release/', now: AUG31 })
git(fx.repo, ['fetch', 'origin'])
expect(await listReleaseBranches({ cwd: fx.repo, prefix: 'release/' })).toEqual(['release/2026-08-31.2', 'release/2026-08-31', 'release/2026-08-01'])
expect(await listReleaseBranches({ cwd: fx.repo, prefix: 'release/' })).toEqual(['release/2026-08-31', 'release/2026-08-01'])
})
it('indexUnreleasedByMergePr 用本地合并记录把分支提交对上 PR', async () => {
fx = await setup()