- pull_request.synchronize: notify reviewer to re-review after push - pull_request_review COMMENTED: notify PR author of review comments - New templates: review_updated.md, review_comment.md - Idempotency: add review ID to content dedup key - Design doc: docs/design/23-toolchain-pr-lifecycle.md
6.1 KiB
§23 — 工具链事件中枢补全:PR 全生命周期通知
状态:草案,待评审 作者:庞统 日期:2026-06-11 框架:基于 §20 Task Type Architecture + §13 工具链设计
背景
问题
工具链事件中枢(toolchain_routes.py)当前只覆盖了 PR 生命周期中约一半的交互节点。review 驳回后 PR 作者修改代码,没有机制通知 reviewer 重新 review——流程在这里断链。
当前覆盖
| 事件节点 | handler | 模板 | 状态 |
|---|---|---|---|
| PR 创建 → 通知 reviewer | _handle_pull_request (opened) |
review_request.md |
✅ |
| Review 通过 → 通知 PR 作者 | _handle_pull_request_review (APPROVED) |
review_result.md |
✅ |
| Review 驳回 → 通知 PR 作者 | _handle_pull_request_review (REQUEST_CHANGES) |
review_result.md |
✅ |
| Issue 指派 → 通知被指派人 | _handle_issues (assigned) |
issue_assigned.md |
✅ |
| CI 失败评论 → 通知 | _handle_issue_comment ([CI]) |
ci_failure.md |
✅ |
| 部署失败 Issue → 通知 | _handle_issues (opened+"部署失败") |
deploy_failure.md |
✅ |
缺失节点
| # | 事件节点 | Gitea 事件 | 优先级 | 理由 |
|---|---|---|---|---|
| E1 | PR 更新(push 新 commit)→ 通知 reviewer | pull_request.synchronize |
高 | review 驳回→修改→重 review 的关键闭环 |
| E3 | Review 评论(COMMENTED)→ 通知 PR 作者 | pull_request_review (COMMENTED) |
中 | reviewer 讨论提问,作者应知道 |
| E4 | PR 上普通评论 → 通知相关人 | issue_comment (on PR) |
低 | 非关键路径 |
方案
框架对齐
按 §20 Task Type Architecture,新增事件处理遵循:
_EVENT_HANDLERS映射 → 路由到对应 handler 函数- handler 提取变量 →
render_template()渲染模板 _TEMPLATE_MAP注册模板名 →templates/toolchain/下新建模板文件- 通知目标通过 Gitea username →
to_agent_id()映射
新增 Handler 1:_handle_pull_request_synchronize
触发:pull_request 事件 + action=synchronize(PR 分支有新 push)
通知对象:PR 的 reviewer(从 PR 的 requested_reviewers 或最近一次 non-COMMENTED review 的提交者)
实现:
修改 _handle_pull_request 的 action 过滤,从只处理 opened 扩展为同时处理 synchronize:
async def _handle_pull_request(payload: Dict[str, Any]) -> None:
action = payload.get("action", "")
if action == "opened":
await _handle_pr_opened(payload)
elif action == "synchronize":
await _handle_pr_synchronize(payload)
# 其他 action 忽略
新增 _handle_pr_synchronize:
- 从 payload 取 PR 信息(number、title、author、head sha)
- 查询最近一次 review(Gitea API
GET /repos/{owner}/{repo}/pulls/{number}/reviews)取 reviewer - 如果没有 review 记录(首次 push 后 reviewer 还没 review),跳过(opened 事件已经通知过了)
- 渲染
review_updated.md模板,发送 Mail 给 reviewer
关键设计决策:
- 不用
requested_reviewers(可能为空),用最近 review 的提交者 - 只在有 review 历史时才通知(避免 opened + synchronize 重复通知)
- Mail from 用
system
Handler 2:PR 合并通知 — 已删除
司马懿 review 指出与 §22 CD 成功通知重叠。CD 成功通知已隐含合并信息,无需单独发 merged 通知。
新增 Handler 3:review COMMENTED 处理
触发:pull_request_review 事件 + state=COMMENTED
通知对象:PR 作者(不是 reviewer)
实现:
修改现有 _handle_pull_request_review,当前逻辑是"非 COMMENTED 才通知",改为 COMMENTED 也通知,但用不同模板:
# 现有逻辑:非 COMMENTED 通知 PR 作者
if state in ("APPROVED", "REQUEST_CHANGES"):
template_name = "review_result"
elif state == "COMMENTED":
template_name = "review_comment"
else:
return # PENDING 等忽略
新增模板
| 模板文件 | 变量 | 说明 |
|---|---|---|
review_updated.md |
repo, pr_number, pr_title, pr_author, branch, new_sha, reviewer | PR 有新 commit,请重新 review |
pr_merged.md |
||
review_comment.md |
repo, pr_number, pr_title, reviewer, comment_body | reviewer 提交了评论 |
_EVENT_HANDLERS 无需改动
synchronize 和 closed 都是 pull_request 事件的 action 子类型,已映射到 _handle_pull_request。COMMENTED 是 pull_request_review 的 state 子类型,已映射到 _handle_pull_request_review。
所以 _EVENT_HANDLERS 不需要修改,只需修改 handler 内部的 action/state 分发逻辑。
不做的事
| 项 | 理由 |
|---|---|
| E4 PR 上普通评论通知 | 低优,非关键路径,后续按需加 |
| Issue 关闭通知 | 低优,关怀性质 |
reviewer 从 requested_reviewers 取 |
不可靠(可能为空),用最近 review 记录更稳定 |
改动范围
| 文件 | 改动 |
|---|---|
src/api/toolchain_routes.py |
修改 _handle_pull_request(扩展 action 分发)+ 新增 _handle_pr_synchronize + 修改 _handle_pull_request_review(支持 COMMENTED) |
templates/toolchain/review_updated.md |
新增 |
templates/toolchain/pr_merged.md |
|
templates/toolchain/review_comment.md |
新增 |
src/daemon/toolchain_templates.py |
_TEMPLATE_MAP 新增 3 个映射 |
docs/design/23-toolchain-pr-lifecycle.md |
本文档 |
验证计划
在 sanguo/moziplus-v2 测试仓库上 E2E 验证:
- synchronize:创建 PR → review 驳回 → push 新 commit → 验证 reviewer 收到"请重新 review" Mail
2. merged:已删除 - COMMENTED:review 提交纯评论 → 验证 PR 作者收到通知
风险评估
- 风险等级:低。新增事件处理,不修改现有 handler 逻辑
- 幂等性:复用现有
_is_duplicate机制 - 性能:synchronize handler 有一次 Gitea API 调用(查 review 历史),频率低(只在 push 后触发)