Skip to content

Commit 4873f4c

Browse files
committed
Pair the torch-nightly triage by day, not by commit
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. Pair on the same UTC day instead, picking the baseline closest in time (ties still favour the plain nightly). 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. 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 (14-day window): now selects #83539 (2026-08-12 10:00) vs #83511 (2026-08-12 06:00), -4.0h, same UTC day, commits differ. Before this change it returned #82789/#82790 from 2026-08-07. - Simulated both rules over 21 days of builds: same-commit rule: 6/12 torch-nightly builds paired same-day rule: 12/12 paired, and identical to the old choice on all 6 days where the old rule found one - 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 4873f4c

1 file changed

Lines changed: 59 additions & 29 deletions

File tree

tools/torchci/vllm_torch_nightly_triage.py

Lines changed: 59 additions & 29 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,18 +124,16 @@ 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
@@ -243,17 +251,39 @@ def render(
243251
agents = agent_concentration(regressed)
244252
top_agent_share = (agents[0][1] / len(regressed)) if regressed else 0.0
245253

254+
same_commit = tn["commit"] == base["commit"]
246255
out: List[str] = []
256+
if same_commit:
257+
out.append(
258+
f"**{len(regressed)} job(s) regressed** on torch nightly "
259+
f"[#{tn['number']}]({tn['url']}) versus baseline "
260+
f"[#{base['number']}]({base['url']}), both at commit "
261+
f"`{tn['commit'][:12]}`.\n"
262+
)
263+
else:
264+
# Different commits: the comparison is same-day, not a controlled A/B, so
265+
# a "regression" can also come from vLLM commits landing between the two.
266+
gap_hours = (base["created_at"] - tn["created_at"]).total_seconds() / 3600
267+
out.append(
268+
f"**{len(regressed)} job(s) regressed** on torch nightly "
269+
f"[#{tn['number']}]({tn['url']}) versus same-day baseline "
270+
f"[#{base['number']}]({base['url']}) ({gap_hours:+.1f}h).\n\n"
271+
f"> :warning: The two builds ran **different commits** "
272+
f"(`{tn['commit'][:12]}` vs `{base['commit'][:12]}`), so this is a "
273+
f"same-day comparison rather than a controlled A/B. A regression here "
274+
f"may be caused by vLLM commits landing between the builds rather than "
275+
f"by torch nightly.\n"
276+
)
277+
out.append("| | build | commit | outcome |")
278+
out.append("|---|---|---|---|")
279+
out.append(
280+
f"| torch nightly | [#{tn['number']}]({tn['url']}) "
281+
f"| `{tn['commit'][:12]}` | {tn['state']} |"
282+
)
247283
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"
284+
f"| baseline | [#{base['number']}]({base['url']}) "
285+
f"| `{base['commit'][:12]}` | {base['state']} |"
252286
)
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']} |")
257287
out.append(
258288
f"\n- regressed (fails here, passes on baseline): **{len(regressed)}**\n"
259289
f"- fails on both (pre-existing, not torch): {len(buckets['both'])}\n"
@@ -443,7 +473,7 @@ def main() -> int:
443473
pair = find_latest_pair(client, args.lookback_days)
444474
if pair is None:
445475
print(
446-
f"No torch-nightly build with a same-commit baseline in the last "
476+
f"No torch-nightly build with a same-day baseline in the last "
447477
f"{args.lookback_days} days; nothing to compare.",
448478
file=sys.stderr,
449479
)

0 commit comments

Comments
 (0)