# Flaky tests: rerun once and record it (`gstack-flaky`) `gstack-flaky run` runs your test command, reads the JUnit report it writes, and when tests failed, runs the command once more. A test that passes on its rerun is a **flaky pass**: the job stays green and the flake is recorded on a ledger, so the daily flaky pass can fix it at the source. A test that fails twice is red. This is CREW rule 16 ("run the failed test again and note that it is flaky") for any runner that writes JUnit: Playwright, `bun test`, jest, vitest and pytest. gstack's own free suite keeps its file-level retry (`GSTACK_FREE_RETRY_FLAKY`, [Flake ledger](TESTING_INTERNALS.md#flake-ledger)). ## Get started in GitHub Actions ```yaml - uses: oven-sh/setup-bun@v2 with: { bun-version: 1.4.4 } - name: Install gstack-flaky (pinned) env: { GSTACK_REF: } run: | git clone --quiet --filter=blob:none https://github.com/garrytan/gstack.git "$RUNNER_TEMP/gstack" git -C "$RUNNER_TEMP/gstack" checkout --quiet "$GSTACK_REF" - name: E2E env: PLAYWRIGHT_JUNIT_OUTPUT_NAME: results/junit.xml GSTACK_FLAKE_LEDGER_JUNIT: ${{ runner.temp }}/flaky-junit-ledger.jsonl run: | "$RUNNER_TEMP/gstack/bin/gstack-flaky" run --junit results/junit.xml -- npx playwright test --reporter=line,junit - if: always() uses: actions/upload-artifact@v4 with: { name: flaky-junit-ledger-e2e, path: "${{ runner.temp }}/flaky-junit-ledger.jsonl", if-no-files-found: ignore, retention-days: 90 } ``` Replace `GSTACK_REF` with a gstack commit you have tested; the bin needs only Bun and git. In Actions it also writes a step-summary table of the flaky passes and one `::warning` annotation per flaky test, so they are visible on the run before anyone reads the ledger. ## Runners | Runner | Command after `--` | Notes | |---|---|---| | Playwright | `npx playwright test --reporter=line,junit` with `PLAYWRIGHT_JUNIT_OUTPUT_NAME=` | `gstack-flaky` sets `PLAYWRIGHT_JUNIT_INCLUDE_RETRIES=1` so Playwright's own `retries` are reported; with retries configured, those attempts stand and nothing is rerun again. | | bun | `bun test --reporter=junit --reporter-outfile=` | | | jest, vitest, pytest (`--runner generic`) | your command, writing JUnit | Always reruns the whole command, even with `--rerun-scope test`. | The command after `--` runs without a shell. When it needs one, wrap it as `bash -c '