Flaky tests are the tax everyone pays and nobody budgets for: reruns burn runner minutes, engineers stop trusting red builds, and real regressions hide in the noise. AI is well-suited to the analysis half — mining test history for flake patterns and drafting quarantine PRs — while humans keep the merge decision. This playbook builds that division of labor.
Tier: Core · Workflow area: CI/CD & release engineering
@Skip annotations nobody revisits.Skip this if failures are all genuine — flake triage on a healthy suite is procrastination.
Aggregate the evidence. Produce a per-test table: name, runs, failures, failure-on-retry-pass count (the flake signature), first-seen, last-seen. A short script over JUnit XML is enough:
# collect all junit xml from recent runs into ./results/, then:
python3 flake_stats.py results/ --since 28d --out flake_report.csv
Ask for classification with a structured output contract.
Below is 28 days of per-test CI history (CSV) plus sample failure messages
per test. Classify each failing test as:
- FLAKY (fails intermittently on unchanged code; passes on retry)
- REGRESSION (started failing at a specific commit and stays failing)
- ENV (failures correlate with runner/infra messages, not test logic)
Output JSON: [{test, class, confidence, evidence, first_failing_commit?}].
Evidence must quote the data — no unsupported claims. Mark confidence LOW
when history is under 10 runs.
Audit the borderline calls. Sort by confidence ascending. For every LOW item, check the raw history yourself — misclassifying a real regression as flaky is the expensive failure of this whole workflow.
Generate quarantine PRs, one per test area. Have the assistant draft the PR: the skip/tag change, plus a mandatory issue link, owner, and un-quarantine criterion ("passes 50 consecutive runs on main"). No orphan skips.
Draft a quarantine PR for the 4 confirmed-FLAKY tests in payments-service.
Include: the quarantine tag change, a tracking issue body per test with the
flake evidence table, suggested owner from CODEOWNERS, and an explicit
exit criterion. Keep the diff minimal.
Human merges; pipeline enforces the exit. Add a scheduled job that runs quarantined tests nightly and reports — quarantine without a path back is deletion in slow motion.
Never let any automation quarantine a test without a human merge. A "flaky" security or data-integrity test that was actually catching a real race is how quarantine becomes an outage generator.
Apply the gate chain to the quarantine change like any infra change:
first_failing_commit against the actual git log before accepting any FLAKY verdict that began at a specific commit.Test names and failure messages can leak client domain details (endpoints, schema names). For client codebases under AI-tool restrictions: run the aggregation script locally, replace test identifiers with stable hashes before sending history to a hosted model, and map back locally — classification only needs the pattern, not the name. Or run the classification on a local model; the task is tabular pattern-reading, which mid-size local models handle acceptably when history is clean.