🚀 拒绝无效加班!我用 Node.js 撸了一个“全能” AI 代码审查助手 (支持 GitHub/GitLab/Gitea)

1,447 阅读4分钟

🚀 拒绝无效加班!我用 Node.js 撸了一个“全能” AI 代码审查助手 (支持 GitHub/GitLab/Gitea)

前言: 你是否也经历过这样的场景:

  • 每天花费大量时间 Review 琐碎的代码格式问题?
  • 新人提交的 PR 充满了 console.log 和显而易见的 Bug?
  • 想引入 AI 辅助 Review,但市面上的工具要么太贵,要么不支持内网 GitLab/Gitea?

既然如此,不如自己动手!本文将带你从零实现一个 企业级 AI Code Review Agent,支持多平台、并发控制、ChatOps 交互,甚至能像老司机一样教你写代码。

💡 项目亮点

先看效果,这个 Bot 能做什么?

  1. 全平台兼容:无缝对接 GitHub、GitLab (私有化)、Gitea。
  2. 精准打击:不做“废话文学”,基于 AST 和 Diff 上下文,只评论变更行。
  3. ChatOps:在评论区输入 /review,随叫随到,立即重审。
  4. 防爆破设计:内置 并发队列增量去重,保护你的 Token 额度,防止 API 被刷爆。
  5. 深度定制:支持 OpenAI / DeepSeek / Anthropic,Prompt 可完全自定义。

🏗️ 架构设计:拒绝面条代码

为了保证项目的扩展性(毕竟要适配那么多平台),我采用了 六边形架构 (Hexagonal Architecture) 的思想,将核心业务逻辑与外部依赖解耦。

系统架构图

graph TD
    User["用户 / Git 平台"] -->|Webhook/CLI| Entry["入口 (Server/CLI)"]
    Entry --> Core["核心逻辑"]

    subgraph Core Logic
        Orchestrator["审查编排器 (大脑)"]
        Queue["并发任务队列"]
        DiffParser["Diff 精准解析"]
        PromptEng["Prompt 引擎"]
    end

    Core -->|调度| Queue
    Queue -->|执行| IAI

    Core -->|使用| IPlatform["接口: IPlatformProvider"]
    Core -->|使用| IAI["接口: IAIProvider"]

    IPlatform -->|实现| GitHub["GitHub Adapter"]
    IPlatform -->|实现| GitLab["GitLab Adapter"]
    IPlatform -->|实现| Gitea["Gitea Adapter"]

    IAI -->|实现| OpenAI["OpenAI / DeepSeek"]

🛠️ 核心难点与解决方案

在开发过程中,我遇到了几个比较坑的点,这里分享一下解决方案。

1. 并发控制与 Rate Limit

痛点:一个 PR 可能包含 50+ 个文件,如果瞬间发起 50 个 OpenAI 请求,账号分分钟被封,或者服务器 OOM。

解法:引入 p-queue 实现全局并发队列。

// src/utils/queue.ts
import PQueue from 'p-queue';

// 全局单例队列,限制最大并发数为 5
export const analysisQueue = new PQueue({
  concurrency: parseInt(process.env.CONCURRENCY_LIMIT || '5'),
});

在编排器中,我们将每个文件的分析任务丢进队列:

// src/core/orchestrator.ts
const tasks = targetFiles.map((file) => {
  return analysisQueue.add(async () => {
    logger.info({ file: file.filename }, '开始分析...');
    // ... 调用 AI, 解析结果 ...
    return comments;
  });
});

await Promise.all(tasks);

2. 交互式体验 (ChatOps)

痛点:有时候 AI 提了建议,我改完了,但我不想推一个新的 Commit 只是为了触发 Webhook,或者我想手动触发一次复查。

解法:监听 Issue Comment / Note Hook 事件,解析指令。

我在 IPlatformProvider 接口中增加了异步 parseEvent 能力,支持“指令水合”——即收到 /review 评论时,自动反查 PR 的最新 Commit SHA,伪装成一个 PR Update 事件。

// src/platforms/github.ts
if (eventName === 'issue_comment' && body.startsWith('/review')) {
  // 1. 识别指令
  logger.info('收到 ChatOps 指令');
  
  // 2. 调用 API 获取 PR 最新状态 (Head SHA)
  const { data: pr } = await this.octokit.rest.pulls.get({ ... });

  // 3. 构造审查事件
  return {
    eventType: 'pull_request',
    commitSha: pr.head.sha, // 关键:获取最新的代码快照
    // ...
  };
}

3. 如何避免“幻觉”行号?

痛点:AI 经常会胡乱引用行号,导致评论标在错误的代码行上,甚至标在未变更的代码上。

解法

  1. Diff 解析:使用 parse-diff 库,严格获取变更块(Hunk)的起止行号。
  2. 上下文校验:在 Prompt 中明确要求 AI 返回 JSON 格式,且必须包含引用代码片段。
  3. 二次校验:在代码中,拿到 AI 结果后,检查该行号是否真的在 Diff 的 validLines 集合中。
// 校验逻辑
const validLines = getReviewableLines(file.rawDiff);

if (!validLines.has(res.lineNumber)) {
  logger.debug('AI 返回了非变更区域的行号,跳过');
  continue;
}

💻 快速上手

项目已经支持 Docker 一键部署,无需复杂的环境配置。

1. 配置环境变量

新建 .env

# AI 配置 (支持 DeepSeek!)
AI_PROVIDER=openai
AI_BASE_URL=https://api.deepseek.com
AI_API_KEY=sk-xxxx
AI_MODEL=deepseek-chat

# 平台配置
GITHUB_TOKEN=ghp_xxxx
GITHUB_WEBHOOK_SECRET=xxxx

# 审查偏好
REVIEW_LANGUAGE=zh-CN
SKIP_DRAFT_PR=true

2. Docker 启动

docker-compose up -d

3. 配置 Webhook

在你的 GitHub/GitLab 仓库设置中,添加 Webhook 指向 http://your-server:4000/webhook,勾选 Pull RequestIssue Comment 事件。

搞定!🚀

🔮 总结与展望

这个项目目前已经具备了生产可用的能力:

  • 全自动化:从代码提交到审查意见生成,全程无感。
  • 低成本:通过 Draft 过滤和文件过滤,大幅节省 Token。
  • 交互性:ChatOps 让 Bot 变成了团队的一员。

未来计划 (Roadmap)

  • 接入本地大模型 (Ollama),实现数据不出内网。
  • 支持更复杂的上下文分析(引用分析、类型定义跳转)。
  • 生成周报/质量趋势图。

如果你也对 AI 提效感兴趣,欢迎 Star ⭐️ 和 PR

项目地址GitHub 传送门 - ai-code-reviewer (请替换为你的实际地址)


最后,求个赞!👍 你的支持是我更新的动力!