feat(cli): add e2e run --max-duration and maxDuration config
Merged
OK
12d ago+347+347+012345678901234567890123456789-39-39-01234567890123456789
Closes #1118.
e2e run had only the per-attempt timeout, so a suite where every test hangs holds its CI slot for tests x attempts x timeout. This adds a run-level budget that stops the way --max-failures does.
npx e2e run --max-duration 900000
export default { targets, maxDuration: 900_000 } satisfies E2EConfig;
--max-duration <ms>overrides the config'smaxDuration. Both take a positive integer of ms;0isINVALID_CONFIG.- The clock starts with the scheduler (
packages/e2e/src/run/scheduler.ts), so app startup stays bounded bystartupTimeoutand is not counted. - When it runs out, the scheduler goes through the
--max-failuresstop path (stopEarlywith aSkipInfo): nothing more is dispatched, running tests end asinterrupted, and tests that never started are skipped with the new causetime-limit. - The runner records one
RUN_TIMEOUTrun error (classtest) and exits 1, not 130.--last-failedpicks up the interrupted andtime-limittests. - A
maxDurationpastsetTimeout's cap (2^31-1 ms, now shared asMAX_TIMER_MSininternal/time.ts) sets no timer instead of firing at once. e2e exploreignores the config'smaxDurationand keeps its own--timeout.- Wire: the report schema's skip causes gain
time-limit(additive).maxDurationstays out of the config digest, so turning it on leaves recordings valid. - Docs:
reference/config#maxduration, thereference/cliflag row,reference/errorsRUN_TIMEOUT, the CI guide, andskills/e2e/references/running.md.
Verified
Ran it locally: yes
- Built CLI, scratch project on the testbed app (web engine, 1 worker), config
maxDuration: 600_000. The suite has one passing test, one that sleeps 30 s, one after it, and a second file. e2e run --max-duration 5000: the flag wins over the config, the run stops at about 5 s, and it exits 1.
↓ |web| tests/b-quick.e2e.ts (1 test | 1 skipped)
❯ |web| tests/a-slow.e2e.ts (3 tests | 1 interrupted | 1 skipped) 4.78s
✓ loads the home page 150ms
× waits on a slow backend (interrupted) 4.63s
↓ never starts [run stopped at its time limit of 5000 ms (maxDuration)]
ERROR test error RUN_TIMEOUT
run stopped at its time limit of 5000 ms (maxDuration): the running tests end as interrupted, the rest are skipped
Tests 1 interrupted | 1 passed | 2 skipped (4)
Errors 1 error
Duration 5.13s (startup 91ms)
exit=1
report.json:status: failed,exitCode: 1,errors: [{ code: RUN_TIMEOUT, category: test }], skip causetime-limiton the two tests that never started.- With the config set to
maxDuration: 3_000and no flag,e2e run --last-failedselected exactly the 3 tests that had not passed and stopped at 3 s with the same output.