GitHub 上做开源或团队协作的朋友基本都有一个共同感受:PR(Pull Request)审查就像项目的“质检关”,可这关过得实在不轻松。我最近在内部项目里捣鼓了一套基于 Hermes 智能体的自动化代码审查方案,把 GitHub PR 的审查流程从“人工肉眼盯 diff”变成了“智能体自动过一遍,人只留在最关键的设计决策环节”,效果比预期好不少。这篇文章就把整个思路、环境搭建、核心实现、实操过程和踩坑记录完整写一遍,适合那些 PR 量不小、又想守住代码质量底线的开发者和技术团队参考。
Hermes 在这里指的是一个可私有化部署的智能体(Agent)框架,它本身不自带“审查能力”,真正管用的是你在里面配置的技能(Skill)和审查规则。换句话说,Hermes 是一副骨架,你得往里面喂规则、喂上下文、喂 API Token,它才能帮你把 GitHub PR 里的问题一条条揪出来。下面我从头到尾拆开讲。
1. 为什么要把 PR 审查交给 Hermes 智能体
1.1 人工审查正在拖累团队的四个隐形问题
先说个真实场景。团队五个人,平均每个 PR 改动 300 行,reviewer 往往要花 30 到 60 分钟才能把代码看完、理解上下文、把意见写得有理有据。如果一天有 10 个 PR,光是等待审查和反复沟通就要占掉一个人半天的工作量。这还只是时间成本。
更麻烦的是标准不统一。老张强调代码要精简,小李重视注释完整,王姐盯的是边界条件,三个人审同一个 PR,给出的意见经常打架。新来的同事看了更崩溃,他不知道到底该听谁的,项目代码风格就这样慢慢变成了“四不像”。
还有一类低级错误特别容易逃过人工眼睛:比如密码硬编码、密钥泄漏进仓库、忘记处理空指针、依赖引入过期版本。这类问题在 diff 里有时候就一两行,reviewer 看快了很容易漏掉,但它们往往就是线上事故的导火索。
最后一个问题是上下文断裂。人工审查的时候,reviewer 不太可能主动去查这个 PR 涉及的历史背景、相关 issue、之前的设计文档,所以经常给出“只见树木不见森林”的意见。而这些问题,恰恰是自动化智能体最容易补齐的短板。
1.2 Hermes 智能体到底能做什么
我在第一次接触 Hermes 这类智能体的时候,第一反应是:“这不就是个能跑脚本的机器人吗?”后来配置完技能模块才发现,它的核心价值在于能把“工具调用”和“语义理解”结合起来。
具体的说,Hermes 能在 PR 触发后自动完成五件事:第一,拉取 PR 的元信息和完整 diff;第二,按文件类型和变更范围匹配对应的审查规则;第三,对新增或修改的代码做静态扫描,命中我们预设的规则库;第四,把 diff 和项目历史上下文丢给大模型引擎做语义层面的分析,判断逻辑缺陷、边界遗漏、设计一致性问题;第五,把结果以评论、行内注释或 Check 报告的形式回写到 GitHub。
它和传统工具的差别在于,SonarQube、ESLint 这类工具能查出“语法层面”的毛病,但对“这个函数在执行顺序上有个隐患”、“这块逻辑和项目里的缓存方案不一致”这类问题就无能为力。Hermes 因为接了语义模型层,恰好能把这两层能力叠加起来用,这才是自动审查真正的价值所在。
2. 环境准备:Hermes Agent 的安装与 GitHub 接入
2.1 Hermes Agent 部署方式怎么选
部署 Hermes Agent 这件事,不同团队诉求不一样,我建议按照规模来定,没必要一上来就上微服务。
最轻量的方式是本地安装。如果你是个人开发者或者三五人的小团队,直接在一台 Linux 服务器或者本地开发机上装 Hermes,用命令行启动一个 Worker 进程,让它监听仓库的 Webhook 或者轮询 GitHub API 就行。安装本身不复杂,准备好 Python 3.9+ 环境,拉取 Hermes 的发布包,配置好依赖,初始化仓库账号,基本上十分钟能搞定。
如果团队规模大一些、任务量重,推荐使用 Docker 部署。Hermes 官方仓库里带了 Dockerfile 和 docker-compose 配置,把应用容器、数据库(用来存历史审查记录)、队列组件(用来处理并发请求)一并编排好。这样做的好处是升级和回滚非常方便,而且 Worker 可以水平扩展。
两种方式的核心区别在于资源占用和管理成本。本地安装适合随时改代码、调试技能配置的场景;Docker 部署则更接近生产环境,适合稳定跑服务。我自己是先在本地把 Skill 调通,再打包成镜像扔到服务器上,两边不耽误。
2.2 打通 GitHub:Token 权限设计是安全底线
Hermes 要读 PR、写评论、更新状态,必须拿到 GitHub 的访问凭证。这里用到的标准方式是创建 Personal Access Token(PAT),但 Token 的权限范围一定要遵循最小化原则。
我踩过的坑是第一次图省事,勾了 repo 全权限,后来 Token 不小心被推到公开仓库,凌晨三点收到 GitHub 的安全告警邮件,那滋味真不好受。正确做法是:如果你只想读取 PR 信息和写审查评论,只勾选:repo(读)、pull_requests(写)、statuses(写)这三个范围。如果要走 Check Run 报告方式,还要加上checks: write权限。
Token 的存放也有讲究,不要硬编码在配置文件里,更不要提交到代码仓库。我通常用环境变量或者密钥管理服务来保存,启动 Hermes 时动态读入。GitHub 端到端传输用 HTTPS,配置里不要关闭证书校验。如果公司内部用的是私有化部署的 GitHub Enterprise,只要在 Hermes 配置里把github_base_url指向自己的域名就可以,其余逻辑完全一致。
2.3 审查规则文件:Hermes 的“大脑”从哪来
Hermes 最核心的部分是它的技能配置,也就是 Skill。刚接触的时候觉得这个概念有点虚,后来理解了:Skill 本质上就是一组“触发条件 + 审查动作 + 输出模板”的组合。
我的配置文件采用 YAML 格式,大致结构是这样的:
skills: - name: review_security trigger: file_patterns: - "**/*.py" - "**/*.js" event: pull_request rules: - id: RULE-001 description: "检查是否包含硬编码密钥" pattern: "(?i)(api[_-]?key|password|secret)\\s*[=:]\\s*['\"][^'\"]+" level: error - id: RULE-002 description: "检查是否使用不安全的函数" pattern: "\\b(eval|exec)\\s*\\(" level: warning model: provider: deepseek task: review temperature: 0.2 output: format: github_review_comment这个文件解决的是“谁触发、查什么、怎么查、结果怎么写”四个问题。很多团队上手 Hermes 之后觉得效果不好,大多是因为规则写得粗糙——规则太少漏报多,规则太严误报多,所以规则的迭代要做好长期的心理准备。
3. 核心实现:Hermes 自动审查 PR 的完整链路
3.1 用 GitHub Actions 把 Hermes 接入 PR 流程
Hermes 本身不直接挂在 GitHub 上,它需要一条“输入通道”。最推荐的方式是配置 GitHub Actions,在 PR 创建或更新时自动把事件推给 Hermes。
我在仓库.github/workflows/review.yml里写了这么一份配置:
name: Hermes PR Review on: pull_request: types: [opened, synchronize, reopened] issue_comment: types: [created] jobs: trigger-review: runs-on: ubuntu-latest if: | (github.event_name == 'pull_request') || (github.event_name == 'issue_comment' && contains(github.event.comment.body, '/hermes-review')) steps: - name: 通知 Hermes 审查 run: | curl -X POST https://your-hermes-server/api/review \ -H "Authorization: Bearer ${{ secrets.HERMES_API_KEY }}" \ -H "Content-Type: application/json" \ -d '{ "repo": "${{ github.repository }}", "pr_number": "${{ github.event.pull_request.number }}", "user": "${{ github.actor }}" }'这里有一个细节值得注意:我加了/hermes-review这个斜杠命令作为手动触发的开关。这样改动很小的 PR 不想走完整审查流程,reviewer 可以在评论区发一句/hermes-review skip跳过,或者主动指定让 Hermes 再查一遍。这也是一个比较讨巧的设计,避免机器人每次把所有 PR 都查一遍,引发开发者的逆反情绪。
3.2 Hermes 审查逻辑的四层拆解
Hermes 收到触发请求之后,内部实际是分层执行的。你可以理解为一条流水线,每一层只干一件事。
第一层是数据采集层。它先根据仓库名和 PR 编号调用 GitHub 的 API,拿回 PR 标题、描述、提交列表、文件变更列表,再逐个请求每个文件的 diff。注意 GitHub 的 diff 对大 PR 有限制,超过一定行数的文件可能拿不全,这个在 5.3 里我会详细说。
第二层是规则匹配层。它把 diff 按文件类型拆开,后缀名是.py就走 Python 规则集,后缀名是.js就走 JavaScript 规则集。这一步是纯静态扫描,不调模型,速度快、成本低。也就是说,规则匹配层的效率非常高,短则几秒,长则几十秒,就能把明显的安全问题、风格问题过滤出来。
第三层是语义分析层。这一步会把每个变更文件里相关的函数上下文、调用关系、最近的提交信息,甚至关联的 issue 标题都拼成一段结构化文本,然后发给大模型接口,让它判断逻辑漏洞、边界遗漏、设计不一致等问题。模型输出的 JSON 结果,会转换成标准审查意见。
第四层是输出层。Hermes 会把规则层和语义层的结果合并,按照文件、行号排序,过滤掉重复项,再通过 GitHub API 的createReviewComment和createCheckRun方法写到 PR 页面上。到这里,整个链路就完整跑通了。
3.3 审查结果怎么做到“可信任”
自动化审查最大的敌人是“狼来了”——如果机器人经常报一些废话、错报,开发者就会无视它的存在。所以我特别在意结果的可信度设计。
在 Hermes 里,每条规则命中后都会带一个置信度字段,这个字段是由规则类型和模型输出共同决定的。比如硬编码密钥这种模式匹配规则,置信度直接给 1.0;而模型分析出来的“可能存在逻辑问题”,置信度可能只有 0.6 到 0.8,这时 Hermes 不会直接给 error 级别,而是用 warning 级别输出,并且生成一段带推理过程的说明文字,方便开发者判断。
另外过滤机制也很重要。我在输出层配置了去重逻辑:如果两条规则命中的代码片段重叠超过 80%,只保留严重级别更高的一条;如果模型给出的意见和规则层重复,只保留规则层结果。这样可以基本杜绝同一个问题被机器人用两种方式反复提的情况。
4. 实操记录:一次完整的 PR 自动审查过程
4.1 典型配置实战:用 Docker 启动 Hermes 服务
以 Docker 部署为例,我先把整个服务编排好。注意到热词里有 “docker hermes” 和 “hermes 安装部署”,这里就重点演示一下容器化部署的操作。
项目根目录放一个docker-compose.yml:
version: "3.8" services: hermes-db: image: postgres:14-alpine environment: POSTGRES_DB: hermes POSTGRES_USER: hermes POSTGRES_PASSWORD: ${HERMES_DB_PASSWORD} volumes: - hermes_db_data:/var/lib/postgresql/data hermes-worker: build: . command: "hermes worker start" environment: HERMES_GITHUB_TOKEN: ${HERMES_GITHUB_TOKEN} HERMES_GITHUB_BASE_URL: ${HERMES_GITHUB_BASE_URL:-https://api.github.com} HERMES_MODEL_API_KEY: ${HERMES_MODEL_API_KEY} depends_on: - hermes-db hermes-api: build: . command: "hermes api serve --port 8080" ports: - "8080:8080" depends_on: - hermes-worker volumes: hermes_db_data:这套编排的核心逻辑是:API 服务负责接收 GitHub Actions 的 HTTP 触发请求,Worker 负责消费队列中的审查任务,PostgreSQL 用来存历史记录和状态信息。三个服务独立的部署方式,让后续扩容变得非常简单,比如审查量大时多起几个 Worker 就行。
启动命令就一行:
docker-compose up -d --build启动后可以用docker-compose logs -f hermes-worker看 Worker 的日志,确认服务已经连上 GitHub API。初次启动不出意外的话,控制台会打出一段初始化信息,表示技能配置已加载、模型接口连通性检测通过。
4.2 一次真实的 Python PR 审查执行记录
配置好之后,我在测试仓库开了一个 Python PR,故意注入三类问题:一个硬编码的数据库密码、一个使用eval()的代码片段、一段明显重复的函数逻辑。
PR 刚创建,GitHub Actions 的 workflow 就触发了,大约 5 秒后 Hermes API 收到请求,Worker 开始拉取 diff。整个处理过程我观察了日志,规则匹配层花了大约 1.8 秒,语义分析层花了 12 秒,最后结果回写到 GitHub。
最终 PR 页面上出现了三条评论:第一条是高亮的RULE-001命中,直接指出了password = "sk_live_xxx"这一行,级别是 error;第二条是RULE-002命中,指出eval(input())存在代码注入风险,级别也是 error;第三条是语义审查模型给出的意见,它提示我重构那段重复的验证逻辑,并给出了具体的合并建议。
整个过程从 PR 创建到审查完成,花了不到 20 秒。我让同事再人工审一遍,他基本只需要看那三条评论,十分钟之内就能把问题确认完。和之前动辄半小时起步的流程相比,效率提升是实打实的。
4.3 效率、成本和准确率的三方权衡
当然,自动化审查不是免费的。模型调用按 token 计费,规则匹配需要占用一定的 CPU,Docker 容器和数据库也要持续消耗内存。我统计了一下,一个规模为 500 行的 PR,一次完整审查大约消耗 8000 个输入 token 和 2000 个输出 token,按照当前市面上的模型定价,单次成本约合人民币几毛钱。
但这里有一个容易被忽略的经济账:如果人工审查一次需要 40 分钟,按开发人力成本折算下来,一次审查的人力成本少说几十元。让 Hermes 先用几分钟把 80% 的机械性问题扫掉,人工只专注于最关键的 20% 逻辑和设计问题,成本和效率的账是划算的。
准确率方面,我做了三个星期的测试,规则层的准确率非常高,几乎没有误报;模型层的误报率大约在 15% 左右,但只要把输出级别控制在 warning,并且附上推理过程,开发者的接受度还是相当高的。
5. 常见问题与排查技巧实录
5.1 容器化部署最常见的三个坑
Docker 部署 Hermes 时,最容易踩的坑是环境变量引用问题。docker-compose.yml里用了${HERMES_GITHUB_TOKEN}这样的变量,但如果你没有在 shell 里 export,Compose 会把它当成空字符串传入容器。结果就是 Hermes 启动正常,但调用 GitHub API 时一直报 401 认证错误。这个问题的排查方法很简单:在启动前用docker-compose config命令检查一遍渲染后的环境变量,确认值是否被正确替换。
第二个坑是网络代理问题。容器内部访问 GitHub API 时,如果宿主机处在受限网络环境下,需要使用代理服务,但容器本身拿不到宿主机的代理配置。解决办法是在docker-compose.yml里显式传入HTTP_PROXY和HTTPS_PROXY环境变量,这样 Hermes 才能通过代理正常访问外部 API。
第三个坑是数据库权限问题。PostgreSQL 容器初次启动时会创建数据库和数据目录,但如果数据卷的属主和容器内进程的 UID 不一致,会出现 Permission Denied 导致数据库一直重启。解决办法是在宿主机上把数据目录的权限改成 777,或者启动容器时通过--user参数指定对应的 UID。
5.2 漏报误报怎么治理
自动化审查跑起来之后,最怕两件事:该查的没查到,和不该报的老瞎报。从我的经验看,针对漏报,应该在规则层和维护策略上做文章,而不是一味增加规则条数。比如我每两周会从线上事故中提取一次关键词,把它们补充进规则库,形成“事故驱动”的规则迭代闭环。
针对误报,关键是给规则设置合理的级别和触发范围。比如某些规则只对核心目录生效,对测试目录直接豁免;某些警告级别的问题不要做成强阻塞,而是以建议形式在评论区列出。这样既能减少开发者对机器人的反感,也能保持规则的长期效力。
还有一个小技巧:遇到模型语义层给出的模糊意见,可以让 Hermes 在评论里追加一句“本条建议由 AI 生成,仅供人工 reviewer 参考”,并给出置信度数值。这么一个小小的改变,开发者的信任度提升非常明显。
5.3 GitHub API 限流与超大 PR 问题
GitHub 的 REST API 按每小时请求数做了限制,个人 Token 普通请求限制为 5000 次/时。单看数字似乎够用,但如果你启用了轮询模式,一分钟内扫一遍所有待审查 PR,高峰期很容易直接把额度打满。
我的解决方案是尽量采用 Webhook + Actions 的触发方式,而不是让 Hermes 持续轮询。这样只有 PR 真正变化的时候才消耗 API 调用,平时完全不占额度。另外,代码变更获取尽量用application/vnd.github.diff这种轻量化格式,减少不必要的元数据请求。
超大 PR 是另一个头疼问题。我碰到一次 PR 改了 3000 行,GitHub 返回的 diff 被截断,导致 Hermes 只分析了前一部分代码。解决办法是引入分页拉取逻辑,把超大的 diff 按文件或者按 commit 拆成多段,逐段审查、最后汇总。配置里也可以设置一个阈值,超过 2000 行的大 PR 不自动审查,改为人工触发,避免流程耗时太长和 token 成本飙升。
5.4 多语言项目的规则冲突处理
一个仓库同时包含 Python、JavaScript、SQL 和 Dockerfile 的项目,在规则层很容易出现“同一条规则在不同语言上的命中语义不同”的问题。比如eval()在 JavaScript 里是危险操作,在 Python 里同样危险,但它俩的上下文和修复建议不一样。
Hermes 的规则文件是按语言分目录配置的,千万不要把所有规则写到一个文件里。我在实践中用了这样的目录结构:
thinking/ # 这是规划目录,忽略实际上我用的结构是:
rules/ python/ security.yaml style.yaml javascript/ security.yaml style.yaml dockerfile/ best_practice.yaml触发时 Hermes 会根据文件后缀只加载合适的规则集。这样不但能避免不同语言之间的规则干扰,还让规则文件本身的维护变得简单清晰。
6. 值得一试的扩展方向与个人心得
整套 Hermes 自动化 PR 审查方案跑通之后,可以探索的扩展方向还挺多的。比如我把“审查历史”和“代码质量趋势”结合起来,每周生成一份各模块缺陷密度报告,定期发现哪些模块经常出问题,再反推代码重构优先级。Hermes 还可以对接飞书或钉钉机器人,审查完成之后把结论推送到即时通讯群,省去反复刷新页面的等待感。
从维护者的角度来看,我特别建议团队在铺开自动化审查时不要急着一口气吃成胖子。先选择一种语言、一类问题(比如安全漏洞)试点,跑两周看看团队接受度和误报率,再慢慢扩展规则范围。相比一步到位,这样循序渐进的方式反而更容易在团队里形成稳定的使用习惯。
最后再说一句实在话:Hermes 这类自动化审查工具,定位是给你干活、帮你扫雷,但真正决定代码质量的还是人的设计能力和责任心。把重复劳动交给机器人,把人从流水线上解放出来去思考更有价值的问题,这才是我们折腾这套自动化方案的初衷。