用 DeepSeek 给 Git 提交做自动 Code Review:从 0 落地一个本地 AI 审查流程

在这篇文章里,我们从一个空目录开始,搭建一套在 git commit 前自动调用 DeepSeek 做代码审查的工作流:

  • 使用 Node.js 脚本 读取本次提交的 git diff
  • 通过 DeepSeek Chat API 做代码审查,并按 严重程度分级
  • 在 pre-commit hook 阶段自动执行,有严重问题就阻止提交
  • 审查规则抽象为 rules.json 配置
  • 模型配置通过 .env.local 管理,方便本地开发
    你可以直接把这里的方案搬进自己的项目。

场景与目标

问题:团队日常开发中,Review 资源有限,小问题容易被漏掉,大问题又可能在合并后才暴露。目标:在每次 git commit 之前,让 AI 帮你快速过一遍变更,提前发现严重问题,并给出可执行的改进建议。我们设计的方案满足这些要求:

  • 只审查本次提交的已暂存改动(Staged Diff)
  • AI 按 严重 / 一般 / 建议 三个级别输出问题
  • 有严重问题时:阻止提交
  • 所有规则(关注点、文案、阻断策略)都写在 rules.json,后续可自定义
  • 模型 Key & 地址放在 .env.local,便于本地环境管理

项目初始化

在一个空目录(例如 AI-Codereview)下,我们先手写一个简单的 package.json:

js 复制代码
{
  "name": "ai-codereview",
  "version": "0.1.0",
  "description": "在 git 提交时调用 DeepSeek 模型进行代码自动审查的简单工具",
  "main": "scripts/deepseek-review.js",
  "bin": {
    "deepseek-review": "scripts/deepseek-review.js"
  },
  "scripts": {
    "review": "node scripts/deepseek-review.js"
  },
  "license": "MIT"
}

这里有两个点:

  • bin 字段:将来可以通过 npm install -g . 安装成全局 CLI,直接用 deepseek-review 命令。
  • scripts.review:方便本地调试,npm run review 即可执行审查脚本。

核心:DeepSeek 代码审查脚本

我们在 scripts/deepseek-review.js 里完成几件事:

  1. 加载 .env.local 和规则配置 rules.json
  2. 从 git diff --cached 读取当前已暂存的变更
  3. 构造一份带有「规则说明 + 输出格式」的 Prompt
  4. 调用 DeepSeek Chat API
  5. 解析 AI 输出中的 BLOCK: YES/NO,决定是否阻止提交

下面是部分代码实现结构:

js 复制代码
// 读取当前已暂存的 diff
function run(cmd) {
  return execSync(cmd, { encoding: "utf8" }).trim();
}

function getStagedDiff() {
  try {
    return run("git diff --cached --unified=0");
  } catch (e) {
    console.error("[deepseek-review] 读取 git diff 失败:", e.message);
    process.exit(1);
  }
}

// 构造 Prompt,把规则和输出格式喂给模型
function buildPrompt(diff, rules) {
  const focusList = Array.isArray(rules.focus) && rules.focus.length
    ? rules.focus.map((item) => `- ${item}`).join("\n")
    : "- 逻辑正确性与潜在 Bug\n- 边界条件与异常处理\n- 性能问题\n- 安全问题\n- 可维护性与可读性";

  const severeDesc = rules.severityLevels?.severe?.description
    || "可能导致功能不可用、数据损坏、安全漏洞或构建失败的问题。";
  const majorDesc = rules.severityLevels?.major?.description
    || "可以运行,但存在潜在 Bug、性能隐患或较大维护成本的问题。";
  const suggestionDesc = rules.severityLevels?.suggestion?.description
    || "风格、命名、结构优化、更优写法等。";

  const of = rules.outputFormat || {};

  return `
你是一个严格的资深代码审查专家,请审查下面这次 git 提交的变更 diff。

【审查重点】
${focusList}

【分级规则】
- 严重问题:${severeDesc}
- 一般问题:${majorDesc}
- 建议与优化:${suggestionDesc}

【输出格式(必须严格遵守,方便工具解析)】
${of.overview || "1. 总体评价(1-2 句)"}
${of.severe || "2. 严重问题(如果没有,请写"无严重问题")\n   - 【严重】描述问题 + 涉及的文件/大致位置 + 原因"}
${of.major || "3. 一般问题(如果没有,请写"无一般问题")\n   - 【一般】描述问题 + 涉及的文件/大致位置 + 原因"}
${of.suggestion || "4. 建议与优化(如果没有,可以写"暂无明显优化建议")"}

${of.blockRule || "5. 最终结论(只保留一行,且用英文 BLOCK 标记,必须大写):\n   - 若必须在提交前修复,请输出:BLOCK: YES\n   - 若允许提交,仅给出建议,请输出:BLOCK: NO"}

注意:
- 不要输出除上述格式以外的额外总结行。
- "BLOCK: YES/NO" 必须是独立一行,前后不要加其他字符。

下面是本次提交的 diff(统一 diff 格式):

${diff}
`;
}

