Skip to content

[RFC] 关于优化 CI/CD 分级测试与配额控制的思考与讨论 #2363

Description

@cpunion

[RFC] 关于优化 CI/CD 分级测试与配额控制的思考与讨论

一、背景与思考

随着项目逐步演进,测试用例和构建链路逐渐丰富。在实际日常研发中,我们经常能观察到一个非常自然的开发习惯:很多开发者在写代码时会“一边开发一边频繁提交(WIP Commits)”

如果每次提交都默认拉起一整套多平台编译与重型测试,会导致两个明显问题:

  1. CI Runner 被频繁占用:中间过程的代码反复触发全量矩阵,不仅造成算力排队,而且对未成型的代码跑全量测试也是一种资源浪费。
  2. 算力与环境配额快速消耗:高频触发会迅速消耗 CI 额度以及构建环境(如 xgo-dev 等)的配额。

为什么参考 Rust 项目的 CI 做法?

Rust 项目(rust-lang/rust)覆盖了非常多的目标平台(70+ 架构),在处理大规模平台矩阵和大量社区提交时积累了很成熟的减负经验。虽然我们目前覆盖的平台没有他们那么多,但我们面向的业务领域复杂度高,未来潜在需要支持的平台与运行环境也在逐步增加

提前参考他们在“分级测试”与“资源节约”上的演进思路,有助于我们在当前阶段用较低的成本设计出一套轻量、清晰且易于扩展的 CI 体系。


二、Rust 项目的 CI 分级结构参考

Rust 团队的核心思路是**“把不同耗时、不同目的的检查按阶段拆开”**:

┌─────────────────────────────────────────────────────────────┐
│ 1. PR 提交阶段 (Fast Check)                                  │
│    - 仅运行格式化、静态检查、规范扫描与基础语法校验            │
│    - 耗时控制在 2~5 分钟内,快速发现基础问题                   │
├─────────────────────────────────────────────────────────────┤
│ 2. 决定 Review / 合并阶段 (Review-Approved Merge Queue)      │
│    - 仅在进入 Review 审核或准备合并时触发                    │
│    - 运行核心主流平台的相对完整测试(45~60 分钟)             │
│    - 批量打包合并(Rollup),避免每个小提交都跑完整测试        │
├─────────────────────────────────────────────────────────────┤
│ 3. 每日定时构建 (Nightly / Async Builds)                     │
│    - 每日凌晨在 master 分支触发                              │
│    - 运行全量目标平台的交叉编译、打包、长链路回归与文档生成    │
├─────────────────────────────────────────────────────────────┤
│ 4. 独立专项评测 (Crater / Benchmark)                         │
│    - 在专属环境中异步运行重型基准测试与全生态回归测试          │
└─────────────────────────────────────────────────────────────┘

这个结构的核心启示在于:日常开发提交只做极轻量检查,重型测试后置到 Review 或夜间定时执行,避免无谓的算力浪费。


三、适合我们当前规模的分级方案探讨

结合我们目前的业务特点和资源情况,建议可以尝试将 CI 划分为以下四个轻量层级:

1. PR 提交阶段:未决定 Review 前的快速检查 (Fast Check)

  • 触发时机:创建 PR 或日常 git push
  • 设计思路
    • 适应“边开发边提交”的习惯:默认只跑极轻量的 Fast Check,开发者即便频繁推送 WIP 提交,也不会过度占用 Runner 算力。
    • 培养 Fork 预跑习惯与 PR 模板引导:鼓励贡献者在自己的 Fork 仓库中完成自测与 CI 验证;在项目的 PR 模板(PR Template) 中加入自检清单(如:“已在个人仓库完成基础验证”),确认准备好后再申请正式 Review。
  • 执行范围
    • 代码格式化(Format / Lint)。
    • 基础语法与类型检查。
    • 核心模块的轻量快速单测(单平台,如 Linux)。
  • 目标2~3 分钟内给出即时反馈,杜绝语法和格式低级错误,几乎不消耗重型配额。

2. 决定 Review 阶段:相对完整的覆盖测试 (Review Check)

  • 触发时机:当 Maintainer 开始介入 Review,或通过标记(如打 ready-for-review 标签 / 评论指令 / Merge Queue)触发。
  • 执行范围
    • 全量单元测试与核心端到端(E2E)集成测试。
    • 主流目标平台的快速编译验证。
    • 关键业务链路的回归测试。
  • 目标:在真正准备合并前做充分验证,确保主干代码质量,避免过程中的重复测试开销。

3. 每日定时与异步检查 (Nightly / Async Full Matrix)

  • 触发时机:每日固定时间(如凌晨)或非高峰期定时执行。
  • 执行范围
    • 全平台完整交叉编译。
    • 耗时较长的端到端场景与深度压力测试。
    • 运行性能基准测试(Benchmark),并记录趋势数据。
  • 目标:在夜间业务闲时集中跑耗时任务,全面兜底兼容性与性能表现。

4. 减少 xgo-dev / CI 配额占用的实用措施 (Quota Optimization)

  • 路径变更过滤(Path Filtering):如果 PR 仅修改了文档、配置或非核心代码,自动跳过重型编译。
  • 依赖与构建缓存(Build Cache):开启 Go 模块缓存与构建缓存,避免重复拉取依赖与重复编译。
  • 交叉编译按需下沉:日常 PR 不触发多平台打包,仅在 Nightly 或 Release 发布时按需调用 xgo-dev 资源。

四、建议探讨交流的点

  1. 大家觉得当前链路中,哪些检查最适合保留在 PR 快速检查(3分钟以内),哪些适合移至 Review 阶段每日 Nightly
  2. 在 PR 模板中增加“在个人 Fork 仓库先跑通 CI”的引导,大家觉得是否合适?
  3. 在 Review 触发的形式上,大家更习惯哪种方式(例如:打 Label、发送评论指令、还是直接配合 GitHub 自带的 Merge Queue)?
  4. 在降低配额方面,优先开启构建缓存还是路径过滤?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions