Skip to content

ci(mobile): require Flutter tests to run and pass on app PRs, including forks - #21432

Merged
Git-on-my-level merged 3 commits into
mainfrom
lane/ci-fork-gate
Oct 13, 2026
Merged

Git-on-my-level merged 3 commits into
mainfrom
lane/ci-fork-gate

Conversation

@Git-on-my-level

@Git-on-my-level Git-on-my-level commented Oct 13, 2026 •

Copy link
Copy Markdown
Collaborator

Problem

The 2026-10-13 contributor audit found 46 merged fork app PRs without Dart coverage over its full September 13–October 13 window. Since the September 28 ci:full gate, 39 of 59 fork app PRs merged without Dart (28 skipped, 11 absent). Seven of those PRs predate the gate. Five red Flutter tests reached main in the October 13 merges, and the next non-app push reported green because it skipped the suite.

Changes

  • Run the secret-free Dart Analyze & Tests job for selected app changes on every PR, including forks without ci:full, and every nightly. It runs the analyzer ratchet and regular Flutter suite.
  • Keep Mobile Release Eligibility under always(). Before fork deferral or general skip handling, require selected/nightly Dart coverage to conclude success; skipped, failed, cancelled, and missing results fail.
  • Keep generated files, iOS compile, Android compile/JVM, emulator acceptance, and seeded journeys behind their existing full-CI PR conditions.
  • Include regular Dart in the main/nightly failure issue bot. Close the matching open issue when a suite passes; an unrelated push that skips coverage leaves the issue open. Apply recovery closure to all existing suites, including Dart Far Timezones (CI post-merge failure: Dart Far Timezones #20470).
  • Report passed Dart coverage explicitly on the cheap-tier path; look up suite issues through the paginated issues API with exact title matching.
  • Update the contribution guide's ci:full explanation, the CI budget forecast and Linux cap (13,550 → 13,620 minutes/day), and tier-contract assertions while retaining the cheap-tier summary notice.

This repairs the existing shared mobile eligibility primitive rather than adding another guard or workflow. It would have blocked the skipped Dart coverage on #20798 and the missing coverage on #21302 once required.

Zero-job root cause

Fork workflow approval expired. The run page's actual annotation on 38304462940 and 38233046442 says: “This workflow run required approval but was not approved before it expired.” gh run view calls this a likely workflow-file issue, but the API shows failure with zero jobs/check runs and no reusable workflow references. Run 38304462940 and successful same-repo 38446875839 use the identical workflow blob 419ae0624cea5d087415c283635505937d68fcf8.

The same expired-approval annotation was verified for #21324 (38276262726), #21340 (38301133647), #21341 (38302471715), #21343 (38303715580), #20869 (37670747921), #20451 (37122531710), and #15088 (35480665984). This is fork approval expiry, not a fork-only YAML rejection. action_required is the pending approval state; expiry turns it into failure without jobs. The exact organization approval policy remains unreadable with the current token. No policy or branch-protection changes are included.

For maintainers

After this lands and Mobile Release Eligibility becomes a required check on main, an app PR cannot merge until the Flutter tests have actually run and passed. Contributors no longer need ci:full for those tests. ci:full still turns on the iOS and emulator jobs, plus the other existing expensive fork checks. For first-time or outside contributors whose runs require GitHub approval, maintainers must click Approve and run before jobs can start. Once eligibility is required, a PR with an unapproved run stays pending because the required eligibility check has not been created, and that blocks merging. This is the intended outcome. Expired approval also leaves the required check missing and blocks merging.

The coordinator will make Mobile Release Eligibility a required status check on main after merge. This PR does not change branch protection or rulesets.

To verify forks after merge, use a fork app PR whose merge ref includes this workflow revision, without ci:full. Approve its pending GitHub workflow run if needed, then verify Dart Analyze & Tests runs and Mobile Release Eligibility reflects its result on the exact head SHA. Existing runs may retain the old workflow: rerunning an old run alone is not proof of the new gate. Coordinate an author update/rebase when necessary; do not push to their fork. A genuinely failing Dart run must yield failed eligibility. Unrelated PRs should keep passing eligibility with Dart skipped. No other contributors' labels, comments, forks, or workflow runs were changed in this lane.

Runner cost and risks

The audit estimated 59 fork app PRs in 15 days, about four/day, each up to the existing 30-minute Ubuntu timeout: roughly 120 extra Linux runner-minutes/day at the timeout ceiling, plus one regular Dart nightly (up to 30 minutes/day). No new macOS work. At the inventory's retained 17-minute p50, four additional PR runs/day estimate 68 Linux minutes/day; repeated pushes/reruns can increase this.

Existing open fork app PRs can become blocked once the coordinator requires the gate; flaky Flutter tests will now block merges. Fork workflow approval remains necessary where GitHub requires it. Green nightlies close recovered suite issues; skipped suites do not erase failure history. This still does not run regular Flutter on every unrelated main push.

Validation

  • actionlint .github/workflows/mobile-app-checks.yml: passed.
  • Existing mobile release admission tests: 20 passed. Updated CI-tier/issue-bot tests: seven passed, including the retained GITHUB_STEP_SUMMARY deferral notice, nightly error text, and actual issue-bot Bash with a mock gh for recovery closure, skipped-push preservation, and non-matching-title preservation.
  • python3 .github/scripts/check_ci_budget.py --refresh and budget validation: passed; Linux cap is 13,620 minutes/day.
  • Inspected Dart and prerequisite local actions: no secrets.*, OIDC, protected environment, or write permission in the Dart job. The main/nightly issue writer remains guarded from PR runs.
  • OMI_PR_BODY_FILE=/tmp/ci-fork-gate-pr-body.md make preflight: 26 checks passed. scripts/pr-preflight --pr-body-file /tmp/ci-fork-gate-pr-body.md: 26 checks passed. History-dependent failure-class ratchet explicitly skips because the checkout is shallow.
  • Push through normal hooks passed, including Flutter codegen/localization and desktop flow metadata. Worktree is clean.
  • Own same-repo PR ci(mobile): require Flutter tests to run and pass on app PRs, including forks #21432 at 04026662f0737d62ced830b06df82aef08c65dbd: Mobile App Checks run 38453891951 completed successfully. Detect Changes, Generated Files, Dart Analyze & Tests, Seeded Journeys (hermetic), Android Compile Smoke, Android JVM Unit Tests, Android Emulator Acceptance, iOS Compile Check, and Mobile Release Eligibility all succeeded. Dart Tests (Pacific/Kiritimati) and Post-merge mobile failure issues were correctly skipped on this PR. This PR changes three .github/ files and the contribution guide, with no app source changes.

Product invariants affected

none

Failure-Class: none

🤖 Generated with Claude Code

Git-on-my-level and others added 2 commits October 14, 2026 01:40
Require successful selected Dart coverage before handling deferred heavy jobs, run the ordinary suite every nightly, and close recovered suite failure issues.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Budget four additional fork Dart runs per day and preserve the cheap-tier step summary while requiring successful selected and nightly Flutter coverage.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@mintlify

mintlify Bot commented Oct 13, 2026 •

Copy link
Copy Markdown

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated
omi 🟢 Ready View Preview Oct 13, 2026, 6:56 PM

💡 Tip: Enable Automations to automatically generate PRs for you.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 13, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-13T19:23:08.527550Z 0402666 New commits
ℹ️ 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@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: c75eb64ff6

ℹ️ 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 on lines +939 to +941
if [[ "$result" == success ]]; then
if [[ -n "$issue_number" ]]; then
gh issue close "$issue_number" --repo "$REPO" --reason completed

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 Serialize recovery before closing failure issues

Because the workflow’s concurrency group includes github.run_id for every non-PR event, main pushes and nightly runs can overlap. If an older successful run reaches this branch after a newer failing run has created or updated the same suite issue, it closes the issue even though the latest result is red; the reverse ordering can also reopen an issue after recovery. Serialize these reconciliations or compare run/SHA recency before closing the issue.

Useful? React with 👍 / 👎.

Report passed Dart coverage, use exact issue titles from the paginated API, exercise recovery and skipped-push behavior, and align the cap rationale with the approved forecast.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Git-on-my-level
Git-on-my-level merged commit e1216b3 into main Oct 13, 2026
71 of 73 checks passed
@Git-on-my-level
Git-on-my-level deleted the lane/ci-fork-gate branch October 13, 2026 20:20
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.

1 participant