Skip to content

fix(e2e): Retry iOS E2E flows when app fails to reach "E2E Tests Ready"#6448

Merged
alwx merged 4 commits into
mainfrom
alwx/ci/retry-e2e-ready-flake
Jul 15, 2026
Merged

fix(e2e): Retry iOS E2E flows when app fails to reach "E2E Tests Ready"#6448
alwx merged 4 commits into
mainfrom
alwx/ci/retry-e2e-ready-flake

Conversation

@alwx

@alwx alwx commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

📢 Type of change

  • Bugfix
  • New feature
  • Enhancement
  • Refactoring

📜 Description

Wrap the per-flow maestro test invocation in dev-packages/e2e-tests/cli.mjs with a one-shot retry, but only for the specific Cirrus Labs Tart VM flake where the app fails to render "E2E Tests Ready" after a fresh launchApp clearState.

Behavior:

  • MAX_ATTEMPTS = 2 — at most one retry per flow.
  • Retry fires only when the failure output contains the exact string Assert that "E2E Tests Ready" is visible... FAILED. Every other failure (real assertion failure like assertEventIdVisible, App crashed, driver errors) still fails immediately, so regressions are not masked.
  • Between attempts, a 5-second pause lets the simulator/IDB driver settle.
  • CI logs surface the flake explicitly:
    • [Flaky] <name> (Xs) (Assert that "E2E Tests Ready" is visible... FAILED) — retrying (2/2)
    • On a successful retry: [Passed] <name> (Xs) (attempt 2/2)

Everything lives inside cli.mjs; .github/workflows/e2e-v2.yml is unchanged.

💡 Motivation and Context

Over the last week, the Test RN 0.86.0 ... hermes ios production no on cirrus E2E jobs on main have failed on most non-trivial pushes.

Every failure is the same shape:

> Flow <any of captureException/captureMessage/captureReplay/captureUnhandledPromiseRejection/crash>
  Kill ${APP_ID}... COMPLETED
  Launch app "${APP_ID}" with clear state ... COMPLETED
    Assert that "E2E Tests Ready" is visible... FAILED

💚 How did you test it?

  • node --check dev-packages/e2e-tests/cli.mjs — syntax valid.
  • Reviewed the exact failure signatures in the five most recent failing runs on main; every one contains the retried string on a launch after killApp, not on an in-test assertion.
  • Not run end-to-end locally: the flake is specific to Cirrus Labs Tart VMs and does not reproduce on macOS locally. Real validation happens on this PR's CI run and on subsequent main merges.

📝 Checklist

  • I added tests to verify changes
  • No new PII added or SDK only sends newly added PII if sendDefaultPII is enabled
  • I updated the docs if needed.
  • I updated the wizard if needed.
  • All tests passing
  • No breaking changes

🔮 Next steps

  • Watch the next few runs on main — if the [Flaky] ... — retrying line becomes rare enough or a specific flow starts consistently failing on retry too, the underlying Cirrus/Tart-VM issue can be revisited (e.g. shutting down and rebooting the simulator between flows, or moving primary runs to Bitrise).

🤖 Generated with Claude Code

#skip-changelog

On Cirrus Labs Tart VMs, roughly one `maestro test` flow per run of
`e2e-v2.yml` on iOS intermittently fails immediately after
`launchApp clearState` with `Assert that "E2E Tests Ready" is
visible... FAILED`. The failure duration (14-19s) is far below the
5-minute `extendedWaitUntil` in `assertTestReady.yml`, indicating the
Maestro driver or app connection drops on the fresh launch rather than
a real UI regression.

Retry the flow once, but only when the failure output matches this
specific signature — real assertion failures elsewhere (e.g.
`assertEventIdVisible`, `App crashed`) are surfaced immediately so
regressions are not masked. Maestro's CLI exit code is a flat 0/1
(`TestCommand.kt:461`), so the pattern must be detected in stdout.

The retry logs a distinct `[Flaky] ... — retrying (2/2)` line and a
`(attempt 2/2)` suffix on the passing line so CI output makes it
obvious when the flake occurred.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Semver Impact of This PR

None (no version bump detected)

📋 Changelog Preview

This is how your changes will appear in the changelog.
Entries from this PR are highlighted with a left border (blockquote style).


This PR will not appear in the changelog.


🤖 This preview updates automatically when you update the PR.

@github-actions

github-actions Bot commented Jul 14, 2026

Copy link
Copy Markdown
Contributor
Warnings
⚠️

⚠️ Auth token handling changes detected

This PR modifies code related to Sentry auth token handling. Please ensure no auth tokens are accidentally exposed or mishandled. See GHSA-68c2-4mpx-qh95 for context.

Files with auth token changes:

  • dev-packages/e2e-tests/cli.mjs

Generated by 🚫 dangerJS against 5b30a48

@alwx alwx self-assigned this Jul 14, 2026
@alwx alwx marked this pull request as ready for review July 14, 2026 08:00
@alwx alwx added the ready-to-merge Triggers the full CI test suite label Jul 14, 2026

