Repository navigation
e2e: the Chainsaw catch budget counts only the global legs, not the per-suite collectors #3754
Description
Activity
- addedkind/bugCategorizes issue or PR as related to a bugCategorizes issue or PR as related to a bugarea/testingIssues or PRs related to testing (e2e, bats, unit tests)Issues or PRs related to testing (e2e, bats, unit tests)
on Aug 11, 2026 - addedtriage/needs-triageIndicates an issue needs triage by a maintainerIndicates an issue needs triage by a maintainer
on Aug 12, 2026 lexfrei commented
on Sep 7, 2026 ContributorAuthorMore actionsWhat that undercount costs at job level, measured on the OIDC pair while raising one of their budgets.
Once the BYO Ready wait goes to 20m (5m sat below the floor, which is the bootstrap hook's own 600s deadline), one failing suite costs 49m: 20m assert, 5m own catch, 6m and 13m for the two global legs, 5m cleanup that fails anyway because the uninstall cannot start while the install is still running.
Both suites pay that in the same run.
execution.parallel: 1makes them serial, the runner passes no--fail-fast, and both legs sit on theConfiguration'sspec.error.catch, so they are charged per failing test rather than once per run. The pair is 98m, and the trigger is ordinary: the release retries forever, so a single platform breakage reds both at full price.Composing that against the worst job observed in a 19-run window (138m) puts the total near 226m against the 215m cap. That is a stack of ceilings which have never fired together rather than a bound, so it is not a claim that a run has failed this way.
Correcting an earlier version of this comment, which softened the attribution in the wrong direction. Computed identically before that change, the same composition is 206m, because the three un-timed collectors it replaces already carried a 15m inherited ceiling, so a failing suite was 39m rather than free. Two things follow and neither replaces the other. 206 against the 215m cap is a fit, with nine minutes to spare, so the change is what crosses it: 226 against 215 is eleven minutes over. And 206 of the 226 is 91%, so almost all of the total was accumulated before, by the collectors this issue is about.
So the accumulated cost is where the work is, and that is this issue, but the crossing belongs to the change and should not be smoothed over. One 13m leg alone takes 26m off the both-fail path, which is more than the 20m the budget correction adds, so bounding the legs restores the fit on its own.
- addedtriage/acceptedIndicates an issue is ready to be actively worked onIndicates an issue is ready to be actively worked onpriority/backlogGeneral backlog priority. Lower than priority/important-longtermGeneral backlog priority. Lower than priority/important-longtermand removedtriage/needs-triageIndicates an issue needs triage by a maintainerIndicates an issue needs triage by a maintainer
on Sep 23, 2026
hack/e2e-chainsaw/.chainsaw.yaml:57-59records the worst-case diagnostics cost of a failed test as ~19m, and derives it from the two globalerror.catchlegs: the previous-instance log read attimeout: 6m(:82) and the crust-gather snapshot attimeout: 13m(:133). The figure is exact for those two, and the block says outright that it exists so the arithmetic does not have to be rediscovered.It does not count the
catchcollectors that individual suites add. Those run on the same failed test, in addition to the global legs. Counting them is easy to get wrong in the direction of undercounting, for two reasons that are worth stating before the table: a suite'scatchcan sit at test level (spec.catch) or on a single step (spec.steps[].catch), and ascriptop that omitstimeout:does not run unbudgeted. It inheritstimeouts.exec, which is5m.The enumeration below is
(.spec.catch[]?, .spec.steps[]?.catch[]?) | select(has("script")) | .script.timeoutover everyhack/e2e-chainsaw/*/chainsaw-test.yaml, so it can be reproduced or refuted rather than taken:catchscript opsharbortimeout:plus two at2mqdrant2mat test level and a5mon theverify-pvc-reclaim-on-deletestepbuckettimeout:openbao2mkubernetes-oidc-system2mkubernetes-oidc-customconfig2mSo a failed
harbortest can spend ~28m in diagnostics against the ~19m the block states, and a failedqdranttest ~26m.The gap is not the
2mcollectors. It is thatharborandbucketeach carry one op with notimeout:at all, and an omitted budget is the largest single contribution while being the only entry a reader cannot see a number for.qdrant's second op is the same shape of surprise from the other direction: it is explicit at5m, but it lives on a step rather than inspec.catch, so a count that walks only one of the two levels misses it entirely.This matters because of what the same block says happens at the job ceiling: the E2E job is capped at 180 timeout-minutes, a cap ends the job
cancelled, and the ~4m48s grace window is consumed by the earlierCollect reportstep, so bothcozyreport.tgzand the job log are lost. That was measured, on runs 29557003429 and 29568562337. A cascade reddening many suites is the case the block already calls out as spending a large share of the job in diagnostics, and the per-suite collectors make each of those tests cost more than the recorded figure.Three things worth deciding separately:
catchscript may omittimeout:here at all. Inheritingtimeouts.exec: 5mis what makesharborandbucketdominant while reading like the cheapest rows in the table.catchshould be allowed at both nesting levels, given that the two have to be enumerated separately and a partial walk silently undercounts.Pre-existing:
harbor,qdrant,bucketandopenbaoall carry these atcfaf2e086. The two OIDC rows are the smallest entries in the table and are new; they change the total by 4m and nothing else about the shape of the problem. This is not a regression from a specific change. It is an accounting gap in a comment that is otherwise precise, and worth closing while the comment is still trusted.