Codex接入GitLab后,MR自动审查会漏掉什么?

Codex Cloud 现在已经能接 GitLab。

OpenAI 8 月 19 日把 GitLab Support 放进 Beta:可以连接 GitLab Project、为项目创建 Codex Cloud Environment,从 Issue 或 Merge Request 里通过 @codex 发起任务,也可以做一次性或自动 Merge Request Review。

真正值得工程团队注意的,不是“终于支持 GitLab”这件事,而是官方明确写出的一个限制:

如果 GitLab 省略了 collapsed diff 或 oversize diff,Codex 就无法完成完整 Review。

这句话非常关键。

因为它揭示了所有 AI Code Review 系统都会遇到的一个边界:

模型没有看到的代码
不可能被可靠审查

但很多团队最后只看一个:

AI Review = PASS

却没记录:

它到底看到了多少 Diff?

Review Coverage必须是一级指标

假设一个 MR:

Changed Files: 42
Changed Lines: 5800

GitLab 为了性能折叠了一些大文件。

Codex 实际看到:

Files: 31
Lines: 3600

如果最终只输出:

No critical issues found.

这句话非常容易被误解成:

5800 行全部审过

所以每次 AI Review 应该附带:

Coverage

例如:

{
  "changed_files": 42,
  "reviewed_files": 31,
  "changed_lines": 5800,
  "reviewed_lines": 3600,
  "collapsed_files": 7,
  "oversize_files": 4
}

然后算:

file_coverage = 31 / 42 = 73.8%

不到阈值,Review 不应该标成:

PASS

而应该:

INCOMPLETE

我会把Review状态拆成四种

public enum ReviewStatus {
    PASS,
    FAIL,
    INCOMPLETE,
    ERROR
}

INCOMPLETEPASS 不是一回事。

例如:

PASS:
已经覆盖所有要求审查的文件,未发现阻断问题

INCOMPLETE:
存在未获取的 Diff,不能给出完整结论

UI 里也应该用不同颜色。

GitLab的大Diff为什么会消失

大型代码平台为了避免页面和 API 请求过重,会对:

超大文件
生成文件
二进制
大规模变更

做折叠或截断。

所以 Coding Agent 不能只依赖:

Merge Request Diff API

如果权限和工作流允许,Review Worker 最好有第二条路径:

Checkout Repository
↓
Base Commit
↓
Head Commit
↓
git diff

自己在工作区里算完整 Diff。

例如:

git fetch origin merge-requests/1842/head:mr-1842

git diff \
  origin/main...mr-1842 \
  -- .

这样至少不受 UI 折叠影响。

但“自己checkout”又引入了新的安全边界

如果 MR 来自不可信分支:

不要直接执行代码

Review 阶段只需要:

read repository
parse diff
static analysis

不要因为 Agent 想“验证一下”,就自动:

npm install
npm test

外部贡献的:

package.json
postinstall
Makefile
test script

都可能执行任意命令。

所以 Review Environment 最好分两级:

Level 1:
Read-only Diff Review

Level 2:
Sandboxed Validation

只有 Level 2 才允许运行构建和测试。

Webhook是另一个容易忽略的攻击面

OpenAI 的 GitLab 集成说明里提到:

GitLab-triggered activity
需要权限配置相应 Webhook

对于 GitLab Self-Managed 或 Dedicated,Workspace Admin 需要先配置连接,而且 Webhook Activity 要求:

GitLab 19.0+

一旦接上 Webhook,就意味着:

外部事件
可以触发 Agent

所以必须验证:

Webhook Signature
Project ID
Event Type
Branch
Actor

不能只看 JSON 里写:

{
  "object_kind": "merge_request"
}

就启动 Codex Task。

Webhook必须先去重

GitLab 重试 Webhook 是正常行为。

如果:

同一个 MR Event

触发两次 Agent:

两个 Review
两份评论
两次成本

所以需要:

Inbox

例如:

@Entity
public class GitLabWebhookInbox {

    @Id
    private String deliveryId;

    private String projectId;
    private String eventType;
    private Instant receivedAt;
}

处理前:

deliveryId 已存在
→ ACK
→ 不重复执行

自动Review不能绑定“每次push都全量重跑”

一个 MR 可能连续 Push:

10 次

如果每次都:

完整仓库 Review

成本很快上升。

可以做 Incremental Review:

previous_reviewed_sha
↓
current_head_sha
↓
git diff old...new

只审新增变化。

但安全相关规则可以全量重新跑。

例如:

