feat(toolchain): auto-deploy on PR merge (git pull + pm2 restart) (#43)

- Add auto-deploy logic in _handle_pr_closed after mail notification
- git pull origin main in install dir on merge
- Smart restart: only restart pm2 when src/templates/frontend/*.py changed
- Pure docs changes: pull only, no restart
- Deploy failure logged but does not block mail notification
- Update design doc §23 with auto-deploy section
This commit is contained in:
cfdaily
2026-06-12 13:26:10 +08:00
parent 5474d0a0e8
commit 9bb1e9dc64
2 changed files with 53 additions and 1 deletions
+37
View File
@@ -481,6 +481,43 @@ async def _handle_pr_closed(payload: Dict[str, Any]) -> None:
title = f"PR 已合并: {pr_title} ({repo}#{pr_number})"
_send_mail(pr_author, title, text)
# 自动部署:git pull + 按需 pm2 restart
try:
import subprocess
import os
install_dir = os.environ.get("SANGUO_PROJECTS_DIR", os.path.expanduser("~/.sanguo_projects"))
repo_dir = os.path.join(install_dir, "sanguo_moziplus_v2")
# git pull
pull_result = subprocess.run(
["git", "pull", "origin", "main"],
cwd=repo_dir, capture_output=True, text=True, timeout=30
)
if pull_result.returncode == 0:
logger.info("Auto-deploy: git pull success for %s", repo)
# 判断是否需要重启:获取 PR 变更文件列表
files = await _fetch_pr_files(repo, pr_number)
needs_restart = any(
f.startswith("src/") or f.startswith("templates/") or f.startswith("frontend/") or f.endswith(".py")
for f in files[0]
)
if needs_restart:
restart_result = subprocess.run(
["pm2", "restart", "sanguo-moziplus-v2"],
capture_output=True, text=True, timeout=15
)
if restart_result.returncode == 0:
logger.info("Auto-deploy: pm2 restart triggered (files: %s)", ", ".join(files[0][:5]))
else:
logger.error("Auto-deploy: pm2 restart failed: %s", restart_result.stderr)
else:
logger.warning("Auto-deploy: git pull failed: %s", pull_result.stderr)
except Exception as e:
logger.error("Auto-deploy: unexpected error: %s", e)
async def _handle_issues(payload: Dict[str, Any]) -> None:
"""处理 issues 事件:assigned → 通知被指派人;opened+部署失败 → 通知运维。"""