✨ feat(vscode): 发布摘提交认出 GitHub 合并提交和 squash 提交的 PR 号
This commit is contained in:
1 parent
7351b6247f
commit
5a1c0e20a2
3 files changed
+73
-22
No files matched your search
+38
-16
@@ -26,7 +26,7 @@ export interface UnreleasedCommit {
|
||||
author: string
|
||||
date: string
|
||||
body: string
|
||||
/** Gitea 查到的所属 PR;没有就不分组。 */
|
||||
/** 从合并记录认出的所属 PR;没有就不分组。 */
|
||||
pr?: number
|
||||
prTitle?: string
|
||||
/** 带 alembic 迁移文件时才有;blocked 有值就不能摘。 */
|
||||
@@ -114,12 +114,28 @@ export function pickCurrentRelease(prefix: string, remoteBranches: string[]): st
|
||||
return remoteBranches.filter(b => b.startsWith(prefix)).sort().at(-1)
|
||||
}
|
||||
|
||||
/** Gitea 默认合并说明:Merge pull request '标题' (#260) from … */
|
||||
export function parseGiteaMergeSubject(subject: string): { number: number, title: string } | undefined {
|
||||
const m = /^Merge pull request '(.+)' \(#(\d+)\)/.exec(subject)
|
||||
if (!m)
|
||||
return undefined
|
||||
return { title: m[1], number: Number(m[2]) }
|
||||
/**
|
||||
* 从合并进开发分支的提交说明里认出 PR 号和标题,认不出返回 `undefined`。
|
||||
*
|
||||
* 认三种默认说明:Gitea 合并提交 `Merge pull request '标题' (#260) from …`;GitHub 合并提交 `Merge pull request #260 from owner/分支`,
|
||||
* 标题在说明正文第一行,正文为空就用来源分支;squash 合并的 `标题 (#260)`,两家都是这个格式。
|
||||
*
|
||||
* @param subject 提交说明的标题行
|
||||
* @param body 提交说明正文(标题行之后的部分),只有 GitHub 合并提交用得上
|
||||
*/
|
||||
export function parseMergeSubject(subject: string, body = ''): { number: number, title: string } | undefined {
|
||||
const gitea = /^Merge pull request '(.+)' \(#(\d+)\)/.exec(subject)
|
||||
if (gitea)
|
||||
return { title: gitea[1], number: Number(gitea[2]) }
|
||||
const github = /^Merge pull request #(\d+) from (\S+)/.exec(subject)
|
||||
if (github) {
|
||||
const title = body.split('\n').map(line => line.trim()).find(Boolean)
|
||||
return { title: title ?? github[2], number: Number(github[1]) }
|
||||
}
|
||||
const squash = /^(.+) \(#(\d+)\)$/.exec(subject)
|
||||
if (squash)
|
||||
return { title: squash[1], number: Number(squash[2]) }
|
||||
return undefined
|
||||
}
|
||||
|
||||
/** 同 PR 收一组(新→旧首次出现顺序)。pr 号来自合并记录,不是扫提交说明。 */
|
||||
@@ -202,29 +218,27 @@ export async function listReleaseBranches(o: { cwd: string, prefix: string }): P
|
||||
return names.filter(b => b.startsWith(o.prefix)).sort().reverse()
|
||||
}
|
||||
|
||||
/** 用本地 merge 记录把未发布 sha 对上 PR。不打 Gitea。 */
|
||||
/** 用本地的合并记录把未发布提交对上 PR:合并提交带进来的提交归那个 PR,squash 合并的提交看它自己的说明;不调代码托管接口。 */
|
||||
export async function indexUnreleasedByMergePr(o: {
|
||||
cwd: string
|
||||
current: string
|
||||
devBranch: string
|
||||
shas: readonly string[]
|
||||
commits: readonly { sha: string, subject: string }[]
|
||||
}): Promise<Map<string, { number: number, title: string }>> {
|
||||
const needed = new Set(o.shas)
|
||||
const needed = new Set(o.commits.map(c => c.sha))
|
||||
const out = new Map<string, { number: number, title: string }>()
|
||||
if (needed.size === 0)
|
||||
return out
|
||||
const raw = await mustGit(
|
||||
o.cwd,
|
||||
['log', '--right-only', '--cherry-pick', '--merges', '--format=%H%x00%s', unreleasedRange(o.current, o.devBranch)],
|
||||
['log', '--right-only', '--cherry-pick', '--merges', '--format=%H%x00%s%x00%b%x1e', unreleasedRange(o.current, o.devBranch)],
|
||||
'读取合并记录失败',
|
||||
)
|
||||
if (!raw)
|
||||
return out
|
||||
for (const line of raw.split('\n')) {
|
||||
const [sha, subject] = line.split('\0')
|
||||
for (const chunk of raw ? raw.split('\x1E') : []) {
|
||||
const [sha, subject, body = ''] = chunk.replace(/^\n+/, '').split('\0')
|
||||
if (!sha || !subject)
|
||||
continue
|
||||
const parsed = parseGiteaMergeSubject(subject)
|
||||
const parsed = parseMergeSubject(subject, body)
|
||||
if (!parsed)
|
||||
continue
|
||||
const members = await mustGit(
|
||||
@@ -239,6 +253,14 @@ export async function indexUnreleasedByMergePr(o: {
|
||||
if (out.size === needed.size)
|
||||
return out
|
||||
}
|
||||
// squash 合并没有合并提交,PR 号只在提交自己的说明里。
|
||||
for (const c of o.commits) {
|
||||
if (out.has(c.sha))
|
||||
continue
|
||||
const parsed = parseMergeSubject(c.subject)
|
||||
if (parsed)
|
||||
out.set(c.sha, parsed)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user