Skip to content

feat: auto-retry-on-flaky for mix test.json (v0.5.0)#2

Merged
e-fu merged 1 commit into
developmentfrom
auto-retry-flaky
Jun 1, 2026
Merged

feat: auto-retry-on-flaky for mix test.json (v0.5.0)#2
e-fu merged 1 commit into
developmentfrom
auto-retry-flaky

Conversation

@e-fu

@e-fu e-fu commented Jun 1, 2026

Copy link
Copy Markdown
Contributor

Summary

Bare mix test.json now auto-retries failed tests once and distinguishes confirmed failures from flakes — so an AI agent running the default command isn't blocked by 1–2 intermittent async/GenServer/LiveView reds it can't be told to re-run.

On failures, the task re-runs only the previously-failed tests (ExUnit-native --failed --all) in a subprocess, merges both runs by {module, name}, and classifies:

  • confirmed — failed both runs → stays in tests, exit non-zero
  • flaky — failed then passed → moved to a top-level flaky[] array (named, never hidden) and no longer blocks

When every first-run failure heals, summary.result becomes "passed" and the exit code is 0 (System.halt(0) override). A retry metadata object (retried/confirmed/flaky) is added whenever a retry runs. Honors NEVER HIDE TEST FAILURES — flakes are always surfaced.

Opt-out

  • --no-retry flag
  • config :ex_unit_json, retry: false
  • Auto-skipped for: --failed, --summary-only, --first-failure, --compact, --group-by-error, --filter-out, a file:line target, umbrella projects, and any already-green suite.

Changes

  • New ExUnitJSON.Retry — pure merge/2 core (100% coverage)
  • ExUnitJSON.Configretry?/0 + :retry option
  • Mix.Tasks.Test.Json--no-retry parse, generalized temp-buffer, retry orchestration, heal-to-green exit override
  • Docs: moduledoc, README, CHANGELOG (v0.5.0), .version0.5.0
  • Roadmap task 30

Tests

12 Retry unit + 4 retry integration + 4 Config tests. Full suite green. format / credo --strict / dialyzer / sobelow / doctor all clean.

Copilot AI review requested due to automatic review settings June 1, 2026 01:16

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a783fae3c0

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread lib/ex_unit_json/retry.ex

{flaky_tests, kept_tests} =
Enum.split_with(run1_tests, fn test ->
failed?(test) and id(test) in run2_passed_ids

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Drop healed invalid tests from --all retry output

When auto-retry is used with --all and a setup_all failure heals on the retry, the first run includes each test as state: "invalid" while the module failure is moved to flaky. This predicate only removes tests whose first-run state was failed, so those invalid entries remain in tests even though merge_summary/4 sets invalid to 0 and result to passed, producing a contradictory green result containing invalid tests. This affects mix test.json --all suites with flaky setup_all callbacks.

Useful? React with 👍 / 👎.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds default automatic retry-on-flaky behavior for mix test.json, including merge logic to classify healed failures as flaky while preserving confirmed failures.

Changes:

  • Adds ExUnitJSON.Retry.merge/2 and retry orchestration in Mix.Tasks.Test.Json.
  • Adds --no-retry / config :ex_unit_json, retry: false support and tests.
  • Updates README, moduledocs, changelog, version, and roadmap metadata for v0.5.0.

Reviewed changes

Copilot reviewed 13 out of 13 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
lib/ex_unit_json/retry.ex Adds retry merge/classification logic.
lib/mix/tasks/test_json.ex Adds retry enablement, buffering, subprocess retry, and final output handling.
lib/ex_unit_json/config.ex Adds retry config option and retry?/0.
lib/ex_unit_json.ex Documents retry behavior and schema additions.
test/ex_unit_json/retry_test.exs Adds unit coverage for retry merge behavior.
test/ex_unit_json/config_test.exs Adds config tests for retry option handling.
test/mix/tasks/test_json_test.exs Adds parsing and integration tests for retry behavior.
README.md Documents user-facing retry behavior and opt-out.
CHANGELOG.md Adds v0.5.0 release notes.
ROADMAP.md Marks retry task as shipped.
roadmap/tasks.toml Adds completed roadmap task metadata.
roadmap/data.json Adds generated roadmap task data.
.version Bumps package version to 0.5.0.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread lib/ex_unit_json/retry.ex
Comment on lines +140 to +142
# When everything healed, any run-1 `invalid` count (from a setup_all that
# has since recovered) is stale — passing means nothing invalid remains.
if result == "passed", do: Map.put(summary, "invalid", 0), else: summary
@e-fu
e-fu merged commit ed8fcc2 into development Jun 1, 2026
1 check passed
@e-fu
e-fu deleted the auto-retry-flaky branch June 1, 2026 01:20
e-fu added a commit that referenced this pull request Jun 4, 2026
…al-reviewer pass

Reports: .audit/<sha>-<slug>.md × 23 (14 full audits, 9 fast-path)

Auto-applied (bugs):
- retry.ex: setup_all casualties (invalid tests) now resolve against the retry
  run — healed → passed, re-failed → confirmed, never silently dropped
  (4-reasoner: Codex GH bot P2 + Copilot + Codex CLI + Claude, PR #2)
- formatter.ex: umbrella --compact merge crash → JSONL concatenation
- formatter.ex: --first-failure capped across umbrella merge
- formatter.ex: merged error_groups re-sorted count-desc
- test_json.ex: stale-output guard (rm → truncate fallback → raise)
- test_json.ex: --cover precompile honors --no-compile / --warnings-as-errors
- test_json.ex: coverage start failures warn on stderr
- test_json.ex: --cover no longer suppresses the --failed TIP
- test_json_test.exs: parse tests exercise production parser (70-line copy deleted)

Auto-applied (docs):
- CHANGELOG: [Unreleased] entry; v0.4.1 --cover-threshold; v0.4.3 hint fix
- Schema docs: "invalid" state, hint key, module_failures shape, coverage examples
- ROADMAP: schema section synced, Jason-fallback wording, phase prose
- roadmap/tasks.toml: AGENT.md → AGENTS.md (rmap re-rendered)
- config/filters/formatter inline doc drift (:all → :debug, defaults)

Discarded with rationale: Codex "~> 0.4 excludes v0.5.0" (false — includes it),
4 cosmetic single-reasoner items. No discuss-design divergence; no rmap follow-ups.

Quality gates: 349/349 tests, dialyzer 0, credo --strict 0, sobelow clean, doctor 100%
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants