Uber开源代码审查工具uReview:规则即代码,重塑PR审查流程
2026/9/9 15:27:06 网站建设 项目流程

提到“Uber uReview代码审查”这个项目名,很多人的第一反应是:Uber不是做打车的吗,怎么跑去搞代码审查工具了?其实Uber内部的技术氛围一直很浓,很多工程实践和工具链都相当扎实,uReview就是他们开源出来的一套偏工程化的代码审查辅助方案。代码审查这件事,几乎所有团队都在做,但真正做得好的没几个,uReview的核心思路是把“审查规则”变成仓库里可维护的配置,让每一次Pull Request的审查都走同一条标准流程,减少reviewer凭感觉发挥的空间。如果你带过团队、做过技术负责人,或者只是单纯想把自己仓库的审查流程规范化,这个项目值得研究一下。这篇就从一个实际使用者的角度,聊聊uReview的设计思路、部署方式,以及我踩过的坑。

1. 为什么代码审查这么难做好

1.1 代码审查的真正难点

代码审查这套东西,说简单也简单,说难是真难。简单的地方在于,看一个人的PR然后给反馈,谁都会;难的地方在于,不同的评审人看同一个PR,给出的意见可能天差地别。有的reviewer死磕命名,一个变量名能来回讨论好几轮;有的reviewer只关心主流程有没有bug,其他一概不管;还有的reviewer干脆只回一个LGTM,连代码都没细看。

这种差异带来的直接后果就是:审查质量完全取决于这次PR碰巧分配到谁手里。同一个改动,遇到严格的reviewer可能被打回重写,遇到宽松的reviewer可能一次就过了。团队里一旦出现这种情况,开发体验会很差,而且很容易引发矛盾——"你为什么这么针对我""我上次这么写不是也过了吗"。

我自己待过几个团队,这个问题几乎无解。定了审查规范也没用,规范是文档,文档是没人看的。真正能让规范落地的,要么靠人肉提醒,要么靠工具强制执行。uReview走的就是第二条路。

1.2 Uber碰到的实际问题

Uber在2017年前后重点建设支付业务的时候,是出了几次线上事故的。事后复盘的时候发现,很多问题根子上都出在代码审查这个环节——不是代码本身多难写,而是提交上来的代码经常带着明显的基础性缺陷,比如:

  • 改了数据库迁移脚本,但是忘了同步更新回滚逻辑
  • 新增了依赖库,但是没有检查license是否合规
  • 改了API接口,却没有更新对应的文档或者客户端SDK
  • 影响线上交易核心链路的改动,根本没有评估过灰度方案

这些问题单看技术含量都不高,但架不住多。每个PR都靠reviewer人肉去查,漏掉一个就是一颗雷。Uber的做法是把这些检查点固化成清单,每个PR都必须逐项确认,确认不了就不许合入。这个思路一开始是在支付团队内部用文档+人工勾选的方式试的,后来觉得太麻烦,就顺手写了个工具把它自动化了,这就是uReview的雏形。

1.3 uReview到底解决了什么

uReview解决的问题可以概括成一句话:把审查流程中“非主观判断”的部分用机制固化下来。代码风格好不好、架构设计合不合理,这类东西uReview管不了,那是reviewer的经验和水平问题。但“是否包含测试”“是否有数据库迁移”“是否修改了依赖”“是否需要更新文档”这类问题,是可以通过规则强制检查的。

工具的做法很简单:你在仓库里放一个规则配置文件,uReview读取这个文件,把里面的每一条规则对应到GitHub PR评论里的一个checkbox。reviewer打开PR,评论区顶部就是一份自动生成的审查清单,每条规则后面都有一个可以勾选的框。规则是写进仓库代码里的,和代码一起评审、一起变更,所有人都能看到,而不是躺在某个角落里吃灰的wiki文档。

2. uReview的核心设计:规则即代码

2.1 rules.yaml的结构拆解

uReview的使用核心是一个YAML配置文件,官方示例里一般叫rules.yaml。整个文件的结构非常直观,顶层是仓库级别的配置,然后往下就是一条一条的规则。每条规则由两部分组成:typeitems

type定义了这条规则的类别,目前支持的主要有requiredsupportinformationalrequired是强制项,审查人必须确认没有问题才能勾选;support是建议项,允许审查人跳过,但至少要过目一眼;informational就是纯提示,不需要审查人做任何操作,只是把信息带到PR评论里。

