mcpField
D
diagnosing-ci-and-merge-bottlenecks

diagnosing-ci-and-merge-bottlenecks

github.com/posthog云与 DevOps95177 次安装今天更新
代码仓库

关于 diagnosing-ci-and-merge-bottlenecks

面向工程团队的 CI 与 PR 合并瓶颈分析技能,使用命名工具查看工作流健康度、PR 生命周期和测试失败信号。适合诊断聚合层面的交付延迟,而非调查单个失败测试。

主要功能

  1. 01查看工作流成功率与耗时分位数
  2. 02筛选失败或待处理 CI 的 PR
  3. 03分析 PR 生命周期阶段耗时
  4. 04识别疑似或已确认的不稳定测试
  5. 05按来源和仓库限定分析范围

适用场景

  1. 01比较相邻时间窗口中的 CI 速度
  2. 02找出等待时间最长的开放 PR
  3. 03定位单个 PR 流程中耗时的阶段
  4. 04识别需要隔离处理的测试

MCP 相关

通过命名 MCP 工具读取 GitHub 来源、PR、工作流健康度和测试健康队列;不要求编写 SQL。

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/posthog/ai-plugin --skill diagnosing-ci-and-merge-bottlenecks

安装后在 Claude Code 中输入/diagnosing-ci-and-merge-bottlenecks确认已加载。

详细介绍

诊断 CI 和合并瓶颈

工程分析将拉取请求视为产品分析中的用户:PR 会经过一条流水线 (opened → CI → review → merged → deployed),任务是找出它在哪个环节变慢。表层是命名的 MCP 工具——调用即可,无需编写 SQL。已在 PostHog/posthog 上进行自用验证;同一套工具也适用于 自主 Agent(例如 PostHog Desktop),帮助它们分析自己的 PR。范围是流水线整体健康状况: 若要将某个失败的测试或红色运行追查至得出结论,请切换到 investigating-ci-failures 技能。

工具

  • pull-requests — PR 工作主力。列出开放的 PR,以及自 date_from(默认为 -30d)以来已合并或关闭的 PR,按时间倒序排列。每行包含 author(嵌套对象:handle、display_name、is_bot)、repo (嵌套对象:owner、name)、state、is_draft、labels、open_to_merge_seconds、ready_to_merge_seconds, 以及通过 head-SHA 联接汇总的 ci(runs / passing / failing / pending)。可解答大多数 PR 层面的问题:哪些 PR 的 CI 失败或仍在等待、哪些 PR 开放时间最长、按作者或仓库进行分类,以及合并耗时统计(自行对返回的已合并行计算中位数和 p95,绝不要计算平均值;若 ready_to_merge_seconds 非空则优先使用,因为它不包含草稿时间)。
  • workflow-health — 统计一个时间窗口内各工作流的 CI 健康状况(date_from / date_to,默认最近 24 小时): run_count、success_rate、p50_seconds、p95_seconds、last_failure_at。可解答“CI 正在变快还是变慢”,以及“哪个工作流耗时长或不稳定,成为瓶颈”。此功能不内置趋势分析——请针对两个相邻时间窗口分别调用并进行比较。success_rate 统计成功或以明确失败状态(failure、timed_out、startup_failure 或 stale)结束的运行,不包括跳过、取消、中性或需要采取操作的运行。p50_seconds / p95_seconds 仅统计成功的运行,因为取消和失败的运行会提前结束,从而导致时长趋势产生偏差。如果时间窗口内没有符合条件的运行,这些值均为 null——比较两个时间窗口前请先处理 null(某个工作流可能在一个窗口内有运行,在另一个窗口内则没有)。run_scope=pull_request 将范围限定为归属于 PR 的运行,不包括 master/main(仅限同一仓库的 PR——来自 fork 的运行没有 PR 归属信息)。
  • pr-lifecycle — 单个 PR 的时间线:一个标题,以及按顺序排列的事件——开放、转为可供评审和转为草稿(当 issue-events 表已同步时),接着是每次工作流运行对应的一对 CI 开始/结束事件(多工作流仓库中会有多组,按时间交错排列),最后是合并/关闭。可解答“PR N 卡在哪个环节”。metric_quality 为 partial(不包含评审或评论事件)。
  • engineering-analytics-flaky-tests — 根据逐测试的 CI 区间,在一个时间窗口内统计活跃的测试健康队列(date_from 默认为 -7d,最多 30 天)。证据按每次 CI 运行计数,绝不按区间或运行尝试计数。只有在证据能够证明存在非确定性时,classification 才为 confirmed_flake (same_commit_recovery_run_count > 0:同一提交在同一个矩阵任务中既未通过测试又通过了测试,例如通过“Re-run failed jobs”尝试后测试转为绿色,或通过任务内重试;在不同任务中通过,例如 FOSS 通过而 EE 未通过,不算恢复);quarantined 表示在屏蔽期间记录了一个可容忍的失败;suspected_regression 表示只记录了失败,这只是缺乏证据,并非真实故障的证据。符合以下任一条件的测试会进入队列:同一提交出现恢复、出现隔离失败、master/main 上出现任何失败,或至少在 min_failed_prs 个不同 PR 上失败(failed_pr_count)。可解答“这个失败的测试让我们付出了什么代价”,并筛选隔离候选项。它无法回答“哪些测试不稳定”:此队列只能检测主 Backend pytest 和 Frontend Jest 测试套件,且只有在有人重新运行失败的任务(或 pytest 测试被手动标记为 @pytest.mark.flaky(reruns=N))后,才能获得恢复证据。计数是绝对信号,而非比率:大多数通过的运行都不会被记录,因此不存在可信的分母。CI 配置故障会排除该次尝试的所有测试记录,而不仅仅是失败记录:如果某次运行尝试中有 3 个或更多任务的测试报错,或涉及 3 个或更多所属团队,或者某次任务尝试中有 100 个或更多不同的测试失败或报错。 影响范围如此广泛的真实故障也会被排除,因此当整个测试套件或任务都变红时,请查看 workflow-health,不要把空队列误认为状态健康。
  • engineering-analytics-sources:团队已连接的 GitHub 来源和仓库。如果有多个来源或仓库,请先调用此工具,并将所选条目的 source_id 和 repo 传给 pull-requests、workflow-health、pr-lifecycle 和 team-ci-health。只传 source_id 会读取该来源的默认仓库,而不是你所选的仓库。只有一个来源和仓库时,工具会默认使用它们。

