首页
/ Flutter 仓库 CI 最佳实践指南:合入、标签、重跑与测试分片的高效策略

Flutter 仓库 CI 最佳实践指南:合入、标签、重跑与测试分片的高效策略

2026-09-06 18:16:29作者:滑思眉Philip

本篇指南围绕 Flutter 官方仓库中团队日常使用其内部 CI/CD 系统的高效技巧展开,内容取自仓库文档 docs/infra/Ci-Best-Practices.md。你可以学到:如何处理 "This branch is out-of-date" 提示、为什么优先用 auto-submit 标签代替手动点击 merge、revert 标签的正确打开方式、重跑测试套件为何优于全量重试,以及在 .ci.yaml 中新增/重命名/重新分片测试目标所要付出的真实成本与完整操作流程。

阅读前提:这是面向 Flutter 内部 CI 的补充指南

本文档是 Flutter 内部 CI/CD 系统的补充性实践建议,并非面面俱到的完整教程,而是把"如何尽可能高效"的实战经验沉淀成文。它约束的对象主要是 flutter/flutter 主框架仓库及其关联的 flutter 官方仓库(本仓库即对应框架源码与 CI 配置的镜像,根目录存在一份真实可查的 .ci.yaml,全文共 7800 余行,是本文所有分片讨论的实例来源)。

这套 CI 体系在 .ci.yaml 文件头部有自述:

# Describes the targets run in continuous integration environment.
# Flutter infra uses this file to generate a checklist of tasks to be performed
# for every commit.

即:每个提交都要按 .ci.yaml 里声明的 targets 清单执行一套任务检查。其中 flutter_drone recipe 会把 shard 键对应的分片委托给仓库内 dev/bots/test.dart 执行。相关的更多流程性文档位于 docs/infra/Adding-a-new-Test-Shard.mddocs/infra/Autosubmit-bot.mddocs/infra/Landing-Changes-With-Autosubmit.md,可作为本文的配套阅读。


"This branch is out-of-date" 并不(总是)意味着失败

当至少有一个 commit 被合并进 PR 的祖先分支时,GitHub 会自动生成 "This branch is out-of-date" 提示。在 Flutter 官方仓库中,这只是一条警告,并不会阻止合并,因此不必一看到它就着急 rebase。

但有两种边界情况需要合并/变基:

  1. 你的 PR 基于的那个 commit 恰好导致某个测试失败。如果祖先分支上已经合入了前向修复(forward fix)或 revert,建议 rebase 你的 PR 以纳入该修复,避免测试持续红。
  2. 你的 PR 基于的 commit 已经超过几天。为保证测试跑在最新代码之上,建议 rebase,让 CI 结果对当前主干有意义。

对照到本仓库的实际运作:flutter/flutter 在合并层面还有一套独立的 merge queue(自动提交队列)机制,相关设计见 docs/infra/merge_queue.md,与 GitHub 自带的过时提示是两套不同逻辑,勿混淆。

优先给 PR 打 auto-submit 标签,而不是点 "merge"

auto-submit 是一个特殊标签:打上后,当测试全部通过时,PR 会被自动合并(或排队等待合并)——在 flutter/flutter 的场景下是进入合并队列等待。这是官方推荐的合并方式,开发者无需守在电脑前盯着绿灯再手动点击。

如果有一个或多个测试失败,而你确信失败与你的 PR 无关(即属于 flake 偶发失败),请不要反复 push 空提交去触发全量重试,而应参考下文"优先重跑测试套件"一节处理。

auto-submit 背后的自动化逻辑由 Autosubmit bot 承担,其完整校验规则(代码评审数量、check run 状态、合并可行性、代码冲突检测)记录在 docs/infra/Autosubmit-bot.md,其典型工作流为:

  1. 提交 PR;
  2. 后台自动对改动运行大量测试;
  3. 开发者打上 auto-submit 标签,表示"测试通过后请自动合入";
  4. 全部校验成功后,bot 完成合并。

