fix: 所有问题都建 Issue、合并失败重试、push 与 PR 事件分流

1. 所有问题都建 Issue(原先只有阻断级才建)
   建 Issue 的判据从 blocking 改为 findings:任何等级的问题都创建/更新 Issue,
   等级体现在标题 [OCR][medium] 与标签 medium 上,阻断项在正文标注
   「(阻断合并)」。低等级问题不再丢失,也不会挡住合并。
   无任何发现时才关闭该分支的 Issue。

2. 合并失败自动重试
   Gitea 在算完 PR 可合并性之前会返回 405 Please try again later,
   原先直接放弃,晋级随机失败。现在对 405/409/5xx 按指数退避重试 4 次;
   权限不足、真实冲突等永久失败立即放弃并往 PR 留言说明。
   PR 已被合并(405 already merged)视为成功,幂等收尾。

3. push 与 PR 事件分流(本次新发现的 bug)
   合并路径原先按「是否找到关联 PR」判断,于是一个残留的 test→prd PR
   会让后续 push 被当成 PR 事件,走错分支并跳过晋级,日志还会给出
   「PR targets prd, which is not a checked branch」这种与实际不符的原因。
   现在按事件类型决定:trigger 以 pull_request 开头才走合并 PR 路径,
   push/manual 一律走晋级分支。关联 PR 仅用于评论归属。

验证:
- 直接 push test → 建出 issue #4([OCR][medium],标签 code-review,medium)
- 合并重试与幂等分支的判定表全部通过
- 事件分流判定表:push/manual → promote,pull_request.* → merge PR
This commit is contained in:
2026-09-21 15:16:06 +08:00
parent a0b15fb2d9
commit 7cd2c85888
4 changed files with 162 additions and 31 deletions
+10 -6
View File
@@ -219,14 +219,18 @@ async function handlePush(payload, cfg) {
}
}
// A push is always handled as a push, never as a pull request. An open pull
// request whose head happens to be this branch is only linked for comment
// routing; letting it decide the merge path would make a leftover promotion
// pull request hijack the branch's own promotion logic.
const scoped = repo.review_scope === "pr";
const pr = scoped ? null : await findOpenPullRequestForRef(cfg, repo, refName, toSha);
if (scoped && !pr) {
const linkedPr = scoped ? null : await findOpenPullRequestForRef(cfg, repo, refName, toSha);
if (scoped && !linkedPr) {
return { queued: 0, reason: "review_scope=pr and no open pull request" };
}
// Base the review on what the push would merge into: the open PR's target
// when there is one, otherwise the managed branch.
const baseRef = pr?.base?.ref || repo.managed_branch;
// Compare against what this branch merges into: its linked pull request's
// target when it has one, otherwise the branch it promotes into.
const baseRef = linkedPr?.base?.ref || repo.managed_branch;
if (findJobBySha(db, repo.id, toSha)) {
return { queued: 0, reason: `commit ${toSha.slice(0, 10)} already queued or running` };
@@ -240,7 +244,7 @@ async function handlePush(payload, cfg) {
baseRef,
fromSha: before,
toSha,
prNumber: pr?.number ?? null,
prNumber: linkedPr?.number ?? null,
});
logger.info(`queued job #${jobId} for ${owner}/${name} ${refName}@${toSha.slice(0, 10)}`);
return { queued: 1, jobId };