diff --git a/src/api/toolchain_routes.py b/src/api/toolchain_routes.py index 4aa467c..c6a09dd 100644 --- a/src/api/toolchain_routes.py +++ b/src/api/toolchain_routes.py @@ -265,7 +265,8 @@ async def _handle_pull_request(payload: Dict[str, Any]) -> None: await _handle_pr_opened(payload) elif action == "synchronize": await _handle_pr_synchronize(payload) - # 其他 action 忽略 + elif action == "closed": + await _handle_pr_closed(payload) async def _handle_pr_opened(payload: Dict[str, Any]) -> None: @@ -434,9 +435,9 @@ async def _handle_pr_synchronize(payload: Dict[str, Any]) -> None: # 查询最近 review 的提交者 reviewer = await _fetch_latest_reviewer(repo, pr_number) if not reviewer: - # 没有 review 历史,跳过(opened 事件已经通知过) - logger.debug("No review history for PR #%s, skipping synchronize notification", pr_number) - return + # 没有已有 review 历史,fallback 到默认 reviewer + reviewer = "simayi-challenger" + logger.info("No review history for PR #%s, using default reviewer %s", pr_number, reviewer) text = render_template("review_updated", { "repo": repo, @@ -451,6 +452,38 @@ async def _handle_pr_synchronize(payload: Dict[str, Any]) -> None: _send_mail(reviewer, title, text) +async def _handle_pr_closed(payload: Dict[str, Any]) -> None: + """PR closed → 如果 merged,通知 PR 作者。""" + pr = payload.get("pull_request") + if not pr or not isinstance(pr, dict): + return + + # 只处理 merged 的 PR + if not pr.get("merged", False): + return + + repo = _repo_fullname(payload) + pr_number = pr.get("number", 0) + pr_title = pr.get("title", "") + pr_author = pr.get("user", {}).get("login", "unknown") + # merged_by 可能不在 payload 中,fallback 到 sender + merged_by = ( + pr.get("merged_by", {}).get("login", "") + or payload.get("sender", {}).get("login", "unknown") + ) + + text = render_template("review_merged", { + "repo": repo, + "pr_number": str(pr_number), + "pr_title": pr_title, + "pr_author": pr_author, + "merged_by": merged_by, + }) + + title = f"PR 已合并: {pr_title} ({repo}#{pr_number})" + _send_mail(pr_author, title, text) + + async def _handle_issues(payload: Dict[str, Any]) -> None: """处理 issues 事件:assigned → 通知被指派人;opened+部署失败 → 通知运维。""" action = payload.get("action", "") diff --git a/src/daemon/toolchain_templates.py b/src/daemon/toolchain_templates.py index 4e3a067..c5d55f5 100644 --- a/src/daemon/toolchain_templates.py +++ b/src/daemon/toolchain_templates.py @@ -23,6 +23,7 @@ _TEMPLATE_MAP: Dict[str, str] = { "deploy_failure": "deploy_failure.md", "review_updated": "review_updated.md", "review_comment": "review_comment.md", + "review_merged": "review_merged.md", } # 模板缓存 diff --git a/templates/toolchain/review_merged.md b/templates/toolchain/review_merged.md new file mode 100644 index 0000000..e76b685 --- /dev/null +++ b/templates/toolchain/review_merged.md @@ -0,0 +1,8 @@ +## PR 已合并 ✅ + +**仓库**: {{repo}} +**PR #{{pr_number}}**: {{pr_title}} +**作者**: @{{pr_author}} +**合并者**: @{{merged_by}} + +PR 已成功合并到主分支。