优先用 revert 标签回滚最近合入的提交

当合入的 commit 引发 CI 失败时,与其手动构造反向提交,不如用 revert 标签:该标签会触发自动创建一条回滚该 commit 的新 PR,且绕过大部分测试,以最快速度让树恢复绿色。

使用前必须满足两个条件:

  • 在 PR 上追加一条以 reason for revert: 开头的评论,例如:
reason for revert: This breaks the build, see XYZ link.
  • 与管辖该仓库的 Google 团队协调后再使用 revert 标签。因为并非所有场景都适合 revert,误用可能造成困惑。

Autosubmit bot 对 revert 请求还有额外约束(详见 docs/infra/Autosubmit-bot.md):发起人需为 flutter-hackers 团队成员;目标 PR 必须是 24 小时内合入的;必须提供以 Reason for revert: 开头的理由,否则标签会被移除。在 flutter/flutter 主仓库中,support_no_review_revert 通常为 true,即 revert 请求不强制要求先评审。

重跑单个测试套件,比全量重跑所有测试便宜得多

flutter/flutter 中,一次完整的全量测试运行要消耗 100~200 台虚拟机,耗时 30~60 分钟。这是极其昂贵的资源开销,应尽量规避。

而 push 一个新 commit,或点击 GitHub 内置的 merge 按钮,都会重新触发该 PR 的全量测试。有时确有必要,但大多数场景下,只重跑一个(或少数几个)失败的测试套件,成本要低得多。

实操建议:对疑似 flake 的失败,优先进入失败任务的详情页使用"Re-run"按钮只重跑对应套件,而不是用空 commit 或改动触发的全量重跑。这与 docs/infra/Reducing-Test-Flakiness.md 中对偶发失败的治理思路一致——把资源留给真正需要验证的代码,而不是花在重复的绿跑上。

新增测试目标的成本:每个 target 都会独占一台 VM

Flutter 团队用于跑测试的资源是有限的。文档记录(截至 2025/05/23)flutter/flutter 的 presubmit 资源池大致为:

资源池 规模
Linux VM(Ubuntu) 约 301 台
ARM64 Mac VM(Mac-14) 约 131 台
Windows VM(Windows-10) 约 134 台

而用于真机测试的 device lab 资源比这些虚拟机组更加稀缺

新增一个测试目标(test target)意味着:整台 VM 将在克隆仓库、搭建测试基础设施、运行测试套件的整个时间段内被独占,通常耗时 15~30 分钟,部分集成测试甚至更久。虽然好的测试套件很重要,但在新增 target 前请先自问:

  • 我的测试目标必须在多个平台上跑吗?
  • 是否存在尚未逼近超时上限的既有测试目标,可以把测试加进去,从而复用同一台 VM?

在批量新增测试目标、或拿不准如何组织时,建议先咨询基础设施团队(team-infra)。真实配置形态可对照根目录 .ci.yaml:例如其中 Linux snippetsLinux flavors_test_linux 等 target 均显式携带 bringup: true,且通过 properties.shard 声明分片、通过 runIf 声明触发条件、通过 timeout(单位分钟)约束运行时长——每新增一行这样的 target,都意味着资源池多一份长期占用。

重命名/重新分片测试的成本:为什么可能花掉 4 个 PR

本节建议仅适用于 flutter/flutter 仓库。

由于测试基础设施的运作方式,重命名或重新分片(resharding)测试非常耗时,能不做就不做,必须做时也要谨慎协调。核心约束有三条:

  • 新分片必须先以 bringup: true 加入,这意味着它不会在 presubmit 中运行,postsubmit 阶段也不会触发树关闭
  • 分片稳定运行后要改为 bringup: false,这需要第二个 PR
  • 在主干(master)删除(或重命名)一个分片,会导致该测试在所有 release candidate 分支中被静默跳过;必须把 .ci.yaml cherry-pick 进每个 release candidate 分支才能恢复覆盖率。

场景示例:从 2 个分片扩到 3 个分片

