You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
CI perf: PR CI — 23% of full PR runs re-test unchanged diffs after a merge-main push (~20–30k Linux job-min/day, feeds the ubuntu-latest backlog) #1373
Window: 2026-10-09 16:16–20:16 UTC. Data: all 299 CIpull_request runs in the window (3 listing pages), plus job detail for 22 of them.
202 of the 299 runs were full runs: about 172 jobs, still running or lasting more than 6 min. The other 97 were draft or skip runs of 30 jobs, mostly skipped.
46 of the 202 full runs (23%) ran on a head commit that only merges main into the PR branch. The head commit's first line was Merge remote-tracking branch 'origin/main' into …, Merge branch 'main' into … or Merge main …. Two more were cancelled early.
With a merge queue, a PR doesn't need to be up to date with main. The queue re-tests every entry on top of the latest main before it merges.
Agent sessions still merge main into their branches after each landing, usually with no conflict. Each such push triggers the full PR tier again.
concurrency (cancel-in-progress on PRs) cancels only the superseded run on the same branch. It does nothing about the burst across about 80 branches.
Proposed fix
Two parts. Either one helps on its own.
CI side (M), in ci.yml's preflight / dispatch-tests job:
If the PR head is a 2-parent merge whose second parent is on origin/main, check whether the PR's own diff is unchanged. Compare git diff $(git merge-base origin/main HEAD) HEAD with git diff $(git merge-base origin/main HEAD^1) HEAD^1 by git patch-id --stable.
If it is unchanged, look up the newest CI run for HEAD^1. That is one REST read: actions/runs?head_sha=<HEAD^1>&event=pull_request.
If that run concluded success, emit an output (for example reuse=true) that makes the heavy jobs skip (if: needs.dispatch-tests.outputs.reuse != 'true'), the same way the draft tier skips today.
Otherwise run the full tier. That covers conflict resolutions, a failed or missing previous run, and API errors.
clippy keeps running, so a compile break from main is still caught on the PR.
Process side (S): in AGENTS.md, tell agent sessions not to merge main into a PR branch unless it has a conflict or needs a change from main. The merge queue already tests against the latest main.
Expected saving
About 23% of full PR runs during a post-landing burst. That is ~16k Linux + ~3k Windows job-min per 4 h at today's burst level.
Conservatively ~20–30k Linux + ~4–6k Windows job-min/day, since bursts follow each batch of landings.
Indirectly, it shrinks the ubuntu-latest backlog behind merge_group runs, which was the cause of the 77–81 min groups today.
PR feedback latency on a merge-main push drops from ~22 min (unloaded) to about 2 min (clippy plus preflight).
Coverage and risk
Every test still runs on the PR diff, on the previous head, and again in the merge queue against current main before merging. The skip applies only to a clean merge whose PR diff is byte-identical to a head that already passed.
ci-ok and clippy keep their names. Skipped needed jobs already count as passing in ci-ok.
Risk: a semantic conflict between main and the PR shows up only in the merge queue, about 20 min later, not on the PR. That is the same guarantee the queue provides today.
Risk: patch-id equality on a merge with conflict resolution. Any resolved hunk changes the PR diff, so the patch-id differs and the full tier runs.
Measurement
Window: 2026-10-09 16:16–20:16 UTC. Data: all 299
CIpull_requestruns in the window (3 listing pages), plus job detail for 22 of them.maininto the PR branch. The head commit's first line wasMerge remote-tracking branch 'origin/main' into …,Merge branch 'main' into …orMerge main …. Two more were cancelled early.agent/v5-nuget-mapping)agent/v5-nuget-lock-reader)ci/depot-linux-runners)agent/v5-cargo-stale-rlib)Where the time goes
mainmoved under them.ubuntu-latestqueue wait at p50 16.6 / p90 18.9 min at 19:00. Merge-group runs took 77–81 min instead of ~22 (see CI perf: ci-ok — waits 9–18 min for anubuntu-latestrunner whileubuntu-22.04starts in <1 min (merge-queue critical path, backlog hours) #1372 and CI perf (settings): merge queue builds 5 entries at a time — a 13-PR burst took 100 min to drain on a 21-min CI run (~21 min per PR past the 5th) #1248).Root cause
main. The queue re-tests every entry on top of the latestmainbefore it merges.maininto their branches after each landing, usually with no conflict. Each such push triggers the full PR tier again.concurrency(cancel-in-progresson PRs) cancels only the superseded run on the same branch. It does nothing about the burst across about 80 branches.Proposed fix
Two parts. Either one helps on its own.
ci.yml's preflight /dispatch-testsjob:origin/main, check whether the PR's own diff is unchanged. Comparegit diff $(git merge-base origin/main HEAD) HEADwithgit diff $(git merge-base origin/main HEAD^1) HEAD^1bygit patch-id --stable.CIrun forHEAD^1. That is one REST read:actions/runs?head_sha=<HEAD^1>&event=pull_request.success, emit an output (for examplereuse=true) that makes the heavy jobs skip (if: needs.dispatch-tests.outputs.reuse != 'true'), the same way the draft tier skips today.clippykeeps running, so a compile break frommainis still caught on the PR.AGENTS.md, tell agent sessions not to mergemaininto a PR branch unless it has a conflict or needs a change frommain. The merge queue already tests against the latestmain.Expected saving
ubuntu-latestbacklog behind merge_group runs, which was the cause of the 77–81 min groups today.clippyplus preflight).Coverage and risk
mainbefore merging. The skip applies only to a clean merge whose PR diff is byte-identical to a head that already passed.ci-okandclippykeep their names. Skipped needed jobs already count as passing inci-ok.mainand the PR shows up only in the merge queue, about 20 min later, not on the PR. That is the same guarantee the queue provides today.Effort
M for the CI side. S for the process side.
ROI
Saving ≈ (25k Linux ×1 + 5k Windows ×2) / 1000 = 35 × confidence 0.5 ÷ effort 2 = 8.8
Generated by Claude Code