items是规则的具体清单项,每一项都是一个字符串描述,比如“确保所有异常都记录了日志”。当uReview跑起来的时候,它会把这个结构转换成PR评论里的检查列表,每条item对应一个checkbox。

repo: my-project rules: - type: required items: - Change includes tests - Change includes migration or rollback plan - type: support items: - Update README if user-facing behavior changed

上面这个例子就定义了一条强制规则(必须包含测试、必须包含迁移或回滚方案)和一条建议规则(如果影响了用户可见行为,需要更新README)。实际用下来,rules.yaml的写法没有任何黑魔法,就是一个普通的结构化配置,团队成员一看就懂。

2.2 uReview检查哪些内容

uReview本身不能被理解成一个静态代码分析工具。它不做lint、不跑测试、不扫漏洞,它做的事情可以理解为“上下文感知的审查助手”——根据PR涉及的文件和改动范围,决定哪些规则需要被激活,然后生成一份定制化的检查清单。

具体来说,uReview在运行时主要做这几件事:

  • 获取当前PR的元信息,包括标题、描述、变更文件列表、当前状态
  • 读取仓库根目录下的rules.yaml
  • 如果在PR描述里发现了特殊指令,比如跳过某些规则的标注,会识别并记录
  • 在PR上更新一条评论,把规则转成checklist展示出来

更贴心的一点是,uReview支持在规则描述里写一些模板变量,可以根据PR的实际信息动态生成描述。比如一条规则可以写成:“本次变更涉及{changed_files}个文件,请确认数据库迁移脚本已同步更新”。这样生成的checklist就带上了上下文信息,reviewer不用再去手动数文件,看起来更直观。

2.3 为什么用GitHub PR评论而不是独立网站

这里其实是一个很关键的产品决策。uReview完全可以做成一个独立的web服务,给每个PR生成一个审查链接,reviewer点进去勾选。但Uber选择了直接复用GitHub的PR评论作为交互载体。

原因很简单:降低切换成本。工程师的日常工作流里,Review PR的活动本来就发生在GitHub上,如果还要额外去另一个网站打开一个审查页面,这中间就多了一次上下文切换。而把checklist直接放在PR评论区,reviewer打开PR的同时就能看到全部规则,勾选也直接通过GitHub的评论操作完成,不离开当前页面,几乎没有适应成本。

这个设计思路其实很值得借鉴。很多团队做工具的时候喜欢造一个新入口,要用户打卡、登录、进入专属工作台,听起来很酷,但用户根本不会用。uReview把工具“放进”用户已经在使用的环境里,这种嵌入式的体验反而更容易被接受。

3. 从头到尾接入uReview的完整过程

3.1 前置条件说明

如果你想在自己的项目里用uReview,需要准备几样东西:一个GitHub仓库、一个能跑GitHub Actions的CI环境,以及一个具有PR读写权限的GitHub访问令牌。如果你们用的是GitHub免费版,只要仓库是公开的,Actions的免费时长足够跑uReview这种轻量级任务;如果是私有仓库,就需要确认一下套餐里包含的Actions分钟数。

除了GitHub之外,uReview官方实现里也有对GitLab等平台的支持计划,但实际成熟路径还是GitHub为主。所以如果你公司的代码托管在GitLab上,接入成本会略高一些。不过据我了解,目前网上也有一些基于uReview思路的自制适配方案,把同款checklist逻辑移植到GitLab MR上,这种属于二次开发了,不在原版能力范围内。

3.2 在仓库里添加rules.yaml

接入的第一步是在项目根目录创建rules.yaml文件。这里我给一个更完整的实际案例,以一个小型后端服务为例:

repo: payment-service rules: - type: required items: - Change includes unit tests for new logic - All error cases are handled or explicitly documented - Database migration has a rollback plan - No new dependency without license verification - type: support items: - Update API documentation for endpoint changes - Add metric or logging for new critical paths - type: informational items: - This PR includes changes to the payment module, please double-check