假设已有配置如下(注意:每个 target 对应一个独立的 LUCI builder):

targets:
  - name: Linux web_tests_1_2
    shard: web_tests
    subshard: "0"
  - name: Linux web_tests_2_2
    shard: web_tests
    subshard: "1"

现在想增加到第三个分片(实质上是重命名所有 target):

targets:
  - name: Linux web_tests_1_3
    shard: web_tests
    subshard: "0"
  - name: Linux web_tests_2_3
    shard: web_tests
    subshard: "1"
  - name: Linux web_tests_3_3
    shard: web_tests
    subshard: "2"

这需要以下步骤:

  1. .ci.yaml 中加入 3 个新分片,并各自设置 bringup: true
  2. 等待新分片稳定通过;
  3. .ci.yaml 中删除旧分片,并将新分片改为 bringup: false
  4. .ci.yaml cherry-pick 进每个 release candidate 分支以恢复测试覆盖。

整个过程最多可能需要 4 个 PR,并伴随与 release 团队的大量协调。

与官方"新增分片"流程的相互印证

Adding-a-new-Test-Shard.md 对"从零新增一个框架测试分片"给出了标准顺序,可与上文互相印证:

  1. 先在框架仓库的 dev/bots/test.dart 中注册新分片(对既有测试做分片则无需改动 test.dart);
  2. .ci.yaml 中新增对应 builder,确保 shardsubshard/subshards 属性与 test.dart 一致,并始终标记为 bringup: true(此阶段该 target 不会进 presubmit);
  3. 在 Flutter build dashboard 上观察新分片:连续 50 次无 flake 的绿跑后,flake bot 会自动开出移除 bringup: true 的 PR,使该测试具备阻止树的能力,并开始自动进入 presubmit(除非显式写了 presubmit: false)。flake bot 每周三运行一次。

注意:若新 target 是从既有 target 重命名而来,则无需走完整的 bringup 流程。

这些规则在本仓库根目录 .ci.yaml 中有大量活样例:例如 Linux snippets.ci.yaml 第 701 行附近)与 Linux flavors_test_linux(第 736 行附近)都处于 bringup: true 状态;而 Linux analyze(第 365 行起)则是一个未启用 bringup、直接以 shard: analyze 参与 presubmit 的常规 target。分片命名方面,Linux build_tests_1_5build_tests_5_5tool_integration_tests_1_76_7 等均采用 name: <平台> <shard>_<subshard> 的约定,与文档示例 Linux web_tests_1_2 的风格完全一致。


小结:让 CI 资源用在刀刃上

把本文要点浓缩为一份可直接照做的清单:

  1. 不要因为 "This branch is out-of-date" 而焦虑或强行 rebase——仅当基线 commit 引发测试失败或年代过久时才 rebase。
  2. auto-submit 标签等待自动合入,替代手动 merge。
  3. 需要紧急回滚合入问题时,走 revert 标签 + reason for revert: 评论,并先与 Google 团队协调。
  4. 遇到疑似 flake 的失败,只重跑对应测试套件,避免空 commit 触发全量重跑(一次全量 = 100~200 台 VM、30~60 分钟)。
  5. 新增测试目标前先评估:是否多平台必需?能否并入既有的非超时 target?必要时咨询 team-infra
  6. flutter/flutter 中重命名/重新分片测试代价高昂:新分片先 bringup: true、稳定后第二个 PR 改 bringup: false、删除分片还需向每个 release candidate 分支 cherry-pick .ci.yaml——最多 4 个 PR 的协调成本。

以上所有规则的最终落地都在根目录 .ci.yaml 这份真实配置文件中,配合 docs/infra/Adding-a-new-Test-Shard.mddocs/infra/Autosubmit-bot.md 等文档阅读,即可完整理解 Flutter 这套"由 .ci.yaml 声明、由 LUCI 调度、由 bot 自动合入"的 CI 运转模型。

登录后查看全文
热门项目推荐
相关项目推荐