Skip to content

Latest commit

 

History

History
1074 lines (867 loc) · 37.6 KB

File metadata and controls

1074 lines (867 loc) · 37.6 KB

PR Agent

基于 TypeScript + NestJS 构建的 AI 代码评审服务。当前仓库已经调整为 pnpm monorepo:后端服务位于 backend/,Next.js 前端位于 frontend/

English README

目录


Beta 阶段说明

  • PR Agent 当前处于 beta 阶段。
  • 当前唯一正式支持的接入方式是 GitHub App
  • 仓库里仍可能保留普通 GitHub Webhook 和 GitLab 的代码路径,但它们目前不属于受支持的部署范围。

功能特性

核心评审

  • PR 打开 / 更新 / 合并时自动 AI 代码评审
  • 行内评论,支持 GitHub Suggested Changes 建议代码块
  • Report 模式汇总评审,含风险等级评估
  • 增量评审(仅评审上次评审后的新提交)
  • 报告内 Mermaid 变更结构图(按目录/文件可视化)
  • Diff 中疑似密钥泄露检测(轻量正则扫描)
  • 自动标签(bugfix / feature / refactor / docs / security)

交互命令

  • /ai-review — 手动触发评审(comment 或 report 模式)
  • /ask <问题> — 多轮代码问答
  • /checks [问题] — CI 失败诊断分析
  • /generate_tests [重点] — 自动生成测试代码
  • /changelog [--apply] — 生成或提交 Changelog
  • /describe [--apply] — 生成或更新 PR 描述
  • /improve [重点] — 仅输出改进建议导向的评审
  • /add_doc [重点]/add-doc)— 仅输出文档/注释改进建议
  • /reflect [目标] — 生成需求澄清与验收标准问题
  • /similar_issue [关键词]/similar-issue)— 检索同仓库相似 Issue
  • /custom_prompt <提示词> — 使用自定义 AI 提示词分析 PR 变更
  • /help_docs <问题> — 基于项目 /docs 目录内容进行文档问答
  • /analyze — 列出所有变更代码组件并按风险评级
  • /compliance [重点] — 合规与安全审查
  • /improve_component <组件> — 针对指定组件的改进评审
  • /generate_labels — 基于 diff 内容自动生成并应用 PR 标签
  • /similar_code [关键词] — 检测 diff 中重复或相似的代码模式
  • /auto_approve — 基于 AI 风险评估的条件自动 Approve(默认关闭)
  • /scan_repo_discussions — 从最近已合并 PR 的评审讨论中提取最佳实践
  • /feedback — 评审质量反馈,持续优化后续评审

流程守卫

  • .pr-agent.yml 仓库级策略(提醒 / 强制模式)
  • Issue 与 PR 模板完整性检查
  • GitHub Check 集成,可接 Branch Protection(enforce 模式)
  • .github/.gitlab 模板/流程文件识别(workflow/template/CODEOWNERS/CONTRIBUTING)并给出流程建议
  • Issue 创建/编辑时流程预检、PR 创建/编辑/同步时合并前预检(GitHub)
  • 仓库缺少 .pr-agent.yml 时,Issue 自动分诊(可行性/建议/相似 Issue/自动标签)

当前支持范围

  • 仅支持 GitHub App
  • 普通 GitHub Webhook — 当前 beta 不支持
  • GitLab Webhook — 当前 beta 不支持
  • GitHub Actions — 暂不支持

多模型 Provider

  • OpenAI
  • OpenAI 兼容(DeepSeek 等)
  • Anthropic(Claude)
  • Google Gemini

评审触发