写这个文件的时候有几个点需要留意。第一,规则不要写太多,每个type下3到5条就差不多了。见过有团队把规则堆到20多条,结果reviewer根本没耐心逐条看,最后全变成走过场,还不如不搞。第二,规则描述要写清楚,一句话说清楚“要做什么”和“为什么”,不要出现类似“请检查代码质量”这种空洞的表述。第三,informational类型默认不需要勾选,但描述里最好带上具体的预警点,比如哪些模块被改动过、有什么风险,这样才有信息价值。

3.3 通过GitHub Actions触发uReview

配置文件准备好之后,就需要让uReview在每次PR打开或者更新时自动运行。这里用的是GitHub Actions,workflow文件大致长这样:

name: uReview on: pull_request: types: [opened, synchronize, reopened] jobs: ureview: runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 - name: Run uReview uses: uber-common/uReview@v1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

这个workflow的trigger事件是pull_request,并且在PR新开、代码更新、重新打开三种情况下都会执行。GITHUB_TOKEN用的是GitHub Actions内置的自动令牌,不需要额外配置secrets,只要仓库的工作流权限允许写PR评论就行。如果权限设置有问题,可以在仓库Settings -> Actions -> General -> Workflow permissions里勾选“Read and write permissions”。

跑完一次之后,你打开对应的PR,评论区底部就会出现一份uReview生成的checklist。后面的reviewer流程就变成这样:打开PR,看代码,对照checklist逐项确认,有问题的直接在评论里指出,没问题就把对应的checkbox勾掉。等所有规则都被确认之后,PR才允许合入。

3.4 如何强制规则必须被确认

防止reviewer漏掉检查项的机制,uReview是通过状态检查(status check)来实现的。默认情况下,uReview规则在PR评论里展示后,reviewer是不是真的勾了,uReview本身不会拦截合入。如果你希望做到“不确认就不许合入”,需要结合GitHub的branch protection rules。

你可以在仓库的Settings -> Branches里为main分支添加一个保护规则,把uReview对应的status check设为required。这样的话,只要uReview还没有跑完,或者规则里的required类型没有被全部勾选,PR就一直处于“checks未通过”的状态,合入按钮是灰的。

我团队实际用下来,这种“强制性”特别重要。规则写出来,如果只是发一条评论提示一下,那它跟普通评论没有区别,reviewer该跳过还是跳过。只有把规则变成合入的前置条件,大家才会认真对待。这一点在整个uReview的设计哲学里占了很重的分量。

4. 常见问题与排查技巧实录

4.1 规则没有出现在PR评论里

这是接入uReview时最常碰到的问题。workflow正常运行、Actions日志里也没有报错,但PR评论区就是看不到uReview生成的checklist。排查下来发现,大部分情况跟actions/checkout的版本有关。

如果checkout版本过旧,它默认只拉取当前PR的合并后代码,不会包含目标分支的最新状态。uReview在判断仓库配置的时候,就有可能读到旧版本的rules.yaml,或者读不到文件,从而选择静默跳过。解决方法是把checkout升级到v4,并明确指定fetch深度:

- name: Checkout code uses: actions/checkout@v4 with: fetch-depth: 0

另外还有一种情况:rules.yaml文件名大小写不对。Linux环境下的文件名是区分大小写的,如果你创建的其实是Rules.yaml,uReview在查找rules.yaml的时候就找不到。可以先在本地用ls确认一下文件名。

4.2 评论更新了但之前的勾选状态丢了

uReview每次在PR更新时运行,都会刷新一次评论内容。如果reviewer已经在旧版评论里勾选了一些checkbox,新评论生成后,这些勾选状态并不会自动保留。这在代码持续迭代的PR里会造成一点点体验上的摩擦——你刚勾完4项,对方push了一个小修改,uReview重新跑一遍,之前的勾都没了。

官方目前的策略就是直接覆盖评论,不迁就旧的勾选状态。我的建议是,如果PR改动比较大、需要多轮review,尽量让开发者在分支上少做琐碎的小修改,攒一批push一次;或者reviewer先把意见留在代码行级评论里,最后确认的时候再统一走uReview的checklist。这样勾选次数少一些,状态丢失的影响也就有限。

4.3 Status check状态与rules不匹配

接入branch protection之后,有些团队会遇到一种奇怪现象:uReview已经跑成功了,状态检查也显示绿色通过,但PR合入按钮还是被拦截。这种问题多数时候是因为保护规则里指定的check name和uReview实际上报的check name不一致。

GitHub的status check匹配看的是名称,你可以在uReview的日志里找到它上报的check name,比较常见的就是uReview。如果分支保护规则里填的是uReview / job-name,那就可能对不上。解决方法是在保护规则里把状态检查的名称改成日志里显示的那个,或者直接重新选择列表里已有的check。

4.4 规则老化后失去意义

uReview用得越久,规则列表越容易出现“僵尸规则”。比如团队已经明确不兼容某个老框架了,但rules里还有一条“确认兼容旧框架”的规则;又比如某个模块已经被废弃,但跟该模块相关的提醒规则还挂在informational类型下,每天出现在所有PR评论里。时间一长,reviewer对规则会逐渐麻木,本来有意义的规则也会被当成噪音。

建议每隔一两个季度做一次规则体检,把rules.yaml里的每一条规则都过一遍,问一个问题:这条规则现在还能挡住真实问题吗?挡不住的,删。挡得住的,想想能不能用自动化方式替代,能替代的就减掉,让reviewer把有限的注意力留给机器判断不了的东西。

问题类型症状解决方案
配置文件缺失或名称错误PR无评论,uReview日志无报错确认rules.yaml文件名、位置是否正确
checkout读取到旧代码评论内容与最新配置不符升级checkout到v4,设置fetch-depth: 0
check名称不匹配CI显示通过但PR仍被保护规则拦截校准保护规则中的check name
规则过多导致走过场reviewer不再逐条确认精简规则数量,每季度做规则体检

5. 把uReview用好的一些进阶建议

5.1 让规则跟着项目走而不是跟着人走

uReview最适合的落地场景,不是技术团队搞一个“通用审查规范”,而是每个仓库根据自身特点定义不同的规则。底层公共库的审查关注点,跟业务服务是完全不一样的;核心支付模块的关注点,跟内部管理系统也不一样。把规则放到每个仓库里,规则就跟着代码一起走,代码怎么演化,规则就怎么演化。

我见过一些团队想做一个“集团统一规则”然后把所有仓库都套上同一套uReview配置,结果就是每个仓库的PR评论区都出现大量跟自己无关的检查项,没多久大家就开始无视规则了。更合理的做法是,平台团队提供基础规则模板,各业务仓库按需裁剪和增补,保留真正相关的内容。

5.2 结合Code Owner实现分层审查

uReview管的是“必须确认哪些问题”,但它不负责“谁来确认”。这个问题可以跟GitHub的CODEOWNERS机制结合起来用。CODEOWNERS负责规定哪些目录的改动必须经过哪些人审批,uReview负责审查记录里必须确认哪些规则,两者一动一静,正好互补。

比如一个改动同时碰了backend/frontend/两个目录,通过CODEOWNERS,系统会自动把对应两个方向的负责人拉进来做review;而uReview的checklist会提醒后端负责人检查接口兼容性和回滚方案,提醒前端负责人检查API调用变更。这样分工明确,不会出现“所有人都review了,但每个人都在看自己懂的那部分”的假象。

5.3 从审查记录里挖出流程改进点

uReview产出的审查记录本身也是一笔宝贵的数据资产。每一条规则的确认记录,实际上反映了团队审查过程的执行情况。定期翻一翻这些记录,你会发现很多有意思的信号:比如某条required规则总是被最后一个确认,可能说明它不是被遗漏,而是大家真的不关心;比如某个模块的改动频繁触发“no test included”这条规则,可能说明相关开发者的测试基础设施不顺手。

顺着这些信号去优化流程,比拍脑袋定制度要有效得多。我自己操作过的一个例子是:某条“变更是否包含灰度开关”的规则老是被跳过,后来发现是这个团队的变更基本都是内部工具,根本不走线上流量,这条规则对他们来说就是噪音。后来把它从required降级到informational,周会里扯皮的情况明显少了。

好用的工具不需要太多花哨功能,把流程里最烦琐的那一环自动化掉,就已经能带来很大的效率提升。uReview的意义正在于此——它没做什么高深的技术,只是把“审查规则不落地”这个困扰无数团队的经典问题,用一个很直观的机制解决掉了。如果你正在为代码审查流程发愁,不妨先照这个思路把规则写下来,再用工具推着你往前走一步。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询