// 调用 DeepSeek Chat API
function callDeepseek({ apiKey, baseUrl, model, prompt }) {
  return new Promise((resolve, reject) => {
    const postData = JSON.stringify({
      model,
      messages: [
        { role: "system", content: "你是一个资深代码审查工程师,擅长发现问题并提出可行建议。" },
        { role: "user", content: prompt }
      ],
      temperature: 0.2
    });

    const url = new URL("/v1/chat/completions", baseUrl);

    const options = {
      method: "POST",
      hostname: url.hostname,
      path: url.pathname,
      port: url.port || 443,
      headers: {
        "Content-Type": "application/json",
        "Authorization": `Bearer ${apiKey}`,
        "Content-Length": Buffer.byteLength(postData)
      }
    };

    const req = https.request(options, (res) => {
      let data = "";
      res.on("data", (chunk) => (data += chunk));
      res.on("end", () => {
        if (res.statusCode >= 200 && res.statusCode < 300) {
          try {
            const json = JSON.parse(data);
            const content =
              json.choices?.[0]?.message?.content ||
              json.choices?.[0]?.text ||
              "";
            resolve(content.trim());
          } catch (e) {
            reject(new Error("解析 DeepSeek 响应失败:" + e.message));
          }
        } else {
          reject(
            new Error(`DeepSeek API 响应错误:${res.statusCode} ${res.statusMessage} ${data}`)
          );
        }
      });
    });

    req.on("error", (err) => reject(err));
    req.write(postData);
    req.end();
  });
}

你可以直接通过修改这个文件来:

  • 调整审查关注点(例如换成「支付正确性」「权限控制」等)
  • 改写分级说明,贴近你们团队的规范
  • 修改输出格式,比如增加某个模块的专门小节
  • 切换默认阻断策略(blockOnSevereDefault)

模型配置通过 .env.local 管理

为了避免把 Key 写死在代码或 shell 配置里,我们采用 Next.js 常见的 .env.local 风格:

js 复制代码
# .env.local(不提交到仓库)
DEEPSEEK_API_KEY=你的_API_Key
DEEPSEEK_API_BASE=https://api.deepseek.com
DEEPSEEK_MODEL=deepseek-chat

# 是否在严重问题时阻止提交(1 阻止 / 0 不阻止)
DEEPSEEK_BLOCK_ON_SEVERE=1

脚本启动时会:

  1. 查找当前工作目录的 .env.local
  2. 解析每一行 KEY=VALUE,写入 process.env
  3. 如果系统环境变量里已经有同名 KEY,则以系统环境变量为准

这样做有几个好处:

  • 适合前端/Node 项目现有习惯
  • 可以按仓库存储不同 Key/配置
  • 不需要全局污染 shell 环境

Git Hook:在提交前自动执行审查

最后一步,把脚本接到 Git 的 pre-commit 阶段。

由于是拿本项目来执行验证的这里使用 .githooks/pre-commit + core.hooksPath 的方式,方便版本管理。

在项目根目录创建 .githooks/pre-commit:

js 复制代码
#!/bin/sh

# 简单的 pre-commit hook 示例:
# 在执行 git commit 时,自动调用 DeepSeek 代码审查脚本。

echo "[pre-commit] 调用 DeepSeek 进行代码审查..."

node scripts/deepseek-review.js
STATUS=$?

if [ $STATUS -ne 0 ]; then
  echo "[pre-commit] DeepSeek 代码审查脚本执行失败或发现严重问题,终止提交。"
  exit $STATUS
fi

exit 0

然后在仓库里启用它:

shell 复制代码
git config core.hooksPath .githooks
chmod +x .githooks/pre-commit
chmod +x scripts/deepseek-review.js

从此以后,每次在这个仓库里执行:

js 复制代码
git add .
git commit -m "feat: xxx"

都会自动触发:

  1. pre-commit → node scripts/deepseek-review.js
  2. 脚本读取 git diff --cached
  3. 调用 DeepSeek → 按规则分级输出问题,并在末尾给出 BLOCK: YES/NO
  4. 如果是 BLOCK: YES 且当前规则/环境要求阻断 → 本次提交直接失败

审核示例

总结与一些延伸想法

到这里,我们落地了一套本地可配置的 AI Code Review 流程,特点是:

  • 与 Git 强绑定:在提交前提前拦截严重问题
  • 规则可配置:通过 rules.json 抽象了审查维度和分级
  • 模型可配置:模型信息放在 .env.local,符合前端/Node 生态的习惯
  • 行为可调:既可以强制阻断严重问题,也可以在开发早期只做「提示不阻断」

基于这套结构,你还可以继续扩展:

  • 针对不同分支(main / dev)选择不同的规则文件
  • 在审查结果中增加代码示例或重构建议模板
  • 将结果同步到 Git 平台(GitLab MR comment / GitHub PR comment)

由于工具当前只是 0.1.0 版本还有很多待改进的地方,后续将不断优化改进。

相关推荐
mldong7 小时前
你的 Vue3 项目也能有钉钉同款审批流设计器:npm 装包,10 分钟画出第一条审批流
前端·vue.js
2分钟速写快排7 小时前
什么是 RAG?如何用 RAG 实现一个用户记忆?
前端·后端·ai编程
passerby60618 小时前
如何自己造一个时间处理库
前端·javascript·github
走到天涯海角9 小时前
react里面的长列表渲染优化
前端·react.js·前端框架
小羊没烦恼!9 小时前
Hello Web API系列教程——Web API与国际化
java·服务器·前端·javascript·php
北岛贰9 小时前
迷茫焦虑期,我做了一个带支付带官网的 AI 聊天虚拟恋人 App
前端·人工智能·后端
mayaairi11 小时前
Vue2 组件通讯(三):全局事件总线、PubSub、插槽与组件实例属性
前端·javascript·vue.js
kyriewen11 小时前
面试官问我:AI 都能写代码了,前端凭什么还值 25K
前端·javascript·人工智能
风骏时光牛马12 小时前
AI源码分析:拆解模型底层实现逻辑
前端
IT_陈寒12 小时前
React子组件莫名其妙重渲染?你可能漏了这个Hook
前端·人工智能·后端