触发方式 评审模式 去重窗口
PR 打开(opened comment / report(按配置) 5 分钟
PR 更新(synchronize comment / report 5 分钟(按新 commit SHA)
PR 编辑(edited comment / report 5 分钟
PR 合并(closed + merged) report 24 小时(可配置)
/ai-review 评论命令 comment / report 5 分钟
/ai-review report report 5 分钟
/ai-review comment comment 5 分钟
Webhook Header x-ai-mode(仅 GitLab,当前 beta 不支持) report / comment 5 分钟
Issue 创建 / 编辑 流程预检(GitHub)+ 缺省策略自动分诊(无策略文件时) 5 分钟
PR 创建 / 编辑 / 同步 合并前预检(GitHub)

路线图与流程资产

  • 竞争差距落地 backlog:docs/roadmap/2026-02-19-competitive-gap-backlog.md
  • GitHub Issue 模板:.github/ISSUE_TEMPLATE/bug_report.md.github/ISSUE_TEMPLATE/feature_request.md
  • GitHub PR 模板:.github/pull_request_template.md
  • GitLab Issue 模板:.gitlab/issue_templates/Bug.md.gitlab/issue_templates/Feature.md
  • GitLab MR 模板:.gitlab/merge_request_templates/default.md

建议的 GitHub Flow 基线:

  1. 开启 Branch Protection,至少要求 PR Agent Policy 与 CI 必过。
  2. 在仓库启用 .pr-agent.ymlmode: enforce(可先从核心仓库灰度)。
  3. 统一使用 Issue/PR 模板,避免需求与验证信息缺失。

系统架构

仓库拓扑

graph LR
    ROOT[pr-agent monorepo]
    ROOT --> BE[backend/<br/>NestJS + Probot + tests]
    ROOT --> FE[frontend/<br/>Next.js 官网 / 控制台]
    ROOT --> OPS[Docker / Compose<br/>后端部署]
    ROOT --> NP[Nixpacks<br/>前端部署]
    ROOT --> DOCS[docs/<br/>路线图与流程资产]
Loading

整体架构

graph TB
    subgraph 平台入口
        GH_APP[GitHub App<br/>Probot]
        GH_WH[GitHub Webhook]
        GL_WH[GitLab Webhook]
    end

    subgraph NestJS 应用
        direction TB
        CTRL[Controllers<br/>路由 & 校验]
        SVC[Services<br/>签名验证 & 分发]
        INT[集成层<br/>GitHub / GitLab 适配器]
        RE[评审引擎<br/>AI Reviewer + Patch 解析]
        RR[报告渲染器<br/>Markdown + 建议代码块]
    end

    subgraph 外部服务
        AI[AI Providers<br/>OpenAI / Anthropic / Gemini]
        GH_API[GitHub API]
        GL_API[GitLab API]
        NOTIFY[通知推送<br/>Slack / Discord / 企业微信]
    end

    GH_APP -->|Webhook 事件| CTRL
    GH_WH -->|Webhook 事件| CTRL
    GL_WH -->|Webhook 事件| CTRL
    CTRL --> SVC
    SVC --> INT
    INT --> RE
    RE -->|LLM 调用| AI
    RE --> RR
    RR -->|发布评论 / 报告| GH_API
    RR -->|发布评论 / 报告| GL_API
    INT -.->|可选| NOTIFY
Loading

请求处理流程

sequenceDiagram
    participant P as 平台 (GitHub/GitLab)
    participant C as Controller
    participant S as Service
    participant D as 去重模块
    participant I as 集成层
    participant A as AI 评审引擎
    participant R as 报告渲染器

    P->>C: Webhook 事件
    C->>S: 验证签名 & 解析请求体
    S->>D: 去重检查(FNV 哈希,5 分钟窗口)
    alt 重复请求
        D-->>S: 跳过(已处理过)
    else 新请求
        D-->>S: 放行
        S->>I: 分发到平台处理器
        I->>I: 获取 diff、文件内容、策略配置
        I->>A: 发送上下文 + diff 给 AI 模型
        A-->>I: 结构化评审结果(Zod 校验)
        I->>R: 格式化报告 / 行内评论
        R->>P: 通过 API 发布评审
        I-->>P: 可选:通知 Webhook
    end
Loading

模块依赖关系

graph LR
    subgraph NestJS 模块
        APP[AppModule]
        GH[GithubModule]
        GL[GitlabModule]
        GHA[GithubAppModule]
    end

    subgraph 集成层
        GHR[github-review]
        GHW[github-webhook]
        GHP[github-policy]
        GHC[github-content]
        GLR[gitlab-review]
        NTF[notification]
    end

    subgraph 核心层
        REV[ai-reviewer]
        PAT[patch parser]
        RPT[report-renderer]
        POL[review-policy]
        DDP[dedupe]
        HTTP[http client]
        STA[runtime-state]
        SEC[secret-patterns]
        CACHE[cache]
    end

    APP --> GH
    APP --> GL
    APP --> GHA

    GH --> GHR
    GH --> GHW
    GHA --> GHR

    GHR --> GHP
    GHR --> GHC
    GHR --> REV
    GHR --> RPT
    GHR --> NTF

    GLR --> REV
    GLR --> RPT
    GLR --> NTF
    GL --> GLR

    REV --> PAT
    REV --> POL
    REV --> HTTP

    GHR --> DDP
    GLR --> DDP
    DDP --> STA
    GHR --> SEC
    GLR --> SEC
    GHP --> CACHE
Loading

详细请求流

下图追踪每一条请求路径——从 Webhook 入口经过事件路由、命令解析、通用评审引擎,到最终输出与运维。

flowchart LR
    subgraph E["入口端点 (NestJS + Probot)"]
        E1["/api/github/webhooks<br/>GithubAppBootstrapService"]
        E2["/github/trigger<br/>GithubWebhookController"]
        E3["/gitlab/trigger<br/>GitlabWebhookController"]
        E4["/github/replay/:eventId<br/>/gitlab/replay/:eventId"]
        E5["/health /metrics /webhook/events"]
    end

    subgraph GHA["GitHub App 事件路由 (backend/src/app.ts)"]
        A1["issues.opened, issues.edited<br/>runGitHubIssuePolicyCheck"]
        A2["pull_request.opened, edited, synchronize<br/>runGitHubPullRequestPolicyCheck"]
        A3["resolveGitHubPullRequestAutoReviewPolicy"]
        A4["pull_request.closed (merged)<br/>resolveGitHubReviewBehaviorPolicy"]
        A5["issue_comment.created (PR + Issue)<br/>handleGitHubIssueCommentCommand"]
        A6["pull_request_review_thread<br/>recordGitHubFeedbackSignal"]
    end

    subgraph GHW["原生 GitHub Webhook (backend/src/integrations/github/github-webhook.ts)"]
        B1["handlePlainGitHubWebhook"]
        B2["verifyWebhookSignature + payload schema"]
        B3["pull_request / issues / issue_comment / review_thread dispatch"]
        B4["runGitHubPullRequestPolicyCheck + runGitHubIssuePolicyCheck"]
        B5["handleGitHubIssueCommentCommand"]
    end

    subgraph GLW["GitLab Webhook (backend/src/integrations/gitlab/gitlab-review.ts)"]
        C1["runGitLabWebhook"]
        C2["verify token + payload schema"]
        C3["handleGitLabMergeRequestWebhook"]
        C4["handleGitLabNoteWebhook"]
        C5["resolveGitLabReviewPolicy (.pr-agent.yml)"]
    end

    subgraph CMD["命令解析层"]
        D1["parseReviewCommand"]
        D2["parseAsk / parseMention / parseChecks / parseGenerateTests"]
        D3["parseDescribe / parseChangelog"]
        D4["parseImprove / parseAddDoc / parseReflect / parseSimilarIssue / parseFeedback"]
    end

    subgraph CORE["通用评审引擎"]
        R1["runGitHubReview / runGitLabReview"]
        R2["去重 + 限流 + 增量 head + 反馈信号"]
        R3["收集上下文: diff/files/ci/policy"]
        R4["analyzePullRequest / answerPullRequestQuestion"]
        R5["patch 解析 + hunk 优先级 + 行映射"]
        R6["密钥扫描 + 自动标签"]
    end

    subgraph OUT["输出与运维"]
        O1["buildReportCommentMarkdown"]
        O2["buildIssueCommentMarkdown"]
        O3["createComment / notes / managed upsert"]
        O4["publishNotification (可选)"]
        O5["pr_agent_* 指标 + replay 存储"]
    end

    E1 --> A1
    E1 --> A2 --> A3 --> R1
    E1 --> A4 --> R1
    E1 --> A5
    E1 --> A6

    E2 --> B1 --> B2 --> B3
    B3 --> B4 --> R1
    B3 --> B5

    E3 --> C1 --> C2
    C2 --> C3 --> C5 --> R1
    C2 --> C4 --> C5

    A5 --> D1
    A5 --> D2
    A5 --> D3
    A5 --> D4
    B5 --> D1
    B5 --> D2
    B5 --> D3
    B5 --> D4
    C4 --> D1
    C4 --> D2
    C4 --> D3
    C4 --> D4

    D1 --> R1
    D2 --> R4
    D3 --> R4
    D4 --> R1

    R1 --> R2 --> R3 --> R4 --> R5
    R4 --> R6
    R5 --> O1 --> O3
    R5 --> O2 --> O3
    R6 --> O3
    O3 --> O4

    E4 --> B1
    E4 --> C1
    E5 --> O5
    E2 --> O5
    E3 --> O5
    O3 -. 反馈信号 .-> R2
Loading

技术栈

层级 技术
运行时 Node.js 22 (Alpine)
语言 TypeScript 5.7(ES2022,严格模式)
框架 NestJS 11
HTTP 服务 Express 4
GitHub App Probot 13
AI 客户端 OpenAI SDK 4(同时用于兼容 Provider)
校验 Zod 3
状态存储 内存 / JSON 文件 / SQLite(Node.js 内置 node:sqlite
容器 Docker(多阶段构建)

项目结构

pr-agent/
├── backend/
│   ├── src/
│   │   ├── main.ts                 # NestJS 启动入口
│   │   ├── app.ts                  # Probot 事件处理(GitHub App)
│   │   ├── app.module.ts           # NestJS 根模块
│   │   ├── common/                 # 过滤器与共享请求类型
│   │   ├── core/                   # 运行时状态、缓存、环境变量、i18n、HTTP
│   │   ├── integrations/           # GitHub / GitLab / 通知适配层
│   │   ├── modules/                # Webhook、健康检查、回放等 NestJS 模块
│   │   └── review/                 # AI 评审引擎与报告渲染
│   ├── tests/                      # 后端测试套件
│   ├── package.json
│   └── tsconfig.json
├── frontend/
│   ├── app/                        # Next.js App Router 页面与布局
│   ├── components/                 # 前端 UI 组件
│   ├── public/                     # 静态资源
│   ├── package.json
│   └── next.config.ts
├── docs/                           # 产品文档、路线图、流程资产
├── data/                           # 本地/运行时持久化数据挂载点
├── secrets/                        # 本地私钥挂载目录(不提交)
├── Dockerfile                      # 后端容器镜像
├── docker-compose.yml              # 后端部署与本地运维
├── nixpacks.toml                   # 根目录 Nixpacks 入口,部署 frontend
├── package.json                    # Workspace 脚本
├── pnpm-lock.yaml
├── pnpm-workspace.yaml
├── turbo.json
├── README.md
└── README-zh.md

Workspace 说明

  • 仓库根目录 .env 同时供本地后端开发和 Docker Compose 使用。
  • backend/ 是可部署的评审服务;使用根目录 nixpacks.toml 时部署的是 frontend/,不是后端。
  • 容器内后端持久化路径默认是 /data/pr-agent/...,宿主机对应为 data/pr-agent/...

后端路径别名

后端包使用 Node.js ESM subpath imports(配置位于 backend/tsconfig.jsonbackend/package.json):

别名 映射路径
#core backend/src/core/index.ts
#review backend/src/review/index.ts
#integrations/github backend/src/integrations/github/index.ts
#integrations/gitlab backend/src/integrations/gitlab/index.ts
#integrations/notify backend/src/integrations/notify/index.ts

快速开始

前置条件

  • Node.js >= 22
  • pnpm >= 10

本地开发

# 安装 workspace 依赖
pnpm install

# 在仓库根目录准备环境变量文件
cp .env.example .env

# 启动后端(backend 包会读取 ../.env)
pnpm dev:backend

# 启动前端
pnpm dev:frontend

# 生产构建后端
pnpm --filter backend build

# 启动已构建的后端
pnpm --filter backend start

后端默认监听 3000 端口(可通过 PORT 环境变量配置)。前端单独运行时也默认使用 3000

健康检查

curl http://localhost:3000/health
curl http://localhost:3000/health?deep=true   # 测试 AI Provider 连通性
curl http://localhost:3000/github/health       # GitHub 配置状态

配置说明

环境变量

复制 .env.example 并填入所需值。当前受支持的最小配置模板是:

  • .env.github-app.min.example — GitHub App 最小配置

普通 GitHub Webhook 和 GitLab 的最小示例文件仍保留在仓库中,仅供参考,不属于当前 beta 的受支持部署路径。

AI Provider 配置

graph LR
    ENV[AI_PROVIDER 环境变量]
    ENV -->|openai| OAI[OpenAI<br/>OPENAI_API_KEY + OPENAI_MODEL]
    ENV -->|openai-compatible| OC[OpenAI 兼容<br/>OPENAI_BASE_URL + OPENAI_COMPATIBLE_MODEL]
    ENV -->|anthropic| ANT[Anthropic<br/>ANTHROPIC_API_KEY + ANTHROPIC_MODEL]
    ENV -->|gemini| GEM[Gemini<br/>GEMINI_API_KEY + GEMINI_MODEL]
Loading

OpenAI(默认)

AI_PROVIDER=openai
OPENAI_API_KEY=sk-...
OPENAI_MODEL=gpt-4.1-mini

OpenAI 兼容(如 DeepSeek)

AI_PROVIDER=openai-compatible
OPENAI_BASE_URL=https://api.deepseek.com/v1
OPENAI_COMPATIBLE_API_KEY=...
OPENAI_COMPATIBLE_MODEL=deepseek-chat

Anthropic

AI_PROVIDER=anthropic
ANTHROPIC_API_KEY=sk-ant-...
ANTHROPIC_MODEL=claude-3-5-haiku-latest
ANTHROPIC_MAX_TOKENS=8192

Gemini

AI_PROVIDER=gemini
GEMINI_API_KEY=...
GEMINI_MODEL=gemini-2.0-flash

状态持久化

后端 环境变量值 适用场景
内存 memory(默认) 无状态容器、开发环境
JSON 文件 file 简单单实例
SQLite sqlite(推荐) 生产单实例部署
RUNTIME_STATE_BACKEND=sqlite
RUNTIME_STATE_SQLITE_FILE=/data/pr-agent/runtime-state.sqlite3

通知推送(可选)

支持企业微信、Slack、Discord 和通用 JSON Webhook:

NOTIFY_WEBHOOK_URL=https://hooks.slack.com/services/...
NOTIFY_WEBHOOK_FORMAT=slack   # wecom | slack | discord | generic

关键调参

AI 提供商调参

变量 默认值 说明
AI_HTTP_TIMEOUT_MS 30000(30 秒) AI 评审请求 HTTP 超时
AI_ASK_HTTP_TIMEOUT_MS 60000(60 秒) /ask 命令 HTTP 超时(多轮问答通常需要更长时间)
AI_HTTP_RETRIES 2 AI 提供商临时故障时的重试次数
AI_HTTP_RETRY_BACKOFF_MS 400 AI 请求重试基础退避时延(毫秒)
AI_MAX_CONCURRENCY 4 AI 请求最大并发数
AI_MAX_QUEUE_SIZE 200 AI 等待队列上限(超限后拒绝新任务)
AI_SHUTDOWN_DRAIN_TIMEOUT_MS 15000(15 秒) 进程关闭时等待进行中 AI 请求完成的超时时间
AI_DEBUG_LOGS false 记录 AI 请求/响应载荷用于调试
HEALTHCHECK_AI_TIMEOUT_MS 5000(5 秒) 深度健康检查 AI 探测超时
HEALTHCHECK_AI_LIVE_PROBE false GET /health?deep=true 时是否实际调用 AI API(否则仅检查配置)

AI_CONCURRENCY_LIMIT 已废弃,不再生效。请改用 AI_MAX_CONCURRENCYAI_MAX_QUEUE_SIZE

全局运行时与命令限流

变量 默认值 说明
WEBHOOK_BODY_LIMIT 1mb 全局 Express body-parser 上限(超限返回 413
COMMAND_RATE_LIMIT_MAX 10 每用户、每 PR/MR、每命令在窗口内的最大触发次数
COMMAND_RATE_LIMIT_WINDOW_MS 3600000(1 小时) 命令限流时间窗口

GitHub 专属

变量 默认值 说明
GITHUB_MERGED_DEDUPE_TTL_MS 86400000(24 小时) merged + report 事件去重窗口
GITHUB_FEEDBACK_SIGNAL_TTL_MS 2592000000(30 天) 反馈学习信号保留时长
GITHUB_INCREMENTAL_STATE_TTL_MS 604800000(7 天) 增量评审 SHA 缓存有效期
GITHUB_POLICY_CONFIG_CACHE_TTL_MS 300000(5 分钟) .pr-agent.yml 策略/评审配置缓存
GITHUB_POLICY_COMMENT_DEDUPE_TTL_MS 600000(10 分钟) 流程提醒评论去重窗口
GITHUB_ISSUE_AUTO_TRIAGE_ENABLED true 当仓库缺少 .pr-agent.yml 时,在 issues.opened/edited 自动执行 Issue 分诊
GITHUB_ISSUE_AUTO_TRIAGE_AUTO_LABELS true Issue 自动分诊后自动追加推断标签
GITHUB_ISSUE_AUTO_TRIAGE_DEDUPE_TTL_MS 300000(5 分钟) Issue 自动分诊评论去重窗口
GITHUB_ISSUE_AUTO_TRIAGE_SIMILAR_LIMIT 5 自动分诊输出中最多展示的相似 Issue 数量
GITHUB_ISSUE_TRIAGE_DISABLE_AI false 关闭 AI 调用,仅使用内置兜底分诊文案
GITHUB_WEBHOOK_MAX_BODY_BYTES 10485760(10MB) /github/trigger 的额外请求体硬上限
GITHUB_WEBHOOK_SKIP_SIGNATURE false 仅调试可用;NODE_ENV=production 时禁止开启

GitLab 专属

变量 默认值 说明
GITLAB_MERGED_DEDUPE_TTL_MS 86400000(24 小时) merged + report 去重窗口
GITLAB_INCREMENTAL_STATE_TTL_MS 604800000(7 天) 增量评审状态缓存
GITLAB_FEEDBACK_SIGNAL_TTL_MS 2592000000(30 天) 反馈学习信号保留窗口
GITLAB_POLICY_CONFIG_CACHE_TTL_MS 300000(5 分钟) .pr-agent.yml 策略缓存
GITLAB_CHANGELOG_PATH CHANGELOG.md /changelog --apply 写回路径
GITLAB_WEBHOOK_MAX_BODY_BYTES 10485760(10MB) /gitlab/trigger 的额外请求体硬上限
GITLAB_REQUIRE_WEBHOOK_SECRET false 设为 true 时必须配置 GITLAB_WEBHOOK_SECRET
ALLOW_INSECURE_GITLAB_HTTP false 仅本地调试允许 http:// GitLab 地址

调参建议:

  • MERGED_DEDUPE_TTL_MS — 控制 merged + report 事件的去重窗口,防止 Webhook 重投时重复评审。遇到较多 Webhook 重试/Redeliver 时可调大到 48h~72h;需要更快允许同一 PR 合并事件再次触发时可调小到 1h~6h。该变量只影响合并自动触发;手动评论命令触发(/ai-review ...)仍使用短窗口(5 分钟)去重策略。
  • FEEDBACK_SIGNAL_TTL_MS — 控制 /feedback 与 review thread resolved/unresolved 信号的保留时长。团队评审节奏慢、希望长期记忆偏好可设为 60~90 天;规则变化快、希望更快"遗忘"历史偏好可设为 7~14 天。
  • COMMAND_RATE_LIMIT_* — 控制评论命令的防滥用阈值。高活跃仓库可适当上调,命令刷屏场景可下调。

.env.example 提供基础变量参考;上方补充的是代码已实现但通常不在最小模板中的高级开关。


部署指南

Docker 部署(推荐)

graph LR
    subgraph Docker 构建
        B1[阶段 1:构建<br/>node:22-alpine<br/>pnpm install + backend build]
        B2[阶段 2:运行时<br/>node:22-alpine<br/>仅生产依赖]
        B1 -->|COPY dist/| B2
    end
    B2 -->|暴露 3000 端口| SRV[pr-agent 容器]
Loading

构建 & 运行

docker build -t pr-agent:latest .
docker run -d \
  --name pr-agent \
  -p 3000:3000 \
  --env-file .env \
  -v ./data:/data \
  pr-agent:latest

Docker Compose

# 启动
docker compose up -d --build

# 查看日志
docker compose logs -f pr-agent

# 重启
docker compose restart pr-agent

# 停止
docker compose down

docker-compose.yml 挂载的卷:

  • ./data:/data — 持久化状态(SQLite、事件存储)
  • ./secrets/github-app.private-key.pem:/run/secrets/github-app-private-key.pem:ro — GitHub App 私钥

Nixpacks(仅前端)

根目录 nixpacks.toml 用于从仓库根目录部署 frontend/,不会构建或启动后端。

  • Install: pnpm install --frozen-lockfile
  • Build: pnpm --filter frontend build
  • Start: pnpm --filter frontend start

生产部署清单

graph TD
    A[选择平台模式] -->|GitHub App| B1[创建 GitHub App]
    A -->|普通 Webhook| B2[生成 PAT Token]
    A -->|GitLab| B3[生成 API Token]

    B1 --> C[配置 AI Provider]
    B2 --> C
    B3 --> C

    C --> D[设置状态后端 = sqlite]
    D --> E[部署容器]
    E --> F[配置 Webhook URL]
    F --> G[验证健康检查端点]
    G --> H[测试 /ai-review 命令]
Loading
  1. 使用 GitHub App 接入模式 — 这是当前 beta 唯一受支持的接入方式
  2. 配置 AI Provider — 设置 AI_PROVIDER 及对应的 API Key / 模型名称
  3. 启用状态持久化 — 生产环境推荐 RUNTIME_STATE_BACKEND=sqlite
  4. 部署容器 — Docker、Docker Compose、Render、Railway、Fly.io 或 K8s
  5. 配置 Webhook URLhttps://<域名>/api/github/webhooks
  6. 验证 — 访问健康检查端点,并在 PR 中测试 /ai-review 命令

快速部署参考

这是一个适用于 Render/Railway/Fly.io/Docker/K8s 的精简部署路径。

  1. 使用 GitHub App 模式
  2. 使用最小环境变量

GitHub App 最小配置(.env.github-app.min.example

APP_ID=123456
PRIVATE_KEY_PATH=/run/secrets/github-app-private-key.pem
# PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----\\n...\\n-----END RSA PRIVATE KEY-----\\n"
WEBHOOK_SECRET=replace-with-webhook-secret
AI_PROVIDER=openai
OPENAI_API_KEY=replace-with-openai-key
OPENAI_MODEL=gpt-4.1-mini

推荐的单实例补充配置

RUNTIME_STATE_BACKEND=sqlite
RUNTIME_STATE_SQLITE_FILE=/data/pr-agent/runtime-state.sqlite3
WEBHOOK_EVENT_STORE_ENABLED=false
WEBHOOK_REPLAY_ENABLED=false

排障时临时开启 replay

WEBHOOK_EVENT_STORE_ENABLED=true
WEBHOOK_REPLAY_ENABLED=true
WEBHOOK_REPLAY_TOKEN=replace-with-strong-random-token
  1. 启动后端应用
pnpm install --frozen-lockfile
pnpm --filter backend build
pnpm --filter backend start

后端服务监听 PORT(默认 3000)。

  1. 配置 Webhook 地址
    • GitHub App:https://<域名>/api/github/webhooks
  2. Docker 一键启动
docker build -t pr-agent:latest .
docker run -d --name pr-agent -p 3000:3000 --env-file .env pr-agent:latest
  1. 验证清单
    • GET /health
    • GET /github/health
    • GET /metrics
    • 在 PR/MR 评论中测试:/ai-review/ai-review comment
    • Webhook 失败响应应包含结构化字段:error/type/status/path/method/timestamp

如果开启 replay:

  • GET /webhook/events
  • POST /github/replay/:eventId
  • 请求头:x-pr-agent-replay-token: <WEBHOOK_REPLAY_TOKEN>

Nginx 反向代理

当前仓库未提交 deploy/nginx/ 示例文件,可直接使用下方片段作为基线:

server {
    listen 443 ssl;
    server_name pr-agent.example.com;

    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

平台接入

GitHub App(当前唯一支持的方式)

  1. 创建 GitHub App,配置以下权限:
    • Pull requests:Read & write
    • Issues:Read & write
    • Contents:Read & write(/changelog --apply 需要)
    • Checks:Read & write(mode=enforce 时必需)
    • Metadata:Read-only
  2. 订阅事件:
    • Pull requestopened / edited / synchronize / closed
    • Issuesopened / edited
    • Issue comment
    • Pull request review threadresolved / unresolved,用于反馈学习)
  3. Webhook URL 设为 https://<域名>/api/github/webhooks
  4. 配置环境变量:
APP_ID=123456
PRIVATE_KEY_PATH=/run/secrets/github-app-private-key.pem
# PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----\n...\n-----END RSA PRIVATE KEY-----\n"
WEBHOOK_SECRET=your-webhook-secret
  • GitHub App 启用条件(见 backend/src/modules/github-app/github-app.bootstrap.service.ts):APP_ID +(PRIVATE_KEYPRIVATE_KEY_PATH)+ WEBHOOK_SECRET
  • docker-compose.yml 默认挂载私钥路径为 ./secrets/github-app.private-key.pem:/run/secrets/github-app-private-key.pem:ro。如果本地缺少 secrets/ 目录或 PEM 文件,docker compose up 会失败。
  • 建议本地预先创建:mkdir -p secrets datadata 目录通常可由 Docker 自动创建,但手动创建更可控。

若未配置 APP_ID + PRIVATE_KEY(+ WEBHOOK_SECRET),GitHub App 模式会被禁用,此时当前 beta 部署也视为不完整。

当前 Beta 不支持的集成方式

  • 普通 GitHub Webhook 目前不是受支持的部署目标。
  • GitLab Webhook 目前不是受支持的部署目标。

评论命令

所有命令通过 PR/MR 评论触发。标记 (仅 PR) 的命令需要 Pull Request 上下文(diff、CI 检查),在 Issue 评论中不可用。

命令 说明
/ai-review (仅 PR) 触发 AI 评审(未显式指定时默认 report
/ai-review report (仅 PR) 强制 Report 模式(汇总评论)
/ai-review comment (仅 PR) 强制 Comment 模式(行内评论)
/ai-review --mode=report / --mode=comment (仅 PR) 参数方式指定评审模式(与位置参数等价)
/ask <问题> 针对 PR 或 Issue 提问(支持多轮对话)
@bot-name <问题> @提及 Bot 进行提问(设置 GITHUB_APP_SLUGGITHUB_BOT_LOGIN
/checks [问题] (仅 PR) 分析 CI 检查失败原因
/generate_tests [重点] (仅 PR) 为变更生成测试代码
/changelog [重点] (仅 PR) 生成 Changelog 条目
/changelog --apply [重点] (仅 PR) 生成并提交 Changelog 到仓库
/describe (仅 PR) 生成 PR/MR 描述
/describe --apply (仅 PR) 生成并更新 PR/MR 描述
/improve [重点] (仅 PR) 以改进建议为主进行评审
/add_doc [重点] / /add-doc [重点] (仅 PR) 仅输出文档/注释改进建议
/reflect [目标] (仅 PR) 生成需求澄清与验收标准问题
/similar_issue [关键词] / /similar-issue [关键词] 检索同仓库相似 Issue
/custom_prompt <提示词> (仅 PR) 使用自定义 AI 提示词分析 PR 变更
/help_docs <问题> 基于项目 /docs 目录内容进行文档问答
/analyze (仅 PR) 列出所有变更代码组件并按风险评级
/compliance [重点] (仅 PR) 合规与安全审查
/improve_component <组件> (仅 PR) 针对指定组件的改进评审
/generate_labels (仅 PR) 基于 diff 内容自动生成并应用 PR 标签
/similar_code [关键词] (仅 PR) 检测 diff 中重复或相似的代码模式
/auto_approve (仅 PR) 基于 AI 风险评估的条件自动 Approve(默认关闭)
/scan_repo_discussions (仅 PR) 从最近已合并 PR 的评审讨论中提取最佳实践
/feedback resolved|dismissed|up|down [备注] 评审质量反馈

支持别名写法,例如:/ai-review ask .../ai-review checks .../ai-review generate-tests .../ai-review add-doc ....pr-agent.yml 的命令开关覆盖 /describe/ask/checks/generate_tests/changelog/feedback/improve/add_doc/custom_prompt/help_docs/analyze/compliance/similar_code/auto_approve/scan_repo_discussions/reflect 依赖 askCommandEnabled/improve_component 依赖 improveCommandEnabled/generate_labels 依赖 autoLabelEnabled

提示: /ask/feedback/similar_issue/help_docs@提及 在 Issue 和 PR 评论中均可使用。在 Issue 评论中不提供 diff 或 CI 上下文,但会将 Issue 标题和正文作为 AI 上下文。可设置 GITHUB_APP_SLUG(GitHub App 的 slug)或 GITHUB_BOT_LOGIN(Bot 账号 login)启用 @提及 检测。带或不带 [bot] 后缀都支持。


仓库策略配置

在仓库根目录添加 .pr-agent.yml 来配置仓库级行为:

mode: remind          # remind = 仅评论提醒,enforce = 写入失败 GitHub Check

issue:
  enabled: true
  minBodyLength: 20
  requiredSections:
    - Summary
    - Steps to Reproduce
    - Expected Behavior

pullRequest:
  enabled: true
  minBodyLength: 20
  requireLinkedIssue: false
  requiredSections:
    - Summary
    - Test Plan

review:
  enabled: true
  mode: comment         # comment | report
  onOpened: true        # PR 打开时评审
  onEdited: false
  onSynchronize: true   # 新提交时评审
  describeEnabled: true
  describeAllowApply: false
  checksCommandEnabled: true
  includeCiChecks: true
  askCommandEnabled: true
  generateTestsCommandEnabled: true
  changelogCommandEnabled: true
  changelogAllowApply: false
  feedbackCommandEnabled: true
  improveCommandEnabled: true
  addDocCommandEnabled: true
  customPromptCommandEnabled: true
  helpDocsCommandEnabled: true
  analyzeCommandEnabled: true
  complianceCommandEnabled: true
  similarCodeCommandEnabled: true
  autoApproveCommandEnabled: false   # 默认关闭,安全考虑
  scanRepoDiscussionsCommandEnabled: true
  secretScanEnabled: true
  autoLabelEnabled: true
  secretScanCustomPatterns:  # 可选:仓库自定义密钥正则
    - "(?i)my_internal_token_[a-z0-9]{16,}"
  customRules:
    - 所有公开 API 必须提供类型注释
    - 不允许新增 any 类型

GitLab 当前只读取 .pr-agent.yml 中的 review: 段。顶层 modeissuepullRequest 的流程校验是 GitHub 流程能力。

模式说明:

  • remind — 评论提醒缺失项,不阻止合并
  • enforce — 创建失败的 GitHub Check(PR Agent Policy),可在 Branch Protection 中设为必需

模板回退行为:

  • 未配置 requiredSections 时,会自动从仓库模板提取段落标题进行检查:
    • Issue:.github/ISSUE_TEMPLATE/*.github/ISSUE_TEMPLATE.md
    • PR:.github/pull_request_template.md.github/PULL_REQUEST_TEMPLATE.md
  • 若仓库无上述模板,回退到内置默认段落(Issue:Summary / Steps to Reproduce / Expected Behavior;PR:Summary / Test Plan / Related Issue)。

review 字段说明:

字段 说明
enabled / mode 启用 AI 评审,设置默认模式(comment / report)
onOpened / onEdited / onSynchronize 控制哪些 PR 事件自动触发评审
describeEnabled 是否启用 /describe 命令
describeAllowApply 是否允许 /describe --apply 直接改写 PR 描述
checksCommandEnabled 是否启用 /checks 命令
includeCiChecks 是否把 CI 检查结果带入 AI 上下文
askCommandEnabled 是否启用 /ask 命令
generateTestsCommandEnabled 是否启用 /generate_tests 命令
changelogCommandEnabled 是否启用 /changelog 命令
changelogAllowApply 是否允许 /changelog --apply 直接写回仓库 Changelog
feedbackCommandEnabled 是否启用 /feedback 命令
improveCommandEnabled 是否启用 /improve 命令
addDocCommandEnabled 是否启用 /add_doc/add-doc)命令
customPromptCommandEnabled 是否启用 /custom_prompt 命令
helpDocsCommandEnabled 是否启用 /help_docs 命令
analyzeCommandEnabled 是否启用 /analyze 命令
complianceCommandEnabled 是否启用 /compliance 命令
similarCodeCommandEnabled 是否启用 /similar_code 命令
autoApproveCommandEnabled 是否启用 /auto_approve 命令(默认关闭,安全考虑)
scanRepoDiscussionsCommandEnabled 是否启用 /scan_repo_discussions 命令
secretScanEnabled 是否扫描 diff 中疑似密钥泄露并发布安全提示
secretScanCustomPatterns 仓库自定义密钥正则补充规则
autoLabelEnabled 是否根据变更内容自动追加 PR 标签
customRules 团队自定义评审规则(自然语言),在评审与问答中都会强制纳入

可观测性

指标

Prometheus 格式指标通过 GET /metrics 暴露:

  • pr_agent_webhook_requests_total — 按平台和事件统计的 Webhook 请求数
  • pr_agent_webhook_results_total — 按平台和结果(ok/error)统计
  • pr_agent_webhook_replay_total — 回放执行结果统计
  • pr_agent_webhook_store_writes_total — 调试事件存储写入次数
  • pr_agent_webhook_store_trim_total — 调试事件存储裁剪次数
  • pr_agent_health_checks_total — 健康检查端点调用次数
  • pr_agent_http_errors_total — 全局 HTTP 错误计数
  • pr_agent_process_uptime_seconds — 进程运行时间
  • pr_agent_ai_requests_active — 当前 AI 活跃请求数
  • pr_agent_ai_wait_queue_size — AI 并发等待队列长度
  • pr_agent_ai_shutdown_requested — AI 关停标记(0/1)
  • pr_agent_runtime_state_backend_info{backend=...} — 当前状态后端信息指标

健康检查

端点 用途
GET /health 存活探针
GET /health?deep=true 深度检查(AI Provider 连通性)
GET /github/health GitHub Webhook 配置校验
GET /gitlab/health GitLab Webhook 遗留配置校验(当前 beta 不支持)

错误处理

Webhook 错误返回结构化 JSON。已知 Webhook 错误(如 BadWebhookRequestErrorWebhookAuthError)包含描述性消息;未识别的内部错误会被过滤为 "internal server error" 以防止信息泄露。

{
  "ok": false,
  "error": "webhook secret verification failed",
  "type": "WebhookAuthError",
  "status": 401,
  "path": "/github/trigger",
  "method": "POST",
  "timestamp": "2026-01-01T00:00:00.000Z"
}

请求体超过 WEBHOOK_BODY_LIMIT(默认 1mb)时返回 413 Payload Too Large

Webhook 回放(调试用)

排障时临时启用:

WEBHOOK_EVENT_STORE_ENABLED=true
WEBHOOK_REPLAY_ENABLED=true
WEBHOOK_REPLAY_TOKEN=your-secret-token

端点(需携带 x-pr-agent-replay-token 请求头):

  • GET /webhook/events — 列出已存储的事件
  • POST /github/replay/:eventId — 回放 GitHub 事件
  • POST /gitlab/replay/:eventId — 回放 GitLab 事件

韧性机制

  • HTTP 重试:指数退避(2 次重试,400ms 基础延迟),针对 408/429/5xx 状态码
  • 请求去重:FNV 哈希,5 分钟窗口(合并事件 24 小时)
  • 限流:按作用域限制,防止 API 滥用
  • 优雅关停:收到 SIGTERM/SIGINT 后排空进行中的请求

测试

# 后端测试
pnpm test:backend

# 后端覆盖率
pnpm --filter backend test:coverage

# 后端类型检查
pnpm --filter backend check

# 前端生产构建回归检查
pnpm --filter frontend build

后端测试使用 Node.js 内置测试运行器(node:test)。建议的回归检查覆盖:

  • AI 并发控制
  • 缓存与去重行为
  • Diff 解析与 Hunk 优先级
  • GitHub/GitLab 集成逻辑
  • HTTP 重试与错误处理
  • 策略校验
  • 通知适配器
  • NestJS 模块装配

许可证

私有项目 — 详见仓库说明。