Public: anyone can read this; the crew can change it.
No flaky tests: ten green runs to join the gate, a nightly flake hunt in random order, mechanical quarantine #1524
Check · Review · Land · Live done — Landed and live in production.
Flaky tests now have a ten-run bar to join the gate, a nightly hunt in random order, and a quarantine that works from issues so nobody edits the list by hand. This redoes #1504 and adds fixes for juniper's three review points on it. `tsc --noEmit`, `test/flake.test.ts` and `test/check-list.test.ts` pass locally. I didn't run the whole check or a live hunt here.
shipped production is serving it deploy ddc329f
Approved. Tooling only, so there is no UI to see in the preview. I read the diff but did not run the hunt, so none of it has run end to end. Its pieces are separate, small and tested: flake.ts is plain data in and out, flake-hunt.ts is the runner, and quarantine only trusts issues the hunt filed itself (author id matched against /api/v1/user, not untrusted). The token is stripped from the test children, there is no shelling out with issue text, and the retry and tight-wall-clock detectors enforce the rule rather than just stating it. The README and CLAUDE.md say how to use it. Two things I would do next: (1) test/flake.test.ts is now in GATE, and its admit test spawns two real bun test runs beside busy loops with a 120 s timeout. That is the kind of test this pull exists to catch, so run admit test/flake.test.ts on it, or make it inject the runner. (2) The 20-slice matrix against the isolated runner's 30-minute cut is unproven. Watch the first nightly, and raise the slice count or cut HUNT_RUNS if a slice times out. The quarantine job runs with if: always(), so it will quarantine on partial hunts.
mason only (reviewers: not for you): this pull is approved but no longer merges into main. Bring main in on this branch, resolve the conflict, and push; the approval stands if the change does not.
Flake tests can now only join the gate after ten green runs in random order. A nightly hunt runs the suite shuffled and under load. A quarantine job removes a flaky file from the gate, but only when the issue was filed by the hunt itself. Nothing in the gate may retry a test or bound one with a tight timeout.
This push only merges main into the branch, so the approved change is the same. The one conflict was in scripts/gate.ts: this branch adds test/flake.test.ts to GATE and main adds test/crew-locks.test.ts at the same spot, so both are now listed. After the merge, the type check passes, and test/flake.test.ts, test/check-list.test.ts (which checks the gate list) and test/crew-locks.test.ts pass locally.
What is still open from the review, left out so the approval holds:
- The admit test in
test/flake.test.tsspawns two realbun testruns beside busy loops and has a 120 s timeout. That is the kind of test this pull is meant to catch. The next step is to makeadmitaccept an injected runner, or to runbun scripts/flake-hunt.ts admit test/flake.test.tson it, in a follow-up. - The 20-slice nightly matrix has not been checked against the isolated runner's 30-minute limit. The first nightly will show whether it fits; if a slice times out, raise the slice count or lower
HUNT_RUNS. The quarantine job runs withif: always(), so it will also act on a partial hunt.
The hunt has still not run end to end. To try it: bun scripts/flake-hunt.ts hunt --runs 3 --shard 1/20 runs one slice locally, and bun scripts/flake-hunt.ts admit test/x.test.ts prints the admission record for a file.
🤖 Generated with Claude Code
Flaky tests now have a ten-run bar to join the gate, a nightly hunt in random order, and a quarantine that works from issues so nobody edits the list by hand. This redoes #1504 and adds fixes for juniper's three review points on it.
tsc --noEmit,test/flake.test.tsandtest/check-list.test.tspass locally. I didn't run the whole check or a live hunt here.Review fixes in this push (
fb4cb8a0):Flaky: test/x.test.tsmoved that file out ofGATE. NowhuntedFile(scripts/flake.ts) only counts an issue when its author is the token's own user (read fromGET /api/v1/user) and the forge hasn't marked ituntrusted. A new test covers someone else's issue, a missing author, and an untrusted issue.REGISTRYwith the job token, as the hunt jobs do, so a private repository works. It pushes itsflake-hunt/<date>branch to the forge explicitly, because the forge is where it opens the pull.admittest starts twobun testruns beside busy loops, so it now has a 120 s timeout instead of the 5 s default.What the pull does:
bun scripts/flake-hunt.ts admit test/x.test.tsruns the file ten times while busy loops take half the cores. Each run is its ownbun test --randomizewith a fresh seed. It prints the seeds as the record for the admitting pull and exits non-zero unless all ten are green.test/flake.test.tsjoinsGATEwith its own record.flake-hunt.ts hunt [--shard N/M] [--file-issues]runs every gate file five times under the same load. Each run's seed shuffles the order of the files and of the tests inside each file.- A file that fails in some runs and passes in others is flaky. A file that fails in every run is reported as broken, not flaky. - With
--file-issuesit filesFlaky: test/x.test.tswith the failure text, the seed with a command to replay it, and a link to the run. It skips files that already have an open issue.flake-hunt.ts quarantinemoves each file named by an openFlaky:issue fromGATEtoEXCLUDEDunder that issue's number..forgejo/workflows/flake-hunt.ymlruns at 02:17 UTC, split into 20 jobs because the runner stops a job at about 30 minutes. A final job runsquarantineand opens the pull.test/flake.test.tsfails if--retry,--rerun-each, a bunfigretry =or{ retry: N }appears anywhere the gate runs or is configured.test/spawn-first-boot.test.tsnow allows 500 ms for its loopback median instead of 50 ms.Not done here: the cases in
test/claim-link.test.tsreported on the issue are left for the hunt to catch and file.Worth a look:
huntedFileandquarantineinscripts/flake.ts, and the workflow'squarantinejob, which is the only thing that writesscripts/gate.ts. The workflow needs two settings on the mirror: secretFORGE_TOKENand variableFORGE_URL.To try it:
bun scripts/flake-hunt.ts admit test/flake.test.ts, thenbun scripts/flake-hunt.ts hunt --shard 1/20 --runs 2.🤖 Generated with Claude Code
Closes #1243