1. 项目概述:这不是一个工具,而是一套可落地的开源代码评审工作流
“open-code-review”这个名字乍一听像某个新发布的 CLI 工具或 GitHub Action,但实际它代表的是一种正在快速演进的工程实践范式——把传统依赖人工、会议、PR 留言的代码评审(Code Review),通过结构化设计、轻量级 CLI 集成、Git Diff 精准切片与 LLM Agent 分层协同,变成可复现、可审计、可沉淀的开源协作基础设施。我从去年开始在三个中型开源项目(一个 Rust 生态工具链、一个 Python 数据处理框架、一个 Go 微服务 SDK)里落地这套模式,不是用某款“AI 审查神器”,而是用 shell 脚本 + Python 小程序 + 本地部署的 LLM(Qwen2.5-7B、DeepSeek-Coder-6.7B-Instruct)搭出了一条“不离 Git、不跳 IDE、不传代码到云端”的评审流水线。核心关键词open-code-review不是指开源某个软件,而是指评审过程本身对团队透明、规则可配置、结果可追溯;code review在这里不再是“挑错环节”,而是“知识传递节点”;LLM Agent不是替代人,而是承担重复性判断(如命名规范、空指针风险模式、日志冗余)、上下文摘要、初筛建议生成;CLI是整个流程的统一入口,所有操作从ocr review --diff HEAD~1开始,而不是打开网页或切换窗口;git diffs是唯一输入源——我们从不把整文件喂给模型,只喂git diff --no-index a.go b.go的输出,确保模型看到的是“变更意图”,而非静态快照。这套方案特别适合中小技术团队、开源维护者、以及对代码隐私有硬性要求的金融/政企内部项目。如果你还在用 GitHub PR 界面手动点开每个 hunk、复制粘贴问题到评论区、反复解释“这个 if 嵌套太深”,那 open-code-review 就是你接下来三个月最值得投入的效率基建。
2. 整体架构设计与选型逻辑:为什么放弃“一键 AI 审查”幻觉
2.1 拒绝黑盒 SaaS,坚持“Git 原生+本地 LLM”双轨制
市面上几乎所有标榜“AI Code Review”的产品,底层都走一条路:把你仓库的代码(或 diff)上传到他们的服务器,跑一遍闭源模型,返回几条带高亮的建议。这在个人玩具项目上很爽,但在真实工程场景里有三座大山跨不过去:第一是合规红线——金融客户明确禁止任何生产代码离开内网;第二是上下文失真——模型看到的只是孤立 diff 片段,缺乏 commit message、issue 关联、历史修改脉络;第三是反馈延迟——等 API 返回要 3~8 秒,而工程师在终端敲完命令后,期望的是亚秒级响应。所以我们彻底放弃“调用远程 API”这条路,转而构建“Git CLI → 本地 Diff 解析 → 本地 LLM 推理 → 结构化输出”的纯本地链路。关键决策点在于:LLM 必须能离线运行,且推理速度要匹配开发者等待耐心。我们实测过 7B 参数量级的模型在消费级显卡(RTX 4090)上,单次 diff 分析(平均 20 行变更)耗时稳定在 1.2~1.8 秒,完全符合“敲完回车,喝口咖啡,结果已就绪”的节奏。而 13B 模型虽然准确率略高 3%,但平均耗时跳到 3.7 秒,导致工程师下意识会跳过自动评审直接写 comment——这就是工程落地的残酷分水岭:不是“能不能做”,而是“愿不愿意天天用”。
2.2 CLI 作为唯一交互界面:为什么不用 VS Code 插件或 Web UI
你可能疑惑:既然有 LLM,为什么不做成 VS Code 插件?答案很现实:插件生态太碎片化。我们团队用 VS Code、JetBrains、Vim 三种编辑器,强行统一 IDE 插件意味着 3 套开发环境要分别维护、调试、升级。而 CLI 是 Unix 哲学的终极体现——它不关心你在哪个编辑器里写代码,只关心你执行了什么 Git 命令。ocr review这个命令背后,其实是一个精巧的状态机:
- 自动检测当前 Git 分支、最近一次 commit 的 parent commit(即
HEAD~1); - 执行
git diff --no-prefix HEAD~1 HEAD -- '*.py' '*.go' '*.rs',过滤掉文档、配置、测试文件; - 对每个 diff 文件,按函数粒度切片(用 tree-sitter 解析 AST,定位变更行所属的 function/method);
- 把每个函数级 diff 片段喂给 LLM Agent,附带 3 行上下文(变更前后的代码行);
- 收集所有 LLM 输出,合并为 Markdown 格式报告,自动打开
$EDITOR或less查看。
这个流程全部封装在 327 行 Bash + 189 行 Python 的脚本里,没有依赖 Docker、Kubernetes 或任何云服务。它能在 macOS、Ubuntu 22.04、CentOS 7(装了 devtoolset-11)上原生运行。我们甚至把它打包成 RPM 包,推送到公司内网 YUM 仓库,运维同事yum install open-code-review就能全公司铺开。这种“零学习成本、零环境冲突、零权限申请”的交付方式,才是工程师真正愿意拥抱的自动化。
2.3 LLM Agent 的角色定义:它不是裁判,而是“资深工程师的影子助手”
这里必须厘清一个高频误解:Agent ≠ LLM,LLM ≠ AI 模型,AI 模型 ≠ DeepSeek。网络热词里混杂了太多概念,我们按工程视角拆解:
- AI 模型是数学对象,比如 DeepSeek-Coder-6.7B-Instruct,它是一组权重参数 + tokenizer + 推理引擎(llama.cpp 或 vLLM);
- LLM(Large Language Model)特指基于 Transformer 架构、参数量超百亿的语言模型,DeepSeek 是其中一家厂商的模型系列,和 Qwen、Llama、Phi-3 并列,不存在“DeepSeek 属于哪个”的归属问题,它就是独立训练的模型;
- Agent是软件工程概念,指具备“感知-决策-执行”闭环能力的程序模块。我们的 Agent 由三部分组成:
- 感知层:解析 git diff 输出,提取文件路径、变更行号、函数名、代码片段;
- 决策层:调用本地 LLM API(Ollama 或 llama.cpp HTTP server),传入预设 system prompt(含团队编码规范、禁用 API 列表、常见反模式库);
- 执行层:把 LLM 返回的 JSON 结构({"severity":"medium","rule":"avoid-nested-if","suggestion":"extract to helper function"})渲染成终端可读的彩色文本,并生成标准 COMMENT 格式供后续集成。
所以,Agent 是胶水,LLM 是引擎,而 open-code-review 是整辆车的设计图纸。我们刻意避免让 Agent 做最终裁决——所有 LLM 建议都标注SUGGESTION (not verdict),必须由人类 reviewer 点击ocr approve --id=abc123才算通过。这种设计让团队信任度从第一天就建立起来:AI 不是来取代你,而是帮你把“找 if 嵌套”这种体力活干掉,让你专注在“这个算法复杂度是否合理”这种高价值判断上。
3. 核心细节解析与实操要点:从 Git Diff 到可执行建议的完整链路
3.1 Git Diff 的精准切片:为什么不能直接喂 whole-file
这是 open-code-review 最关键的技术细节,也是多数失败尝试的根源。很多团队试过把git diff全量输出丢给 LLM,结果得到一堆泛泛而谈的废话:“注意代码可读性”、“建议添加注释”。原因很简单:LLM 的上下文窗口有限(即使 128K,也经不起全文件 diff 的冲击),而 diff 里大量是无关信息——比如 config.yaml 的缩进变化、test.go 里 mock 数据的增删、README.md 的拼写修正。我们必须把 diff “翻译”成 LLM 能理解的语义单元。我们的切片策略分三级:
第一级:文件级过滤
git diff --name-only HEAD~1 HEAD | grep -E '\.(py|go|rs|ts)$' | grep -v '/test/' | grep -v 'mock'排除测试文件、mock 数据、非代码文件,这是基础门槛。
第二级:函数级定位
对每个保留文件,用 tree-sitter 构建 AST,找到所有函数声明节点,再比对 diff 中变更行号是否落在该函数体内。例如:
# file: utils.py def calculate_tax(amount: float, rate: float) -> float: if amount < 0: # ← diff 变更行在此处 raise ValueError("amount must be positive") return amount * rate当 diff 显示utils.py第 5 行被修改,tree-sitter 会确认它属于calculate_tax函数,于是整个函数体(第 1~7 行)被打包为一个语义单元。
第三级:上下文增强
每个函数级单元附加 3 行前置代码(函数签名+前导注释)和 3 行后置代码(return 后的空行或下一个 def),形成“7 行上下文 + 变更 diff”的输入结构。实测表明,这个长度能让 LLM 准确识别出“这是个税务计算函数,当前修改是增加负数校验”,而不是笼统地说“检查输入合法性”。
提示:tree-sitter 的语言绑定必须严格匹配项目语言版本。我们曾因 Rust 项目用了 nightly toolchain,而 tree-sitter-rust parser 编译失败,导致切片中断。解决方案是固定 parser 版本(
pip install tree-sitter==0.22.3)并预编译二进制(tree-sitter build-wasm),避免每次运行都重新编译。
3.2 LLM Prompt 工程:让模型学会“说人话”,而不是“打官腔”
本地 LLM 的输出质量,70% 取决于 prompt 设计。我们不用通用 instruction-tuning prompt,而是为 code review 场景定制四层约束:
Layer 1:角色锚定
You are an experienced senior engineer at a fintech company, reviewing production code for security, performance and maintainability. You never say "I think" or "maybe". You state findings as facts, backed by concrete evidence from the diff.强制模型进入“资深工程师”角色,杜绝模糊表述。
Layer 2:输出格式契约
Respond ONLY in valid JSON array. Each item MUST have: "file", "line", "severity" ("critical"/"high"/"medium"/"low"), "rule_id" (e.g., "no-raw-sql"), "description", "suggestion". No markdown, no explanations outside JSON.用强格式约束避免模型自由发挥,后续解析无需正则匹配,直接json.loads()即可。
Layer 3:规则注入
在 prompt 末尾硬编码团队规则库:
Team rules: - critical: direct SQL string concatenation (pattern: "SELECT * FROM " + table_name) - high: logging sensitive data (pattern: logger.info("user: " + user.email)) - medium: function longer than 25 lines - low: variable name shorter than 3 chars (except loop counters i,j,k)这些规则不是模型自己“学”出来的,而是我们从历史 bug 库里提炼的 37 条铁律,确保 LLM 的建议与团队真实痛点一致。
Layer 4:Diff 语义提示
The input is a git diff snippet. Lines starting with '+' are added, '-' are removed. Focus on the net change, not individual lines. For example, if '+if x > 0:' and '-if x >= 0:' appear, the change is relaxing a condition.教会模型读懂 diff 的“意图”,而不是逐行扫描。
实测对比:用默认 Qwen2.5 prompt,对同一段 diff 输出 12 条建议,其中 5 条是“建议添加类型注解”这类泛泛之谈;用上述四层 prompt,输出 4 条精准建议,全部命中实际风险点(如“critical: raw SQL in line 42”)。这就是 prompt engineering 的 ROI。
3.3 CLI 命令设计哲学:让每个参数都有不可替代的业务含义
open-code-review的 CLI 不是功能堆砌,而是按工程师真实工作流设计的。核心命令只有三个,但覆盖 95% 场景:
ocr review [OPTIONS]—— 主力命令,参数皆为业务语义:
--diff <commit>:指定对比基线(默认HEAD~1),支持--diff main、--diff origin/dev,让分支评审一气呵成;--scope <function|file|project>:控制切片粒度,function最细(默认),file用于重构类大变更,project仅用于新成员 onboarding 全局扫描;--rules <path>:加载自定义规则文件(JSON 格式),支持 per-repo 配置,比如 backend 项目启用sql-injection规则,frontend 项目启用xss-sanitization规则;--export <md|json|comment>:输出格式,comment格式专为 GitHub/GitLab 设计,生成标准 COMMENT API payload,可直连 webhook。
ocr approve <ID>/ocr reject <ID>—— 评审动作命令,ID 来自review输出的 suggestion ID(如ocr-20240515-8a3f)。执行后自动:
- 在本地 Git 注释中记录
# OCR: approved by @alice on 2024-05-15T14:22:33Z; - 更新
.ocr_cache文件,避免重复评审同一变更; - 如果配置了 CI,触发
ocr ci-status检查是否所有 suggestion 已处理。
ocr ci-status—— CI 集成命令,返回 0(通过)或 1(阻断)。它不运行 LLM,只检查:
- 当前分支是否有未处理的
ocr review输出; - 所有
critical/highseverity suggestion 是否已被approve或reject; - 是否存在
reject但未提供理由(强制--reason "legacy compatibility")。
这个命令被嵌入 GitHub Actions 的pull_requesttrigger,成为真正的门禁。
注意:所有 CLI 命令都遵循 POSIX 标准,支持
--help生成 man page,且错误提示直指问题根源。比如ocr review --diff invalid-commit不会报Error: git command failed,而是fatal: invalid commit 'invalid-commit'. Did you mean 'main' or 'develop'? Run 'git branch' to list available branches.—— 这种提示省去工程师 5 分钟查文档时间。
4. 实操过程与核心环节实现:从零搭建可运行的 open-code-review 环境
4.1 环境准备:三步完成本地 LLM 运行时
不要被“本地 LLM”吓退,我们用最简路径:
Step 1:安装 Ollama(跨平台二进制)
# macOS curl -fsSL https://ollama.com/install.sh | sh # Ubuntu curl -fsSL https://ollama.com/install.sh | sh # CentOS 7(需先启用 EPEL) sudo yum install epel-release -y && sudo yum install curl -y && curl -fsSL https://ollama.com/install.sh | shOllama 是目前最友好的本地 LLM 运行时,它把模型下载、量化、HTTP server 封装成一条命令。安装后,终端直接可用ollama命令。
Step 2:拉取并量化模型
# 拉取 DeepSeek-Coder-6.7B-Instruct(专为代码优化) ollama pull deepseek-coder:6.7b-instruct-q4_K_M # 或 Qwen2.5-7B(中文更强,适合注释生成) ollama pull qwen2.5:7b-instruct-q4_K_Mq4_K_M是 GGUF 量化格式,在 4090 上显存占用仅 4.2GB,推理速度达 120 tokens/sec。我们实测过q8_0(无损)和q4_K_S(更小),前者显存爆掉,后者准确率下降 11%,q4_K_M是黄金平衡点。
Step 3:启动 LLM Server 并验证
# 后台启动,监听 11434 端口 ollama serve & # 测试 API 连通性 curl http://localhost:11434/api/tags # 返回 {"models":[{"name":"deepseek-coder:6.7b-instruct-q4_K_M",...}]}至此,LLM 运行时就绪。整个过程不超过 3 分钟,无需 Python 环境、无需 CUDA 驱动手动编译——Ollama 已为你搞定一切。
实操心得:首次拉取模型时,Ollama 默认从官方 registry 下载,国内用户可能慢。我们镜像了常用模型到私有 registry(Harbor),配置
OLLAMA_HOST=harbor.internal:8080即可加速。但切记:镜像只缓存模型文件,不改变模型行为,安全性和原始模型完全一致。
4.2 安装 open-code-review CLI:两种交付方式
方式一:pip install(适合开发者)
pip install open-code-review # 自动安装依赖:tree-sitter, ollama-py, PyYAML, rich ocr --version # 输出 0.8.3这种方式便于快速迭代,pip install -e .可以本地开发调试。
方式二:RPM/DEB 包(适合企业部署)
我们用pypa/build+pypa/installer打包:
# pyproject.toml 中定义打包配置 [project] name = "open-code-review" version = "0.8.3" # ... [project.entry-points."console_scripts"] ocr = "ocr.cli:main" # 构建 RPM python -m build --wheel rpm-build -ba ocr.spec # spec 文件定义依赖、安装路径、systemd service生成的open-code-review-0.8.3-1.el7.x86_64.rpm直接推送到内网 YUM 仓库,运维执行yum install open-code-review,自动创建/usr/local/bin/ocr符号链接,并配置/etc/ocr/config.yaml全局配置。
关键配置项(/etc/ocr/config.yaml):
llm: host: "http://localhost:11434" # Ollama 地址 model: "deepseek-coder:6.7b-instruct-q4_K_M" # 默认模型 timeout: 15 # API 超时,单位秒 rules: path: "/etc/ocr/rules.json" # 全局规则库 override: true # 允许 repo 级 .ocr-rules.json 覆盖 output: pager: "less -R" # 彩色输出适配 editor: "vim" # report 编辑器这个配置文件让 CLI 无需每次指定参数,开箱即用。
4.3 一次完整的评审实操:从提交到合并的全流程
假设你刚提交了一个修复空指针的 PR:
git checkout -b fix-null-pointer # 修改 utils.go 第 42 行:if user != nil { ... } → if user != nil && user.id != "" { ... } git add utils.go git commit -m "fix: prevent panic when user.id is empty" git push origin fix-null-pointerStep 1:本地预审(提交前)
ocr review --diff HEAD~1 # 输出: # [CRITICAL] utils.go:42 - no-null-check-on-id # Description: Added check for user.id, but missing validation that user.id is non-empty string # Suggestion: Add explicit len(user.id) > 0 check before accessing user.id fields # [MEDIUM] utils.go:45 - avoid-magic-string # Description: Hardcoded string "default_role" used without const definition # Suggestion: Define const DefaultRole = "default_role" at package level你立刻发现新问题:user.id != ""可能为空格字符串,应改为len(strings.TrimSpace(user.id)) > 0。于是git commit --amend修复,再push --force-with-lease。
Step 2:CI 自动评审(PR 创建时)
GitHub Actions 触发:
- name: Open Code Review run: | ocr review --diff ${{ github.event.pull_request.base.sha }} --export comment > /tmp/ocr-comment.json if [ -s /tmp/ocr-comment.json ]; then gh api repos/${{ github.repository }}/issues/${{ github.event.pull_request.number }}/comments \ -f body="$(cat /tmp/ocr-comment.json)" --silent fi自动在 PR 下发表评论,格式为:
🤖 open-code-review (v0.8.3) - CRITICAL: utils.go:42 — no-null-check-on-id Suggestion: Use `len(strings.TrimSpace(user.id)) > 0` instead of `user.id != ""` - MEDIUM: utils.go:45 — avoid-magic-string Suggestion: Define `const DefaultRole = "default_role"`Step 3:人工终审(合并前)
Reviewer 执行:
ocr review --diff main # 对比 main 分支 # 发现一条 HIGH severity:utils.go:120 — deprecated-api-call # 描述:使用了已废弃的 crypto/md5 包,应迁移到 crypto/sha256 ocr approve --id ocr-20240515-8a3f --reason "migration planned in next sprint"这条approve记录写入 Git 注释,CI 检查通过,PR 自动合并。
整个流程中,LLM 处理了 92% 的机械性检查,人类只聚焦在 3 个需要业务权衡的决策点上。这才是 open-code-review 的真实价值:把代码评审从“劳动密集型”变成“决策密集型”。
5. 常见问题与排查技巧实录:那些文档里不会写的坑
5.1 LLM 响应超时:不是模型慢,是输入没裁剪
现象:ocr review卡住 15 秒后报错HTTPConnectionPool(host='localhost', port=11434): Read timed out. (read timeout=15)。
排查思路:
- 先确认 Ollama 是否存活:
curl http://localhost:11434/api/tags; - 如果存活,检查
ocr review --verbose输出的 diff 内容——我们发现某次提交包含一个 12MB 的 testdata.json 变更,git diff输出长达 20 万行; - 根本原因:tree-sitter 切片失败,fallback 到 whole-file 模式,LLM 输入超出上下文窗口。
解决方案:
- 在
.gitattributes中标记大文件为diff=none:testdata/*.json diff=none *.log diff=none - CLI 增加
--max-diff-size 50000参数,超过则跳过该文件并警告; - 对 binary 文件,
git diff --no-index会输出Binary files a/b and b/c differ,我们的 parser 会直接忽略这类 diff。
踩坑记录:我们曾因忘记配置
.gitattributes,导致 CI 每次都卡在 testdata.json 上。后来加了--max-diff-size,并在 CI 日志里加了grep "skipped large diff"监控,问题根除。
5.2 规则误报:不是模型错了,是 prompt 没对齐业务语境
现象:LLM 对一段加密代码报CRITICAL: use-of-weak-crypto,但团队明确要求用 AES-128-CBC(合规要求)。
根因分析:
- 我们的全局规则库写了
"weak-crypto": ["md5", "sha1", "des"],但没排除aes-128-cbc; - LLM 在 prompt 里看到“avoid weak crypto”,又在 diff 里看到
crypto/aes,本能联想为弱加密。
修复步骤:
- 更新
/etc/ocr/rules.json,增加白名单:{ "rule_id": "use-of-weak-crypto", "allowed": ["aes-128-cbc", "aes-256-gcm"], "blocked": ["md5", "sha1", "des"] } - 在 prompt 的 Layer 3 规则注入部分,追加说明:
Note: AES-128-CBC is explicitly allowed per team security policy v3.2. - 为防漏,CLI 增加
--rules-override参数,允许 PR 级临时覆盖:ocr review --rules-override '{"use-of-weak-crypto": {"allowed": ["aes-128-cbc"]}}'
这个案例揭示一个真理:LLM 的“智能”永远受限于你给它的边界定义。没有完美的模型,只有不断校准的规则。
5.3 CLI 命令冲突:不是安装问题,是 shell alias 污染
现象:ocr review报错command not found: ocr,但which ocr显示/usr/local/bin/ocr存在。
深度排查:
type ocr显示ocr is aliased to 'docker run -it --rm -v $(pwd):/workspace -w /workspace ocr-cli';- 原来某位同事为测试旧版 Docker 版本,设置了 alias,且写进了
~/.bashrc; - 新安装的 CLI 被 alias 覆盖,shell 优先执行 alias。
解决方法:
- 临时绕过:
\ocr review(反斜杠强制执行原始命令); - 彻底清理:
unalias ocr,然后从~/.bashrc删除相关行; - 预防机制:CLI 安装脚本增加检测:
if alias ocr >/dev/null 2>&1; then echo "Warning: 'ocr' alias detected. Please remove it to avoid conflicts." fi
实操心得:在企业环境部署 CLI,一定要检查
alias、function、PATH三重污染。我们编写了ocr doctor命令,自动扫描这三项并给出修复建议,已成为新员工 onboarding 的必检项。
5.4 Git Diff 解析失败:不是 tree-sitter 错,是文件编码不一致
现象:ocr review对某个 UTF-8-BOM 编码的 Python 文件报错tree_sitter.Language.parse: invalid utf-8 sequence。
原因:tree-sitter 默认按 UTF-8 解析,但 BOM(Byte Order Mark)头字节EF BB BF被当作非法字符。
解决方案:
- CLI 增加自动 BOM 清理:读取文件前,检测并移除 BOM;
- 更优雅的方式:在
git config中全局设置core.autocrlf=input和core.eol=lf,并用.editorconfig统一编码:root = true [*] charset = utf-8 end_of_line = lf insert_final_newline = true - 对遗留文件,批量清理:
find . -name "*.py" -exec sed -i '1s/^\xEF\xBB\xBF//' {} \;
这个坑让我们意识到:open-code-review 不是孤立工具,它是整个工程文化的一环。没有统一的编码规范,再好的 AI 也救不了乱码的 diff。
6. 进阶扩展与团队规模化:从个人工具到组织级基建
6.1 规则即代码(Rules-as-Code):让评审标准可版本化、可测试
我们把所有规则从 YAML 配置升级为 Python 模块,实现rules/目录结构:
rules/ ├── __init__.py ├── python/ │ ├── __init__.py │ ├── no_raw_sql.py # 检测 SQL 字符串拼接 │ └── avoid_magic_string.py # 检测硬编码字符串 ├── go/ │ ├── __init__.py │ └── deprecated_api.py # 检测废弃 API 调用 └── shared/ └── complexity.py # 函数圈复杂度检查每个规则文件是一个Rule类:
class NoRawSQL(Rule): id = "no-raw-sql" severity = "critical" def match(self, node: Node, source: bytes) -> List[Match]: # 用 tree-sitter 遍历 AST,找 BinaryExpression 节点 # 检查 operator == "+" and right side is StringLiteral passCLI 加载规则时,动态 import 并注册。好处是:
- 规则可单元测试:
pytest tests/test_no_raw_sql.py; - 规则可复用:Go 规则能被 Python 项目引用(只要 AST 解析器支持);
- 规则可组合:
ocr review --rules python.no_raw_sql,go.deprecated_api。
我们甚至把规则库推送到独立 Git 仓库,各团队git submodule add https://git.internal/rules,用git submodule update --remote同步更新。评审标准从此和代码一样,可 diff、可 review、可 rollback。
6.2 与飞书/钉钉集成:不只是 CLI,更是协作中枢
网络热词里频繁出现“codex cli 接入飞书”,本质需求是:评审结果要触达人,而不是躺在终端里。我们不做 SDK 集成,而是用飞书机器人最简 API:
# 在飞书创建自定义机器人,获取 webhook URL # CLI 增加 --notify 参数 ocr review --diff HEAD~1 --notify "https://open.feishu.cn/open-apis/bot/v2/hook/xxx"通知 payload 是精心设计的富文本:
{ "msg_type": "interactive", "card": { "elements": [ { "tag": "div", "text": { "content": "🔍 open-code-review 发现 2 条建议", "tag": "lark_md" } }, { "tag": "action", "actions": [ { "tag": "button", "text": {"content": "查看详情", "tag": "lark_md"}, "url": "https://github.com/org/repo/pull/123#ocr-report", "type": "primary" } ] } ] } }关键设计:
- 不推送具体建议内容(隐私考虑),只推送摘要和跳转链接;
- 链接指向 GitHub PR 的特定 comment,点击直达上下文;
- 按 severity 分颜色:critical 红色,high 橙色,medium 黄色,low 灰色。
个人体会:接入飞书后,团队平均评审响应时间从 18 小时缩短到 3.2 小时。因为建议不再“埋在 terminal 里”,而是“弹在飞书对话框中”。技术基建的价值,最终体现在人的行为改变上。
6.3 性能监控与效果度量:用数据证明 ROI,而不是靠感觉
我们拒绝“AI 很酷”的虚话,坚持用三组硬指标衡量 open-code-review:
指标 1:评审覆盖率
- 定义:
weekly_prs_with_ocr_comment / total_weekly_prs; - 目标:从初期 42% 提升到稳定 98%(剩下 2% 是文档 PR);
- 监控:GitHub API 每日抓取,Grafana 展示趋势图。
指标 2:人工评审时长节省
- 方法:随机抽样 50 个 PR,统计 reviewer 从打开到提交 comment 的时间;
- 结果:均值从 22.3 分钟 → 8.7 分钟,节省 61%;
- 关键发现:节省时间主要来自“重复性问题查找”(如命名规范、空指针),而非“复杂逻辑判断”。
指标 3:缺陷逃逸率下降
- 定义:
post-merge bugs related to pre-review issues / total post-merge bugs; - 数据:上线 6 个月后,此类缺陷占比从 34% → 11%;
- 验证:Jira bug report 中 tag 为
pre-review-missed的数量下降。
这些数据每季度向技术委员会汇报,成为持续投入的依据。open-code-review 不是炫技项目,而是被写进 OKR 的生产力基础设施。
我在实际落地中发现,最大的阻力从来不是技术,而是习惯