Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,7 @@
"group": "Quarantining",
"root": "flaky-tests/quarantining/index",
"pages": [
"flaky-tests/quarantining/recipes",
"flaky-tests/quarantining/quarantine-service-availability"
]
},
Expand Down
4 changes: 4 additions & 0 deletions flaky-tests/quarantining/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
Actively quarantining tests will significantly change CI results, as failures from quarantined tests no longer cause builds to fail. [Learn more about the effects of quarantining](./index#whats-affected).
</Warning>

With quarantining enabled, the Analytics Uploader will compare failed test cases against known flaky tests. If a test is known to be flaky, it will be quarantined. If all failed tests are quarantined, the exit code of the test command will be overridden to return 0 and the CI job will pass.

Check warning on line 42 in flaky-tests/quarantining/index.mdx

View check run for this annotation

Mintlify / Mintlify Validation (trunk-4cab4936) - vale-spellcheck

flaky-tests/quarantining/index.mdx#L42

Did you really mean 'Uploader'?

### Quarantining settings

Expand Down Expand Up @@ -75,13 +75,13 @@

When you disable collection quarantining, auto-quarantine is also disabled automatically. Re-enabling quarantining for the collection does not restore auto-quarantine — you must turn it back on separately.

## Quarantining with Sharded or Parallelized Tests

Check warning on line 78 in flaky-tests/quarantining/index.mdx

View check run for this annotation

Mintlify / Mintlify Validation (trunk-4cab4936) - vale-spellcheck

flaky-tests/quarantining/index.mdx#L78

Did you really mean 'Sharded'?

There are two options for handling quarantining.

**Option 1: Wrapping each test invocation**

Wrap each command and specify its JUnit output path. Trunk captures the exit code and automatically uploads results.

Check warning on line 84 in flaky-tests/quarantining/index.mdx

View check run for this annotation

Mintlify / Mintlify Validation (trunk-4cab4936) - vale-spellcheck

flaky-tests/quarantining/index.mdx#L84

Did you really mean 'JUnit'?

**Example**

Expand All @@ -94,11 +94,11 @@

**Option 2: Handling quarantining during upload**

For complex setups where Trunk can’t wrap test commands, run tests first and let the upload step be the final gate. When quarantining is enabled, the upload inspects the provided JUnit results and decides whether to return exit code `0` or `1` based on the outcomes.

Check warning on line 97 in flaky-tests/quarantining/index.mdx

View check run for this annotation

Mintlify / Mintlify Validation (trunk-4cab4936) - vale-spellcheck

flaky-tests/quarantining/index.mdx#L97

Did you really mean 'JUnit'?

**Advanced: Handling build errors outside test runs**

To handle build issues that occur outside test runs, use the --test-process-exit-code option. This provides a fallback exit code if the upload runs without detecting any Junit results.

Check warning on line 101 in flaky-tests/quarantining/index.mdx

View check run for this annotation

Mintlify / Mintlify Validation (trunk-4cab4936) - vale-spellcheck

flaky-tests/quarantining/index.mdx#L101

Did you really mean 'Junit'?

**Example**

Expand All @@ -111,10 +111,10 @@
<YOUR_TEST_COMMAND>
```

The CLI only recognizes tests defined in JUnit. If multiple test executions occur and one fails due to a build error, Flaky Tests won’t detect it and will assume the exit code came from test failures. If those failures are quarantined, the job may incorrectly be reported as successful. To prevent this:

Check warning on line 114 in flaky-tests/quarantining/index.mdx

View check run for this annotation

Mintlify / Mintlify Validation (trunk-4cab4936) - vale-spellcheck

flaky-tests/quarantining/index.mdx#L114

Did you really mean 'JUnit'?

* Upload results for each test execution separately, or
* Generate a JUnit that records build errors.

Check warning on line 117 in flaky-tests/quarantining/index.mdx

View check run for this annotation

Mintlify / Mintlify Validation (trunk-4cab4936) - vale-spellcheck

flaky-tests/quarantining/index.mdx#L117

Did you really mean 'JUnit'?

## Updates in CI

Expand All @@ -124,7 +124,7 @@

<Tabs>
<Tab title="GitHub Actions Workflow">
Using the Trunk Analytics Uploader Action in your GitHub Actions Workflow files, may need modifications to your workflow files to support quarantining.

Check warning on line 127 in flaky-tests/quarantining/index.mdx

View check run for this annotation

Mintlify / Mintlify Validation (trunk-4cab4936) - vale-spellcheck

flaky-tests/quarantining/index.mdx#L127

Did you really mean 'Uploader'?

If you upload your test results as a second step after you run your tests, **you need to add** `continue-on-error: true` **on your test step so your CI** job will continue even on failures.

Expand All @@ -133,14 +133,14 @@
```yaml lines highlight={1,9}
name: Run Tests And Upload Results
on:
workflow_dispatch:

Check warning on line 136 in flaky-tests/quarantining/index.mdx

View check run for this annotation

Mintlify / Mintlify Validation (trunk-4cab4936) - vale-spellcheck

flaky-tests/quarantining/index.mdx#L136

Did you really mean 'workflow_dispatch'?
jobs:
upload-test-results:
runs-on: ubuntu-latest
timeout-minutes: 60
steps:
- name: Run Tests
id: unit_tests

Check warning on line 143 in flaky-tests/quarantining/index.mdx

View check run for this annotation

Mintlify / Mintlify Validation (trunk-4cab4936) - vale-spellcheck

flaky-tests/quarantining/index.mdx#L143

Did you really mean 'unit_tests'?
shell: bash
run: <COMMAND TO RUN TESTS>
continue-on-error: true
Expand Down Expand Up @@ -182,7 +182,7 @@
<Tab title="Using The Trunk Analytics CLI Directly">
**Using Flaky Tests as a separate step**

If you upload your test results as a second step after you run your tests, you need to ensure your test step **continues on errors** so the upload step that's run after can quarantine failed tests. When quarantining is enabled, the `trunk-analytics-cli upload` command will **return an error** if there are unquarantined failures and return a status code 0 if all tests are quarantined.

Check warning on line 185 in flaky-tests/quarantining/index.mdx

View check run for this annotation

Mintlify / Mintlify Validation (trunk-4cab4936) - vale-spellcheck

flaky-tests/quarantining/index.mdx#L185

Did you really mean 'unquarantined'?

```bash
<run my tests> || true # doesn't fail job on failure
Expand All @@ -195,7 +195,7 @@

**Using Flaky Tests as a single step**

You can also wrap the test command with the Trunk Analytics CLI. When wrapping the command with the Trunk Analytics CLI, if there are unquarantined tests, the command will return an error. If there are no unquarantined tests, the command will return a status code 0.

Check warning on line 198 in flaky-tests/quarantining/index.mdx

View check run for this annotation

Mintlify / Mintlify Validation (trunk-4cab4936) - vale-spellcheck

flaky-tests/quarantining/index.mdx#L198

Did you really mean 'unquarantined'?

Check warning on line 198 in flaky-tests/quarantining/index.mdx

View check run for this annotation

Mintlify / Mintlify Validation (trunk-4cab4936) - vale-spellcheck

flaky-tests/quarantining/index.mdx#L198

Did you really mean 'unquarantined'?

```bash
./trunk-analytics-cli test \
Expand All @@ -222,10 +222,10 @@

Right-click any row in the Flaky Tests table to open the context menu. Two quarantine actions are available:

* **Quarantine test** / **Unquarantine test** — toggles the always-quarantine override for that test.

Check warning on line 225 in flaky-tests/quarantining/index.mdx

View check run for this annotation

Mintlify / Mintlify Validation (trunk-4cab4936) - vale-spellcheck

flaky-tests/quarantining/index.mdx#L225

Did you really mean 'Unquarantine'?
* **Never Quarantine test** / **Remove Never Quarantine** — toggles the never-quarantine override. When set, the test is never quarantined, even if auto-quarantining is enabled for the repo.

All four options require admin permissions. Non-admin users see them as disabled with the tooltip "Only admins can set manual quarantine."

Check warning on line 228 in flaky-tests/quarantining/index.mdx

View check run for this annotation

Mintlify / Mintlify Validation (trunk-4cab4936) - vale-spellcheck

flaky-tests/quarantining/index.mdx#L228

Did you really mean 'tooltip'?

**From the test details page**

Expand Down Expand Up @@ -273,6 +273,10 @@
* API: Use the [Flaky Tests API](../reference/api-reference) to fetch a list of all currently quarantined tests in your project.
* Webhooks: Subscribe to the `test_case.quarantining_setting_changed` event to trigger automated workflows whenever a test's quarantine override is modified. Learn more about [Webhooks](https://www.svix.com/event-types/us/org_2eQPL41Ew5XSHxiXZIamIUIXg8H/#test_case.quarantining_setting_changed).

### Recipes and operational patterns

For day-to-day quarantine operations — semantics edge cases, bulk operations, the Events tab, cross-repo configs, and verifying a fix without un-quarantining — see [Quarantine recipes](./recipes).

Check warning on line 278 in flaky-tests/quarantining/index.mdx

View check run for this annotation

Mintlify / Mintlify Validation (trunk-4cab4936) - vale-spellcheck

flaky-tests/quarantining/index.mdx#L278

Did you really mean 'configs'?

<Info>
### Service Availability and Graceful Degradation

Expand Down
143 changes: 143 additions & 0 deletions flaky-tests/quarantining/recipes.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
---
title: "Quarantine recipes"
description: "Cheat sheet, bulk operations, history/events, cross-repo, and fix-verification patterns for quarantining."
---

This page is the practical companion to the main [Quarantining](./index) page. The main page covers what quarantining is and how to enable it. This page covers the operational questions that come up after you have it on — semantics edge cases, bulk operations, cross-repo configurations, the events tab, and how to verify a fix without flipping quarantine state mid-PR.

## Quarantine semantics cheat sheet

A few rules that catch teams by surprise:

| Rule | Detail |
|---|---|
| Only flaky tests auto-quarantine | Broken tests never auto-quarantine, even when auto-quarantine is on. A broken test is a real regression — Trunk surfaces it but does not hide it from CI. |
| Most severe status wins | When several [classifying monitors](../detection/#how-monitors-work) fire on the same test, the most severe status wins (broken > flaky > healthy). A broken-monitor hit on an otherwise-flaky test will block auto-quarantine. |
| Manual "Flag as Flaky" does not quarantine on its own | [Flagging a test as flaky](../detection/flag-as-flaky) only sets its classification. It quarantines that test only when **Auto-Quarantine Flaky Tests** is also enabled in repo or collection settings. |
| State propagation is not instant | After a manual override (Always / Never Quarantine), it can take up to a minute for the new state to reflect everywhere — on the test detail page, in the table, and in CI lookups. If a change appears to revert on page reload, wait and refresh. |

Check warning on line 17 in flaky-tests/quarantining/recipes.mdx

View check run for this annotation

Mintlify / Mintlify Validation (trunk-4cab4936) - vale-spellcheck

flaky-tests/quarantining/recipes.mdx#L17

Did you really mean 'lookups'?
| Deleting a monitor immediately removes its influence | If you delete or disable the monitor that was flagging a test, the test re-evaluates against the remaining active monitors. If no classifying monitors are left, the test goes back to healthy and any auto-quarantine on it is removed. See [Disabling or Deleting a Monitor](../detection/#disabling-or-deleting-a-monitor). |

<Info>
If a test you expect to be quarantined is not, walk this list in order: is auto-quarantine on, is the test classified as **Flaky** (not Broken or Healthy), and is there a more severe monitor active that's outranking the flaky monitor.
</Info>

### When manual override is the right tool

Manual **Always Quarantine** and **Never Quarantine** overrides bypass classification. Reach for them when:

- You know a test is flaky but no monitor has caught it yet, and you need it quarantined right now.
- You want to permanently exclude a critical test from auto-quarantine — for example, a smoke test where a real failure must always block CI.
- A broken test needs to be temporarily hidden from CI while a fix is in progress and you accept the trade-off.

See [Overriding individual tests](./index#overriding-individual-tests) for the UI steps.

## Bulk operations

### Bulk quarantine across a suite

Test suites do not have their own quarantine state — quarantining is per-test. To act on a suite's worth of tests at once:

1. Open the Flaky Tests table.
2. Filter by the suite name (or any other column that scopes the set).
3. Select all matching tests.
4. Apply **Quarantine** as a bulk action.

For auto-quarantined tests, the equivalent "act on this whole suite" move is to mute the detecting monitor for the selected tests rather than overriding each one manually.

### Bulk-unquarantine after an infrastructure incident

When an infra incident (a flaky runner, a bad deploy, a service outage) causes a large number of tests to flake on the same window, auto-quarantine can lock down hundreds or thousands of otherwise-healthy tests at once. There is no bulk-unquarantine API today. The fastest recovery path:

1. Open **Settings** > **Repositories** > your repo > **Flaky Tests** > **Pass-on-Retry Monitor**.
2. Lower the **recovery threshold** to a short window (for example, 3 days).
3. Any test that has not flaked again inside that shorter window will resolve and lose its auto-quarantine.
4. Once the incident-related quarantines have cleared, raise the recovery threshold back to its prior value.

This works because pass-on-retry monitors resolve a test the moment its recent run history no longer matches the configured pattern. Shortening the recovery window forces a re-evaluation across the whole repo.

<Info>
A direct bulk-unquarantine API is a tracked request. Until it ships, the recovery-threshold approach is the recommended workaround for post-incident cleanup.
</Info>

### Bulk "never quarantine"

There is no API to mark a list of tests as **Never Quarantine** in one call. For now this is a manual operation — open each test from the Flaky Tests table and toggle **Never Quarantine** from the row context menu, or use the test detail page. API support for bulk overrides is on the roadmap.

## Conditional quarantine: per-PR, per-branch, or "just this one build"

Trunk does not currently support quarantining a test only on a specific PR, branch, or build. Quarantine state is repo-wide (or collection-wide), and changes apply to all subsequent runs everywhere until you undo them.

If you need behavior that looks like "quarantine this just on my fix branch":

- **For verifying a fix before un-quarantining**, use the recipe in [Verifying a fix without un-quarantining](#verifying-a-fix-without-un-quarantining) below. This is the answer most teams actually want.
- **For temporarily quarantining a test for the duration of a PR**, set **Always Quarantine** when you start the PR and remove the override (or set **Never Quarantine**) when you merge. The override is global for the time it is set, but most PRs are short-lived enough that this is acceptable.
- **For per-branch detection thresholds**, configure separate [failure rate monitors](../detection/failure-rate-monitor#recommended-configurations) with different branch scopes. This controls _detection_ per-branch, not quarantine per-branch, but it is often what teams are reaching for when they ask about per-branch quarantine.

Conditional / per-PR quarantine is a tracked feature request.

## Verifying a fix without un-quarantining

A common workflow: you think you've fixed a flaky test, and you want CI to tell you whether the fix actually works — but you don't want to un-quarantine the test first, in case the fix doesn't hold and you re-pollute CI.

Quarantined tests still run in CI. The Trunk Analytics CLI overrides the **exit code** for failed quarantined tests, but the test's underlying pass/fail outcome is still recorded and uploaded. So:

1. Leave the test quarantined.
2. Push your fix on a branch and run CI normally.
3. In the CI logs (or on the Trunk test detail page's **Test History** tab), look at the test's actual result on those runs — not the quarantine-override pass result at the job level.
4. If the underlying test result is consistently passing across the runs your fix touched, the fix is holding. Remove the override (or wait for the detecting monitor to resolve) to un-quarantine.

On the **Test History** tab, set the **Quarantined** filter to **Only** to see exactly the runs Trunk overrode. The colored left border on each row also distinguishes the underlying outcome (green pass, red fail) from the quarantine state (blue border).

## Quarantine history and the Events tab

The test detail page's **Events** tab is an audit timeline. Two things are worth knowing about how the **Quarantine Event** filter is scoped:

- It surfaces **manual** overrides only — Always Quarantine and Never Quarantine actions, and removals of those overrides. The actor and timestamp are recorded.
- It does **not** surface auto-quarantine history. Auto-quarantine is a consequence of the test's current classification, which lives under flake-detection events. To see why an auto-quarantined test became quarantined, filter the Events tab to **Flake Detection** and look at which monitor flagged it.

If a manual override appears to "vanish" from the timeline after a monitor change, the override is still recorded — but the test's overall quarantine state may have flipped because a more severe monitor now outranks it. Manual overrides do not disappear; the test's effective state is the combination of all monitors plus any overrides.

### How monitor changes affect quarantine state

| Action | Effect on quarantine |
|---|---|
| Disable or delete a classifying monitor | Monitor immediately resolves for every test it was flagging. Tests re-evaluate against remaining active monitors. If no classifying monitor is left, the test transitions to healthy and any auto-quarantine on it is removed. |
| Add a new broken-type monitor that fires on a flaky test | The test's status becomes broken (most severe wins). Because broken tests don't auto-quarantine, the test loses its auto-quarantine. A manual **Always Quarantine** override still keeps it quarantined. |
| Mute a monitor on a specific test | The muted monitor stops contributing to that test's status for the mute duration. If it was the only active classifying monitor, the test transitions to healthy and auto-quarantine is removed for the duration. |

## Cross-repo and forks: applying one repo's quarantine config to another

Quarantine state lives on the repo identified by your git remote URL. If you have a private fork or a separate test-distribution repo and you want it to inherit the main repo's quarantine config without polluting the main repo's run history, override the repo URL on the fork's upload step and run it in dry-run mode:

```bash
./trunk-analytics-cli upload \
--junit-paths "test_output.xml" \
--org-url-slug <TRUNK_ORG_SLUG> \
--token $TRUNK_API_TOKEN \
--repo-url "https://github.com/your-org/main-repo.git" \
--dry-run=true
```

Or with the GitHub Actions uploader:

Check warning on line 121 in flaky-tests/quarantining/recipes.mdx

View check run for this annotation

Mintlify / Mintlify Validation (trunk-4cab4936) - vale-spellcheck

flaky-tests/quarantining/recipes.mdx#L121

Did you really mean 'uploader'?

```yaml
- name: Apply main repo quarantine config (dry-run)
uses: trunk-io/analytics-uploader@v1
with:
junit-paths: <TEST OUTPUT PATH>
org-slug: my-trunk-org-slug
token: ${{ secrets.TRUNK_API_TOKEN }}
repo-url: "https://github.com/your-org/main-repo.git"
dry-run: true
```

What this does:

- `--repo-url` redirects the upload's quarantine lookups to the main repo's config, so the fork's CI honors the main repo's quarantined-test list.

Check warning on line 136 in flaky-tests/quarantining/recipes.mdx

View check run for this annotation

Mintlify / Mintlify Validation (trunk-4cab4936) - vale-spellcheck

flaky-tests/quarantining/recipes.mdx#L136

Did you really mean 'upload's'?

Check warning on line 136 in flaky-tests/quarantining/recipes.mdx

View check run for this annotation

Mintlify / Mintlify Validation (trunk-4cab4936) - vale-spellcheck

flaky-tests/quarantining/recipes.mdx#L136

Did you really mean 'lookups'?
- `--dry-run=true` skips the actual ingestion step, so the fork's run results never land in the main repo's history.

The fork still gets the quarantine overrides at the exit-code layer. The main repo's dashboard stays clean.

<Info>
If you do want the fork's results to appear in the main repo, drop the `--dry-run=true` flag. If you want them tracked separately on the fork's own repo entry, drop both flags entirely — see [Multiple Repositories and Forks](../get-started/multiple-repositories) for the default behavior.
</Info>