没有汇总的合并耗时工具,也没有“计数”工具——请从 pull-requests 中推算这些数据(卡住或失败的数量、合并耗时百分位数)。

每次回答都必须说明的注意事项

这些是当前快照数据的结构性限制——请如实说明,不要掩盖。

  • open_to_merge_seconds 粒度较粗。 它将 草稿 时间和 准备好供审查 时间合并为一个数值。请称其为“从打开到合并”,切勿称为“周期时间”或“审查时间”。如果长期处于草稿状态的 PR 拉高了数值,请明确指出。
  • ready_to_merge_seconds 是更精确的对应指标:从最后一次观察到的准备好供审查状态转换时间到 merged_at 的时长(只计算最后一次草稿/准备就绪状态切换),或者对于可确认从未进入草稿状态的已合并 PR,计算从 created_at 到 merged_at 的时长。Null 表示“未观察到”(PR 的整个生命周期未完全落在已同步的问题事件窗口内,或该表尚未同步),绝不表示零。因此,只能对非 null 行进行汇总,并说明有多少行可观察。
  • CI 状态可能过时。 CI 来源按水位线同步,较新运行记录到达后,不会刷新随后才完成的运行(workflow_run webhook 推出前都是如此)。请将 pending 数量视为尚未定论,而非已确认的失败;先说明状态,不要急于下结论。
  • PR 的 CI 关联只通过头部 SHA 连接。 ci 汇总仅反映最新提交的运行记录。PR 与其检查项之间没有其他关联方式。
  • 选择延后读取审查数据。 GitHub reviews 端点会同步审查提交及其时间戳,但在楔形工具需要之前,读取操作会保持延后。请勿根据缺少这些数据推断审查行为。pr-lifecycle 因同样原因标记为 partial。
  • 部署指标位于 engineering-analytics-dora,数据来自 GitHub 部署表(已同步时由 deploy_data_available 表示)。其中的变更失败和恢复用时字段是部署状态的代理指标(未关联事件),请使用其准确字段名报告,切勿将其称为真正的 DORA 定义。
  • pull-requests 输出中包含机器人和草稿 PR,但按惯例会排除。 对吞吐量/合并耗时问题,请过滤掉 author.is_bot(嵌套在 author 下,不是行级字段)和 is_draft;对机器人影响问题,则应保留它们。
  • pull-requests 返回的页面有上限。 最多返回 1000 行,按最新优先排序:这是固定的服务端上限,会在响应中以 limit 回显,任何参数都无法提高此上限。当 truncated 为 true 时,你推算出的任何百分位数或计数都只涵盖最新页面,而非整个时间窗口。请说明这一点,然后缩小范围,直到实际数据集能完整纳入:author 可筛选单个账号,source_id/repo 可筛选单个仓库,date_from 可缩短时间窗口。

选择工具

