mcpField
D
diagnosing-ci-and-merge-bottlenecks

diagnosing-ci-and-merge-bottlenecks

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

关于 diagnosing-ci-and-merge-bottlenecks

这是面向工程团队和自主 Agent 的 CI 与合并瓶颈诊断技能,通过命名的 MCP 工具分析 PR 生命周期、工作流健康度和测试失败情况。它侧重聚合流水线状况,并明确数据的覆盖范围与局限。

主要功能

  1. 01查看开放及近期关闭的 PR
  2. 02比较 CI 工作流成功率与耗时
  3. 03追踪单个 PR 的生命周期
  4. 04筛选测试健康队列中的问题
  5. 05关联工作流、PR 与生命周期分析
  6. 06说明数据截断、延迟与缺失限制

适用场景

  1. 01发现运行缓慢或不稳定的 CI 工作流
  2. 02筛选 CI 失败或待处理的开放 PR
  3. 03定位 PR 生命周期中耗时的阶段
  4. 04评估测试隔离候选及影响

MCP 相关

该技能通过命名的 MCP 工具读取 GitHub 工程分析数据,包括 `pull-requests`、`workflow-health`、`pr-lifecycle` 和测试健康队列;使用者调用这些工具,而非编写 SQL。

安装

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

$npx skills add https://github.com/posthog/skills --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