@cursor cursor 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.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 25971c9. Configure here.

Comment thread dev-packages/e2e-tests/cli.mjs
Comment thread dev-packages/e2e-tests/cli.mjs Outdated
The `else` branch handling a non-retryable failure logged `[Failed]`
but did not exit the inner `for (attempt)` loop, so a real failure
(anything without the `E2E Tests Ready` flake signature) would still
run `maestro test` a second time. That contradicts the "surface
regressions immediately" invariant this retry logic was written to
preserve — if the second attempt happened to pass, a real regression
would be silently masked.

Caught by both Cursor Bugbot and Sentry's autofix reviewer.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Android (legacy) Performance metrics 🚀

  Plain With Sentry Diff
Startup time 419.59 ms 462.57 ms 42.98 ms
Size 49.74 MiB 55.26 MiB 5.52 MiB

Baseline results on branch: main

Startup times

Revision Plain With Sentry Diff
f3215d3+dirty 411.11 ms 454.38 ms 43.27 ms
d2eadf8+dirty 414.64 ms 454.56 ms 39.92 ms
b0d3373+dirty 557.66 ms 579.42 ms 21.76 ms
27d9693+dirty 419.08 ms 469.12 ms 50.04 ms
4e0b819+dirty 420.56 ms 470.08 ms 49.52 ms
9474ead+dirty 411.45 ms 446.80 ms 35.35 ms
0bd8916+dirty 412.77 ms 451.31 ms 38.54 ms
f9c1ed4+dirty 431.00 ms 466.22 ms 35.22 ms
3d536d1+dirty 524.34 ms 547.32 ms 22.98 ms
04207c4+dirty 459.19 ms 518.54 ms 59.35 ms

App size

Revision Plain With Sentry Diff
f3215d3+dirty 48.30 MiB 53.49 MiB 5.19 MiB
d2eadf8+dirty 48.30 MiB 53.48 MiB 5.18 MiB
b0d3373+dirty 48.30 MiB 53.58 MiB 5.28 MiB
27d9693+dirty 49.74 MiB 55.09 MiB 5.34 MiB
4e0b819+dirty 49.74 MiB 54.81 MiB 5.07 MiB
9474ead+dirty 48.30 MiB 53.61 MiB 5.30 MiB
0bd8916+dirty 48.30 MiB 53.57 MiB 5.26 MiB
f9c1ed4+dirty 49.74 MiB 54.86 MiB 5.12 MiB
3d536d1+dirty 49.74 MiB 55.26 MiB 5.52 MiB
04207c4+dirty 43.75 MiB 48.12 MiB 4.37 MiB

@github-actions

github-actions Bot commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Android (new) Performance metrics 🚀

  Plain With Sentry Diff
Startup time 446.82 ms 523.74 ms 76.92 ms
Size 49.74 MiB 55.26 MiB 5.52 MiB

Baseline results on branch: main

Startup times

Revision Plain With Sentry Diff
a50b33d+dirty 353.21 ms 398.48 ms 45.27 ms
d038a14+dirty 405.08 ms 444.36 ms 39.28 ms
68672fc+dirty 407.55 ms 442.96 ms 35.41 ms
ad66da3+dirty 411.49 ms 449.38 ms 37.89 ms
f170ec3+dirty 505.96 ms 551.88 ms 45.92 ms
27d9693+dirty 438.63 ms 514.08 ms 75.46 ms
41d6254+dirty 406.20 ms 445.52 ms 39.32 ms
68ae91b+dirty 515.04 ms 578.08 ms 63.04 ms
5ee78d6+dirty 411.18 ms 437.83 ms 26.65 ms
ae37560+dirty 428.96 ms 456.86 ms 27.90 ms

App size

Revision Plain With Sentry Diff
a50b33d+dirty 43.94 MiB 48.94 MiB 5.00 MiB
d038a14+dirty 48.30 MiB 53.49 MiB 5.19 MiB
68672fc+dirty 48.30 MiB 53.61 MiB 5.31 MiB
ad66da3+dirty 48.30 MiB 53.49 MiB 5.19 MiB
f170ec3+dirty 48.30 MiB 53.57 MiB 5.26 MiB
27d9693+dirty 49.74 MiB 55.09 MiB 5.34 MiB
41d6254+dirty 48.30 MiB 53.60 MiB 5.30 MiB
68ae91b+dirty 49.74 MiB 54.79 MiB 5.05 MiB
5ee78d6+dirty 48.30 MiB 53.58 MiB 5.28 MiB
ae37560+dirty 48.30 MiB 53.60 MiB 5.29 MiB

Comment thread dev-packages/e2e-tests/cli.mjs

@lucas-zimerman lucas-zimerman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGMT! after CI test pass

@alwx alwx merged commit 41ad081 into main Jul 15, 2026
75 of 82 checks passed
@alwx alwx deleted the alwx/ci/retry-e2e-ready-flake branch July 15, 2026 11:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready-to-merge Triggers the full CI test suite

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants