Skip to content

Commit 06bd098

Browse files
committed
Pair the torch-nightly triage by day against the pinned nightly
The triage only compared a torch-nightly build against a baseline that ran the *same commit* within 900s. That held while both fired in the same cron slot. It stopped holding when torch-nightly moved to 10:00 and the baselines stayed at 06:00/21:00 -- four hours of merges apart, they can never agree on a commit again. `find_latest_pair` walks newest-first and skips any nightly without a match, so instead of reporting nothing it silently pinned every run to the last same-commit pair, #82789/#82790 from 2026-08-07. The workflow kept succeeding and issue #8491 kept being told "still reproducing on #82789" while builds #83159, #83338 and #83539 went unexamined. The staleness was invisible: no failure, no warning, just an increasingly old build number. Two changes: - Pair on the same UTC day instead of the same commit. Over the last 21 days this pairs 12/12 torch-nightly builds versus 6/12 before, and on every day where the old rule found a pair it selects the same baseline -- so nothing regresses, the coverage gap just closes. - Prefer "Full CI run - nightly" over "Full CI run - daily", then closest in time. The plain nightly is the pinned-torch counterpart of the torch-nightly build: same pipeline, same schedule, differing only by TORCH_NIGHTLY=1. Under the previous time-first ordering 2026-08-10 would have compared against the daily (+5.8h) rather than the pinned nightly (-9.2h). The trade-off is real and deliberate: with different commits the pair is no longer a controlled A/B, and a regression may come from vLLM commits landing between the two builds rather than from torch. Reports now say which case they are. Same-commit pairs read as before; different-commit pairs get an explicit warning, the time gap, and both commits in the summary table, which now carries a commit column. Test plan: - Ran find_latest_pair against live ClickHouse build rows: now selects #83539 (2026-08-12 10:00, torch nightly) vs #83511 (2026-08-12 06:00, pinned nightly), -4.0h, same UTC day, commits differ. Before this change it returned #82789/#82790 from 2026-08-07. - Simulated the rule over 21 days of builds: 12/12 torch-nightly builds paired (was 6/12), every one against a "Full CI run - nightly" baseline, and identical to the old choice on all 6 days where the old rule found one. - Job-set sizes are comparable across the three build types (315-321 distinct job names), so the day-over-day comparison is not skewed by one build type running a materially different set. - Rendered a report both ways: different-commit pairs emit the warning, the +/-Nh gap and both commits; same-commit pairs are unchanged apart from the new commit column. - ruff check and ruff format --check clean. Authored with the assistance of Claude Code.
1 parent 434a25d commit 06bd098

1 file changed

Lines changed: 64 additions & 31 deletions

File tree

tools/torchci/vllm_torch_nightly_triage.py

