gitlab ci 的重试逻辑是作业级、同步、无状态的有限次重试,仅对 runner_system_failure 和 api_failure 触发,不适用于 script_failure;需配合脚本层指数退避、健康检查与可观测性建设,合理设 max_times(单元测试0次、集成2次、e2e3次)并告警最终失败。

GitLab CI 的重试逻辑是作业级、同步、无状态的有限次重试,不是“失败就重跑”,而是针对特定失败类型,在单次作业内最多执行指定次数(含首次),每次都是全新环境、不共享状态、不自动加延迟。
明确 retry 的适用边界
它只在当前 job 因 runner_system_failure(如 runner 崩溃、超时)、api_failure(如 GitLab API 调用失败)或网络类错误退出时触发;对 script_failure(脚本逻辑错误、断言失败、编译报错等)默认也会重试,但应谨慎关闭——这类失败通常反映代码或配置问题,重试无意义。
- 重试不保留缓存、环境变量、上一次输出,无法“续跑”
- 不感知网络抖动、限流或服务降级,也不自动插入 sleep
- 不能替代脚本内退避(如指数退避 HTTP 请求)、mock 降级或可观测性建设
按错误类型精准控制重试
避免“一刀切”,用 when 显式限定重试条件,把重试留给真正可恢复的场景:
- 仅对
runner_system_failure和api_failure重试,排除script_failure - 配合前置健康检查:在
script中先curl -f --max-time 5 https://thirdparty.com/health,失败则直接 exit 1 触发重试,比盲目执行测试更高效 - 示例配置:
retry:<br> max_times: 2<br> when:<br> - runner_system_failure<br> - api_failure
与脚本内容协同增强韧性
CI 层 retry 是第一道防线,但必须搭配脚本层措施才能形成可靠链路:
- 在测试脚本中使用带指数退避的 HTTP 客户端(如
retry-axios),而不是依赖 CI 重试来扛网络波动 - 检测到三方服务不可用时,自动切换本地 mock 或跳过非核心用例,避免阻塞流水线
- 记录每次重试前的响应码、耗时、错误摘要,上传截图/日志到对象存储,防止重试覆盖关键线索
合理设置重试次数与层级策略
次数不是越多越好,需结合测试类型权衡:
- 单元测试一般不设 retry(失败大概率是代码缺陷)
- 集成测试建议
max_times: 2 - 端到端(E2E)测试可设为
3,但务必在脚本中加入初始 delay 和请求退避 - 超过最大重试次数后应标记为“最终失败”,并触发告警,而非静默忽略











