极狐GitLab

代码评审找不到人?用 CODEOWNERS 自动指派审批人

极狐GitLab
2026年10月20日
10736
分享:

代码评审找不到人?用 CODEOWNERS 自动指派审批人

定义框:CODEOWNERS 是存放在代码仓库中的一个纯文本文件,用来声明"哪些文件或目录归谁负责"。它按行匹配路径与负责人(用户或群组),当合并请求改动了匹配路径下的文件时,平台会自动把对应负责人列为必需的审批人。它解决的是"谁来审"的归属问题,而不是"审得多严"的标准问题。

为什么评审总是找不到人

多数团队的合并请求卡住,不是因为争议大,而是因为发起人在群里问了一句"这个谁来 review 一下",然后等了两天。

问题的根源是评审责任的存放位置不对。常见的三种做法都有缺陷:

  • 靠口头约定:谁写的谁清楚,但人一离职、一转岗,知识就断档。

  • 写在 README 里:文档和代码是两套东西,README 更新频率远低于代码,三个月后必然失真。

  • 按最近提交者猜:看似合理,但最近改动某个文件的人,可能只是顺手改了个缩进,并不懂这个模块的业务逻辑。

做法

责任归属

失效场景

维护成本

口头约定

模糊

人员变动

高

README 记录

有记录无强制

文档滞后

中

按提交历史猜

有偏差

顺手改动

中

CODEOWNERS

明确且强制

规则写错

低

CODEOWNERS 的价值在于把"归属"从人脑搬进了仓库,并且让它成为一道可执行的门禁,而不是一条建议。

三步把审批人钉到目录上

第一步:在正确的位置建文件

CODEOWNERS 文件不是随便放一个就行,平台只认三个位置,并且找到第一个就停止查找,其余全部忽略。优先级顺序是:

  1. 仓库根目录 ./CODEOWNERS

  2. ./docs/CODEOWNERS

  3. ./.gitlab/CODEOWNERS

一个仓库只用一份。如果你的项目里同时存在根目录和 .gitlab/ 目录各一份,那么后者永远不生效——这是初学者最常踩的第一个坑。

第二步:按语法声明归属

语法是"路径 + 负责人"的一行一条规则。下面是一份可直接复制的示例:

# 默认兜底:任何文件都归架构组
*                    @arch-team

# 支付相关目录需要支付组 + 安全组双重审批
/payment/            @pay-team @security-team

# 基础设施即代码改动必须过 SRE
/terraform/          @sre-team
*.tf                 @sre-team

# CI 流水线配置归属平台组
/.gitlab-ci.yml      @platform-team
/ci/                  @platform-team

# 特定文件精确到人
/db/migrations/      @zhangsan @lisi

要点有三个:

  • 路径以 / 开头表示从仓库根目录匹配;*.tf 这种写法匹配任意目录下的该后缀文件。

  • 负责人可以是 @username,也可以是 @group-name,一行可以并列多个,需要全部通过才算满足。

  • 后匹配优先:如果某一行 * 兜底在前、具体目录在后,后面更具体的条目会覆盖前面的兜底条目。官方语义是"使用最后匹配的条目",所以兜底行必须放在文件最顶部。

第三步:在受保护分支上启用

这一步是绝大多数人漏掉的。CODEOWNERS 文件本身不会强制任何事,它只是声明。要让声明生效,必须同时满足两个条件:

  • 合并请求的目标分支是受保护分支;

  • 该受保护分支上启用了"需要代码所有者审批"。

配置路径:项目 → 设置 → 仓库 → 受保护分支 → 选中 main → 打开「需要代码所有者审批」。

落地前必须知道的 5 个坑

坑 1:权限够大的人可以整条链路绕过。 如果某个账号在受保护分支上拥有"允许推送并合并"权限,它可以直接推到分支、完全跳过合并请求流程,CODEOWNERS 和受保护分支的审批要求一起失效。这类权限通常授予自动化账号和发布工具,务必定期审计名单。

坑 2:新文件不在 CODEOWNERS 里就没人管。 平台是把合并请求里改动的文件,去和目标分支上的 CODEOWNERS 做比对。新建的文件如果在目标分支上没有任何规则匹配,它就不触发任何代码所有者审批。想做到"每个文件都有人审",必须在文件顶部写一条 * 兜底规则。

坑 3:角色不够,审批不作数。 代码所有者审批规则对审批人角色有硬性要求:必须是开发者、维护者或所有者。计划者和报告者角色只能通过常规审批规则批准,不能作为代码所有者签字。这一点在把实习生或外部协作方加进 CODEOWNERS 时经常踩到。

坑 4:群组引用只认直接成员。 在 CODEOWNERS 里写 @group-name 时,只有该群组的直接成员具备审批资格,通过子群组继承而来的成员不算。层级嵌套深的组织在这里会突然发现审批人数量比预期少很多。

坑 5:规则写太细会变成审批地狱。 一个 200 行的 CODEOWNERS,每行三个人,一个跨模块改动可能同时拉进来七八个审批人,合并请求平均等待时间反而变长。建议按"目录级粗粒度 + 关键路径细粒度"配置,普通目录一个群组就够,只有支付、鉴权、基础设施这类高风险目录才叠加多重审批。

常见问题

CODEOWNERS 文件改了之后会立刻生效吗?

不会立刻对已打开的合并请求生效。规则来自目标分支上的 CODEOWNERS 文件版本,因此新规则只对之后创建或重新基于最新目标分支的合并请求起作用。已经打开的合并请求如果改动的文件在目标分支期间被移动或重命名,匹配结果也可能变化。

能不能要求某个目录必须两个人批准?

可以,但不是在 CODEOWNERS 里实现。CODEOWNERS 只负责界定"谁是所有者","需要几票"由合并请求审批规则控制。做法是在项目设置里配置审批规则,把所需审批数设为 2,再配合受保护分支上的代码所有者审批开关。

CODEOWNERS 和分支保护、推送规则是什么关系?

三者是互补而非替代:分支保护管"能不能往这个分支推",推送规则管"提交本身的格式与内容是否合规",CODEOWNERS 管"谁来审"。只有三者都配置,才构成完整的变更管控链条。

让评审归属变成代码的一部分

把责任写进仓库,意味着它会被评审、会被版本化、会被回滚,也不会因为某个人离职而消失。这是代码评审从"靠自觉"走向"可治理"的最小一步。

如果你的团队正在治理变更流程,可以先从一个高风险目录试点,跑两周看合并请求等待时间的变化,再决定是否全仓库铺开。