Lines changed: 64 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,13 @@
1212
``0 14 * * *`` Full CI run - daily (none)
1313
=========================== ====================== =========================
1414
15-
On Mon/Tue/Thu the torch-nightly build and the plain nightly fire in the *same
16-
second* on the *same commit*, differing only by ``TORCH_NIGHTLY=1``. That pair is
17-
a controlled A/B: a job failing in the former and passing in the latter is
18-
attributable to torch nightly, with the vLLM variable held constant.
15+
The baseline is the closest scheduled run on the *same UTC day*. When the two
16+
fire in the same cron slot they also share a commit, which makes the pair a
17+
controlled A/B: a job failing in the former and passing in the latter is
18+
attributable to torch nightly, with the vLLM variable held constant. When the
19+
schedules drift apart the commits differ and the comparison is day-over-day
20+
rather than controlled -- still useful, but a regression may then be caused by
21+
vLLM commits landing between the builds. Reports flag which case they are.
1922
2023
This script finds the most recent such pair and reports the delta. It reads only
2124
job metadata from ClickHouse -- log *contents* are not ingested (the tables carry
@@ -40,14 +43,20 @@
4043
PIPELINE = "CI"
4144

4245
TORCH_NIGHTLY_MSG = "Full CI run torch nightly"
43-
# The plain nightly shares the torch-nightly cron slot; the daily is the fallback
44-
# baseline when a same-second sibling is missing.
46+
# The baseline is whichever of these ran closest in time on the same UTC day; the
47+
# plain nightly wins ties because it shares the torch-nightly cron slot.
48+
#
49+
# Same-commit used to be required as well. That holds only while the two share a
50+
# slot, and stopped holding when torch-nightly moved to 10:00 while the baselines
51+
# stayed at 06:00/21:00: four hours of merges apart, they can never agree on a
52+
# commit again. Requiring it silently pinned every report to the last same-commit
53+
# pair (2026-08-07) while newer builds went unreported.
54+
#
55+
# The trade-off is deliberate. With different commits, a job that fails here and
56+
# passes on the baseline is no longer attributable to torch alone -- intervening
57+
# vLLM commits are also in scope -- so reports say which case they are.
4558
BASELINE_MSGS = ("Full CI run - nightly", "Full CI run - daily")
4659

47-
# A build is only a valid control if it ran the same commit. Buildkite schedules
48-
# fire at the same instant but a commit can land between them in principle.
49-
SIBLING_WINDOW_SECONDS = 900
50-
5160
BAD_STATES = ("failed", "timed_out")
5261

5362
# Job names are frequently sharded ("Multi-Modal Processor (CPU) 1..4") or
@@ -80,9 +89,10 @@ def find_latest_pair(
8089
) -> Optional[Tuple[Dict[str, Any], Dict[str, Any]]]:
8190
"""Return (torch_nightly_build, baseline_build) for the newest complete pair.
8291
83-
Returns None when no torch-nightly build exists in the window, or when the
84-
newest one has no same-commit baseline (in which case there is nothing to
85-
compare against and reporting raw failures would be misleading).
92+
The baseline is the scheduled run closest in time on the same UTC day. Returns
93+
None when no torch-nightly build exists in the window, or when none of them ran
94+
on a day that also had a baseline (in which case there is nothing to compare
95+
against and reporting raw failures would be misleading).
8696
"""
8797
builds = _rows(
8898
client,
@@ -114,26 +124,27 @@ def as_dict(row: Tuple) -> Dict[str, Any]:
114124
if not nightlies:
115125
return None
116126

117-
# Walk newest-first rather than taking only nightlies[0]. Off-schedule
118-
# torch-nightly builds happen (manual triggers land outside the 06:00 slot and
119-
# have no sibling); stopping at the newest would let one of those mask the most
120-
# recent genuinely comparable pair.
127+
# Walk newest-first rather than taking only nightlies[0]. A torch-nightly build
128+
# can still land on a day with no scheduled baseline at all (manual trigger on a
129+
# weekend); stopping at the newest would then report nothing rather than falling
130+
# back to the most recent day that is comparable.
121131
for target in nightlies:
122132
candidates = [
123133
b
124134
for b in parsed
125135
if b["title"].startswith(BASELINE_MSGS)
126-
and b["commit"] == target["commit"]
127-
and abs((b["created_at"] - target["created_at"]).total_seconds())
128-
<= SIBLING_WINDOW_SECONDS
136+
and b["created_at"].date() == target["created_at"].date()
129137
]
130138
if not candidates:
131139
continue
132-
# Prefer the closest in time; ties favour the plain nightly (same cron slot).
140+
# Prefer the plain nightly over the daily, then the closest in time. The
141+
# plain nightly is the pinned-torch counterpart of this exact build -- same
142+
# pipeline, same schedule, differing only by TORCH_NIGHTLY=1 -- so it stays
143+
# the comparator even when the daily happens to have run nearer in time.
133144
candidates.sort(
134145
key=lambda b: (
135-
abs((b["created_at"] - target["created_at"]).total_seconds()),
136146
0 if b["title"].startswith(BASELINE_MSGS[0]) else 1,
147+
abs((b["created_at"] - target["created_at"]).total_seconds()),
137148
)
138149
)
139150
return target, candidates[0]
@@ -243,17 +254,39 @@ def render(
243254
agents = agent_concentration(regressed)
244255
top_agent_share = (agents[0][1] / len(regressed)) if regressed else 0.0
245256

257+
same_commit = tn["commit"] == base["commit"]
246258
out: List[str] = []
259+
if same_commit:
260+
out.append(
261+
f"**{len(regressed)} job(s) regressed** on torch nightly "
262+
f"[#{tn['number']}]({tn['url']}) versus baseline "
263+
f"[#{base['number']}]({base['url']}), both at commit "
264+
f"`{tn['commit'][:12]}`.\n"
265+
)
266+
else:
267+
# Different commits: the comparison is same-day, not a controlled A/B, so
268+
# a "regression" can also come from vLLM commits landing between the two.
269+
gap_hours = (base["created_at"] - tn["created_at"]).total_seconds() / 3600
270+
out.append(
271+
f"**{len(regressed)} job(s) regressed** on torch nightly "
272+
f"[#{tn['number']}]({tn['url']}) versus same-day baseline "
273+
f"[#{base['number']}]({base['url']}) ({gap_hours:+.1f}h).\n\n"
274+
f"> :warning: The two builds ran **different commits** "
275+
f"(`{tn['commit'][:12]}` vs `{base['commit'][:12]}`), so this is a "
276+
f"same-day comparison rather than a controlled A/B. A regression here "
277+
f"may be caused by vLLM commits landing between the builds rather than "
278+
f"by torch nightly.\n"
279+
)
280+
out.append("| | build | commit | outcome |")
281+
out.append("|---|---|---|---|")
282+
out.append(
283+
f"| torch nightly | [#{tn['number']}]({tn['url']}) "
284+
f"| `{tn['commit'][:12]}` | {tn['state']} |"
285+
)
247286
out.append(
248-
f"**{len(regressed)} job(s) regressed** on torch nightly "
249-
f"[#{tn['number']}]({tn['url']}) versus baseline "
250-
f"[#{base['number']}]({base['url']}), both at commit "
251-
f"`{tn['commit'][:12]}`.\n"
287+
f"| baseline | [#{base['number']}]({base['url']}) "
288+
f"| `{base['commit'][:12]}` | {base['state']} |"
252289
)
253-
out.append("| | build | outcome |")
254-
out.append("|---|---|---|")
255-
out.append(f"| torch nightly | [#{tn['number']}]({tn['url']}) | {tn['state']} |")
256-
out.append(f"| baseline | [#{base['number']}]({base['url']}) | {base['state']} |")
257290
out.append(
258291
f"\n- regressed (fails here, passes on baseline): **{len(regressed)}**\n"
259292
f"- fails on both (pre-existing, not torch): {len(buckets['both'])}\n"
@@ -443,7 +476,7 @@ def main() -> int:
443476
pair = find_latest_pair(client, args.lookback_days)
444477
if pair is None:
445478
print(
446-
f"No torch-nightly build with a same-commit baseline in the last "
479+
f"No torch-nightly build with a same-day baseline in the last "
447480
f"{args.lookback_days} days; nothing to compare.",
448481
file=sys.stderr,
449482
)

0 commit comments

Comments
 (0)