Secret Scan
Permission Change
Dependency Change
Workflow Change

这几类应该每次重新检查。

我会把Review拆成三层

Layer 1:确定性规则

Secret
Dependency
License
Protected Path
Schema
Generated File
Binary

Layer 2:静态分析

CodeQL
Compiler
Lint
Type Check

Layer 3:LLM Review

逻辑
可维护性
边界条件
设计问题

这样不会把可以确定性发现的问题全部交给模型。

MR Review的上下文也不能无限塞

如果 5000 行 Diff 全交给模型:

上下文很贵
注意力也会稀释

更合理是先建立 File Risk Score。

例如:

risk = 0

if file in protected_paths:
    risk += 5

if touches_auth:
    risk += 5

if changes_sql:
    risk += 4

if lines_changed > 500:
    risk += 2

if test_file:
    risk -= 1

优先让 Agent 深审:

高风险文件

低风险格式化变更减少 Token。

一个MR Manifest

public record MergeRequestManifest(
        String projectId,
        long mergeRequestIid,
        String baseSha,
        String headSha,
        int changedFiles,
        int changedLines,
        Set collapsedFiles,
        Set oversizeFiles,
        String diffHash) {
}

Review Report 必须绑定:

baseSha
headSha
diffHash

否则 MR 新 Push 后,旧 Review 很容易继续显示:

通过

实际上已经过期。

Review必须有Stale状态

当:

current_head_sha != reviewed_head_sha

立即:

STALE

不要把旧 AI Review 当成当前版本结论。

public boolean isStale(
        ReviewReport report,
        String currentHeadSha) {

    return !report.headSha()
            .equals(currentHeadSha);
}

自动评论不要无限刷线程

AI Code Review 很容易生成大量:

“建议考虑……”

如果每个小问题都单独发评论,MR 会被淹没。

我会设置:

review:
  max_inline_comments: 8
  min_severity: MEDIUM
  low_severity: summary_only

Critical/High:

Inline

Low:

汇总

Review建议还需要“可验证”

好的建议:

AuthFilter.java:91

在 token 为空时这里会 NPE,
因为 line 87 的 getClaim() 可返回 null。

建议新增 test:
missing_subject_claim

差的:

“建议提高代码健壮性。”

生产 Review Agent 应该要求:

File
Line
Evidence
Failure Mode
Suggested Test

没有 Evidence 的评论降级。

自动Review不能拥有Merge权限

我不建议第一阶段让 Review Agent:

review + merge

放在同一个权限主体。

更合理:

Reviewer Agent
只产出 Review Decision

Merge Controller
读取:
CI + Human Approval + Policy
再决定 Merge

避免模型同时当:

裁判
+
执行人

一个最小MR Gate

merge-gate:
  ai-review:
    required: true
    minimum-file-coverage: 0.95
    allow-incomplete: false

  ci:
    required: true

  security:
    critical-findings: 0

  human:
    approvals: 1

如果 Diff Coverage 只有:

73%

AI Review 就算没有发现问题,也不能满足 Gate。

GitLab Self-Managed还要多一个版本检查

官方说明:

Webhook activity requires GitLab 19.0 or later

所以 Connector 初始化时就应该检查:

Server Version

不满足直接提示:

Webhook-triggered Codex tasks unavailable

不要等上线后才发现自动触发不工作。

我会做的12个测试

1. 正常 MR
2. Oversize Diff
3. Collapsed Diff
4. MR Push 后旧 Review 变 Stale
5. Webhook 重复投递
6. Webhook 签名错误
7. 外部 Fork 不执行构建脚本
8. 5000+ 行大 Diff
9. Protected Path 修改
10. 自动评论上限
11. GitLab < 19.0
12. AI Review PASS 但 Coverage 不足

Codex 支持 GitLab 以后,最容易产生的误区是:

“MR 已经有 AI 自动 Review 了。”

真正应该问的是:

AI 看到了多少?
Review 对应哪个 Commit?
有没有被折叠的 Diff?
Webhook 是否重复?
不可信代码有没有被执行?

OpenAI 明确写出“collapsed 或 oversize diff 会让 Codex 无法完成 Review”,反而是一件好事。

它提醒我们:

Code Review 的第一指标,不应该是模型写了多少评论,而是 Review Coverage 到底是多少。

没有覆盖率的“自动审查通过”,只能算一个建议,不能算一个发布门禁。


更多企业级 AI 应用、Agent、RAG 与模型工程化内容,我会继续整理在 智元界

https://www.zyentor.com/