如何统计构建失败率与失败类型分布

统计构建失败率,先要定清三件事:统计哪些流水线和分支、取多长的时间窗、哪些运行算进分母。在此基础上计算三个指标:构建失败率(失败运行数÷有效运行总数)、失败类型分布(各类型失败数÷失败运行总数)、重跑率(重跑运行数÷有效运行总数)。三者合起来才能回答“构建是否频繁失败、失败集中在哪里、重跑是否掩盖了首次失败”,并据此判断是否需要启动专项治理。



要点总览(TL;DR)


  • 构建失败率=失败运行数÷有效运行总数,分母剔除被取消、人工中止和定时空跑等无效运行,统计前先固定流水线、分支与时间窗。
  • 失败类型分布同时给出两个口径:各类型失败数÷失败运行总数看结构占比,各类型失败数÷有效运行总数看对整体失败率的贡献。
  • 重跑率=重跑运行数÷有效运行总数,需与重跑成功率一起看,避免重跑通过掩盖首次失败和不稳定用例。
  • 判断是否需专项治理看四个信号:失败率水平与趋势、失败类型是否集中在少数可修复原因、重跑率是否偏高、失败是否阻断主干交付;不设通用达标线,以自身历史基线为参照。
  • 分母为零或样本过少时不下结论;流水线、分支策略或团队规模变化后需分段统计,失败率下降也不等于质量提升。


评估目标:回答“构建是否频繁失败”


这项度量服务于一个具体决策:当前构建失败是否已经严重到需要立项治理。它要回答三个层层递进的问题。第一,失败率有多高,在所选时间窗内失败运行占有效运行的比例是多少。第二,失败集中在哪些类型,是分散在各类偶发原因,还是集中在少数可修复的原因上。第三,重跑是否掩盖了首次失败,如果大量失败靠重跑通过,单看最终成功率会高估构建稳定性。


度量结果用于判断治理优先级和投入方向,不用于考核个人。把失败率挂到工程师绩效上,容易诱发隐藏失败、减少触发、绕过流水线等行为,反而让数据失真。评估结论应落到“哪类失败值得专项修复”这一层面。


统计对象需要在开始前写清楚,形成一份评估目标说明,至少包含:纳入的流水线清单(如主干构建、发布构建)、纳入的分支(如 main、release/*)、时间窗(如最近四周或某个版本周期)、三个待答问题,以及结论的使用场景。范围一旦确定,后续所有计算都以此为准,中途调整需分段统计。



指标与范围:失败率、失败类型分布、重跑率


三个指标各有分子分母,口径必须固定,否则不同周期的数据无法比较。下表给出定义与纳入排除规则。


指标 公式 分子 分母 单位
构建失败率 失败运行数 ÷ 有效运行总数 结果状态为失败的运行数 有效运行总数 百分比
失败类型分布 某类型失败运行数 ÷ 失败运行总数 该类型失败运行数 失败运行总数 百分比
类型对整体的贡献 某类型失败运行数 ÷ 有效运行总数 该类型失败运行数 有效运行总数 百分比
重跑率 重跑运行数 ÷ 有效运行总数 属于重跑的运行数 有效运行总数 百分比

有效运行是分母的核心。纳入范围为主干与发布分支上由代码提交、合并请求或手动发布触发的流水线运行。排除范围包括:被取消的运行、人工中止的运行、定时任务在无代码变更时的空跑、以及因流水线配置错误而未真正执行的记录。这些运行不反映构建质量,计入分母会稀释失败率。


失败类型分布建议同时给出两个口径。结构占比回答“失败里哪类最多”,类型对整体的贡献回答“哪类失败把总失败率推高了多少”。两者结合,才能判断治理某一类型能带来多大改善。


重跑率单独计算,含义是有效运行中有多大比例是重跑。与之配套的还有重跑成功率:重跑运行中最终通过的比例。重跑成功率高,说明首次失败中有相当部分可通过重跑绕过,常见于不稳定用例、环境抖动或依赖下载失败。这类失败在最终结果里被抹平,但交付节奏和排查成本仍在消耗,因此不能只看失败率。



数据口径与证据:从流水线记录到失败标签


统计的可靠性取决于原始记录是否完整、标签是否一致。建议从流水线系统导出运行级记录,每条运行保留以下字段:运行ID、流水线名称、分支、触发方式、开始时间、结束时间、结果状态、失败阶段、失败日志摘要、是否重跑、重跑对应的首次运行ID。运行ID用于去重,首次运行ID用于把重跑与原始失败关联起来。


失败类型需要一套可执行的分类。下表是一组常用类别及判定线索,团队可按自身技术栈调整,但同一时间窗内应保持稳定。


失败类型 典型判定线索
代码编译错误 编译阶段报错、语法或类型检查失败
单元测试失败 测试阶段断言失败、用例超时
依赖或环境问题 依赖下载失败、版本冲突、镜像或环境不可用
配置与脚本错误 流水线配置解析失败、脚本语法或参数错误
基础设施或资源不足 执行节点失联、磁盘或内存不足、配额超限
超时 阶段或整体运行超过设定时限
其他 无法归入以上类别

标签来源优先自动化:用失败阶段加日志关键字规则归类,例如编译阶段报错归入编译错误,测试阶段断言失败归入单元测试失败。规则覆盖不到的运行进入待人工复核队列,由固定人员按同一份判定说明处理,避免不同人给出不同标签。规则本身要版本化,规则调整后新旧数据需注明口径差异。


数据核验至少做两步。一是抽样比对,从流水线系统随机抽取若干运行,逐条核对统计表中的状态、类型与是否重跑,检查重复计数和状态缺失。二是完整性检查,确认时间窗内每个纳入流水线都有记录,排除因导出遗漏造成的分母偏小。核验发现的问题应回写到口径说明中,而不是在结果里手工修补。



计算与评估步骤:从原始记录到判断结论


计算流程可以固定为六步,便于每期复算和复核。


  1. 按时间窗导出运行记录,以运行ID去重,按纳入排除规则标记有效运行。
  2. 统计有效运行总数与失败运行数,计算构建失败率;统计重跑运行数,计算重跑率与重跑成功率。
  3. 按天或按周拆分,画出失败率与重跑率趋势,观察是否存在突变点。
  4. 对失败运行打标签,统计各类型次数,计算结构占比与对整体的贡献。
  5. 计算集中度:把各类型按失败次数排序,看排名前两三类合计占失败运行的比例。
  6. 结合阻断情况判断:失败是否频繁阻断主干合并或发布,是否造成交付延期。

判断是否构成专项治理问题,建议同时看四个信号:失败率水平及其趋势是否持续偏高或上升;失败类型是否集中在少数可修复原因;重跑率是否偏高、重跑成功率是否异常;失败是否实际阻断了主干交付。四个信号中若失败率趋势上升、类型高度集中、重跑率偏高同时出现,治理的投入产出比通常较高。单一信号不足以支撑立项,例如失败率略高但类型分散、多为环境偶发,更适合先做稳定性改善而非专项治理。


度量结果需要落到可跟踪的治理动作上。ONES 可集成 Jenkins、GitLab CI 等第三方流水线工具,自动同步编排的流水线数据并更新执行状态和日志,并把流水线与项目关联,在项目、迭代、需求中可视化代码提交、流水线构建、产品发布等 CI/CD 过程。团队可以把统计出的高发失败类型转为具体改进事项,在项目中跟踪修复进度,再用后续周期的同一口径数据验证失败率是否下降。具体报表字段与失败标签能力以实际产品配置为准。



算例:一个四周窗口的失败率与类型分布


以下数据为演示用示例,非真实实测结果。某团队统计主干与发布分支最近四周的构建运行,按前述规则去重并剔除取消、人工中止和空跑后,有效运行1200次,其中失败180次,重跑150次。


构建失败率=180÷1200=15%。重跑率=150÷1200=12.5%。若150次重跑中有120次最终通过,重跑成功率为80%,说明首次失败中有相当比例可通过重跑绕过,需进一步看不稳定用例和环境问题的占比。


失败类型分布如下表。


失败类型 失败运行数 占失败运行比例 占有效运行比例
环境与依赖 60 33.3% 5.0%
单元测试 45 25.0% 3.75%
编译错误 30 16.7% 2.5%
配置与脚本 25 13.9% 2.08%
超时 20 11.1% 1.67%
合计 180 100% 15.0%

解读:环境与依赖加单元测试合计105次,占失败运行的58.3%,属于集中可治理区间。这两类失败合计把整体失败率推高约8.75个百分点,若能将其中一半修复,失败率可下降约4.4个百分点。结合12.5%的重跑率,应优先核查环境与依赖类失败中是否存在可通过固定镜像、锁定依赖版本解决的部分,以及单元测试失败中不稳定用例的比例。该结论仍需对照历史基线:若前四周失败率为12%,则15%属于上升,治理紧迫性更高;若长期在15%附近波动且类型稳定,则更适合按类型逐个改善。



解读与限制:阈值、分母为零与指标误用


构建失败率没有通用达标线。不同团队的技术栈、测试密度、发布频率差异很大,套用外部阈值容易得出错误结论。可行的做法是以自身历史基线为参照,看趋势方向和突变点,再结合失败类型集中度判断是否值得投入。


分母为零或样本过少时不下结论。某个流水线在时间窗内有效运行只有几次,失败率会出现0%或100%的极端值,这类结果应标注样本不足,不纳入横向比较。同理,新接入的流水线在稳定运行一段时间前,数据参考价值有限。


前后数据不可比的情形需要分段统计:流水线结构调整、分支策略变更、构建时长或并发配置变化、团队规模明显变化,都会改变失败率的基线。跨这些节点直接比较会混淆口径变化与真实改善。建议在口径说明中记录变更时间点,统计时按变更前后分段呈现。


失败率下降不等于质量提升。失败率只反映构建环节的稳定性,若团队通过减少测试、放宽检查或频繁重跑来降低失败率,指标会变好而交付质量未必改善。因此需要结合缺陷逃逸情况、发布后问题数量和重跑率一起看。重跑成功率高尤其要单独跟踪,它往往指向不稳定用例或环境抖动,这类问题不会体现在最终成功率里,却持续消耗排查时间。把失败率、类型分布、重跑率与交付结果放在同一张评估表里,结论才站得住。



常见问题


统计构建失败率时,被取消和人工中止的运行应该计入分母吗?


不建议计入。被取消、人工中止、定时任务无代码变更时的空跑,以及因流水线配置错误而未真正执行的记录,都不反映构建质量。把它们放进分母会稀释失败率,让指标看起来比实际更好。有效运行应限定为主干与发布分支上由代码提交、合并请求或手动发布触发的运行,并在口径说明中固定下来。


失败类型标签由人工逐条打,还是可以自动归类?


优先用失败阶段加日志关键字规则自动归类,例如编译阶段报错归入编译错误,测试阶段断言失败归入单元测试失败。规则覆盖不到的运行进入待人工复核队列,由固定人员按同一份判定说明处理。规则本身要版本化,调整后新旧数据需注明口径差异,否则类型分布会因标签规则变化而失真。


重跑率多高算异常?只看失败率不够吗?


重跑率没有通用阈值,需要结合自身基线和重跑成功率一起看。重跑成功率高,说明首次失败中有相当比例可通过重跑绕过,常见于不稳定用例、环境抖动或依赖下载失败。这类失败在最终结果里被抹平,但排查成本和交付节奏的消耗仍在。只看失败率会高估构建稳定性,因此重跑率应单独计算并持续跟踪。


失败率连续几周上升,就可以启动专项治理了吗?


失败率上升是重要信号,但建议同时看另外三个条件:失败类型是否集中在少数可修复原因、重跑率是否偏高、失败是否实际阻断了主干合并或发布。如果失败率略高但类型分散、多为环境偶发,更适合先做稳定性改善;如果失败率趋势上升、类型高度集中、重跑率偏高同时出现,专项治理的投入产出比通常更高。单一信号不足以支撑立项。


统计结果和流水线系统里的记录对不上,一般是什么原因?


常见原因有三类:一是导出时遗漏了部分流水线或分支,导致分母偏小;二是重跑运行与首次运行没有通过首次运行ID关联,造成重复计数;三是结果状态字段存在缺失或口径不一致。建议做两步核验:随机抽取若干运行逐条比对状态、类型与是否重跑;再检查时间窗内每个纳入流水线是否都有记录。发现的问题应回写到口径说明中,而不是在结果里手工修补。