问题工具使用方法
CI 是否变慢了?哪个工作流耗时最长?workflow-health在两个相邻时间窗口内调用(例如,先用 date_from=-14d,再用 date_from=-28d 和 date_to=-14d);比较每个工作流的 p50_seconds 和 p95_seconds。优先看中位数,但始终要单独检查 p95——两者的变化并不相关。
哪些未关闭的 PR 有失败或待处理的 CI?pull-requests保留 ci.failing > 0 或 ci.pending > 0 的行。pending 表示尚未结束(或已过时),并非已确定失败。
哪些 PR 开启后停留的时间最长?pull-requests保留 state = open、is_draft 为否且 author.is_bot 为否的行;按 created_at 升序排列(最早的在前)。
PR 合并需要多长时间?按作者统计呢?pull-requests对已合并的行(merged_at 已设置、非机器人、非草稿),汇总非空的 ready_to_merge_seconds(若为空,则使用 open_to_merge_seconds,并标注为粗略值),计算中位数和 p95。按 author.handle 分组,以了解各群组的情况,而非进行排名(对开发者进行监控明确不在目标之列)。调用时使用两个 date_from 时间窗口即可查看趋势。
PR N 卡在哪个环节?pr-lifecycle按顺序查看事件:opened → ready_for_review(存在状态转换事件时可得草稿耗时)、CI 阶段(首次开始 → 最后完成;每个工作流一组)、last CI finished → merged。最大间隔就是瓶颈。如果从就绪到合并耗时很长,但 CI 很快,说明时间花在审查或等待上;目前 partial 数据还无法细分这些耗时——请明确说明。
一次测试失败造成了多大损失?哪些测试应隔离?engineering-analytics-flaky-tests默认时间窗口为 -7d;各行已按影响范围排序(先列主干分支失败,再列影响到的不同 PR 数量)。报告数量,绝不报告比率。关于“是否为不稳定测试”,只有 confirmed_flake 行有确凿证据(同一个矩阵任务中,同一次提交既失败又通过**:重跑后通过,或任务内重试后恢复)。

高价值调查链路

模仿人工调查流程:汇总信号 → 确认问题 → 定位到具体 PR。

workflow-health  (find the slow/flaky long-pole workflow)
   → pull-requests  (confirm it's dragging merge time; list the affected PRs)
      → pr-lifecycle  (open a representative stuck PR and show the gap)

“CI 中位数上升是因为 e2e-playwright 的 p95 翻了一倍;该工作流是 PR #1234 的耗时瓶颈,该 PR 在 CI 中停留了 47 分钟才合并。”

输出预期

  • 首行给出结论,然后列出支持结论的数据。
  • 只要区分有意义,就注明数据粗略、部分缺失或可能过时。
  • 比较多个时间窗口或工作流时,优先使用简短表格,而不是文字说明。并列报告中位数和 p95 — 切勿将二者合并成一个“平均值”。

不要这样做

  • 不要将 open_to_merge_seconds 称为周期时间或评审时间 — 它是粗略的从打开到合并耗时; ready_to_merge_seconds 才是周期时间数据,且仅在值非空时适用。
  • 当 pending > 0 时,不要将 CI 数量报告为已确定的失败 — 结果可能尚未确定或已过时。
  • 不要推断评审或批准情况 — 在某个切入工具需要评审读取能力之前,评审读取仍暂不支持。不要推断单项检查的数量。部署数据来自 engineering-analytics-dora,不能靠推断得出。
  • 不要将按作者划分的数据桶做成排行榜 — 它们用于发现卡住的工作,而不是给人员排名。
  • 不要使用这些工具来获取原始 PR 内容或差异 — 它们提供的是流水线信号,而不是 PR 讨论串。

持久化答案

这些工具用于临时读取;无法将结果保存为洞察或订阅。当用户想将相同数据保存为洞察、仪表板磁贴或定时邮件 / Slack 投递时,请切换到 turning-engineering-analytics-into-insights 技能:底层数据仓库表 (<prefix>github_pull_requests / <prefix>github_workflow_runs,前缀来自 engineering-analytics-sources)可直接使用 HogQL 查询;该技能包含经过整理的列语义,以及创建洞察 / 创建订阅的工作流。

DORA 环境默认包含所有标记为生产环境或名称中包含 production 的持久环境。读取 selected_environments,以确认经过验证的确切范围。DRF 会根据真实名称验证显式筛选条件,包括临时环境。它会修剪并去重有效名称,对于空白或未知名称则返回 400 响应。省略筛选条件即可使用默认值。每个区域部署单独计数;前置时间会按每个 PR 在任一所选环境中的首次成功部署计算一次。

评论

支持 Markdown