ci: reuse native E2E builds across commits and PRs#29247
Conversation
… prs and cross prs
|
CLA Signature Action: All authors have signed the CLA. You may need to manually re-run the blocking PR check if it doesn't pass in a few minutes. |
AI PR Analysis🚫 Merge safe: false | 🟠 Risk: high
AI analysis did not complete. Manual review recommended. |
…abs/cache runs on Namespace- it would have caused redundant restore and a redundant cache save at end-of-run on every Namespace build. Fixed by re-adding the gate
…K cache restore steps (apk-cache-restore and apk-cache-restore-main). With the step skipped, cache-hit stays empty, the gate's elif doesn't match, and we fall through to needs-native-build=true — the actual fresh build.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #29247 +/- ##
==========================================
+ Coverage 81.44% 81.52% +0.07%
==========================================
Files 5318 5328 +10
Lines 140909 141136 +227
Branches 32109 32157 +48
==========================================
+ Hits 114767 115055 +288
+ Misses 18263 18221 -42
+ Partials 7879 7860 -19 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
…hat could be reverted
🔍 Smart E2E Test Selection
click to see 🤖 AI reasoning detailsE2E Test Selection:
No application source code was changed. The risk is that the new build pipeline might produce incorrect or broken test artifacts, which would cause E2E tests to fail. To validate the pipeline works correctly, a representative set of E2E tests should run across core areas (accounts, confirmations, wallet platform) to confirm the built artifacts are functional. Running all tags would be excessive since the app code itself hasn't changed - we just need enough coverage to verify the build artifacts are valid and the pipeline works end-to-end. The selected tags (SmokeAccounts, SmokeConfirmations, SmokeWalletPlatform) cover the most fundamental wallet flows and will adequately validate that the build artifacts produced by the new pipeline are functional. Performance Test Selection: |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 89e6bc5. Configure here.
| timeout_minutes: 10 | ||
| max_attempts: 3 | ||
| retry_wait_seconds: 30 | ||
| command: yarn install --immutable |
There was a problem hiding this comment.
Fingerprint job uses @v4 actions, missing corepack setup
Medium Severity
The post-build-source-hash job uses actions/checkout@v4 and actions/setup-node@v4 while every other job in the workflow uses @v6. More critically, it does not explicitly enable corepack or prepare a specific Yarn version before running yarn install --immutable. The project's package.json declares "packageManager": "yarn@4.10.3", while the build jobs explicitly activate yarn@3.8.7 via corepack prepare. If actions/setup-node@v4 handles corepack differently from @v6 (which other jobs use successfully without explicit corepack steps), the fingerprint job could fail or use a mismatched Yarn version, silently disabling the entire build-reuse feature (fingerprint output stays empty → every build is fresh).
Reviewed by Cursor Bugbot for commit 89e6bc5. Configure here.
|





Description
Replaces the branch-keyed
cirruslabs/cachereuse layer for native E2E builds with a content-addressable cross-run lookup, driven by abuild-source-hashcommit status that is computed once on a stable runner.How it works
flowchart TD A["post-build-source-hash<br/>(ubuntu-latest, pinned to PR head SHA)<br/>fingerprint = yarn fingerprint:generate"] -->|posts build-source-hash status<br/>+ exposes as job output| B["Build iOS / Android job"] B --> C{"check-force-builds<br/>label OR [force-builds] in commit?"} C -- yes --> H["Heavy native-build path<br/>setup-e2e-env + Gradle/Xcode + compile"] C -- no --> D["find-reusable-build<br/>(GitHub Actions REST API)"] D --> D1["Tier 1: same-branch runs"] D1 -- miss --> D2["Tier 2: base-branch (main) runs"] D2 -- miss --> D3["Tier 3: cross-PR runs<br/>(event=pull_request, no branch filter)"] D1 -- hit --> E["actions/download-artifact@v4<br/>by run-id"] D2 -- hit --> E D3 -- hit --> E D3 -- miss --> H E --> F["Lean repack path<br/>Node + yarn install + repack:{ios,android}"] H --> I["Upload .app / release.apk / androidTest.apk"] F --> I I -.->|feeds future runs| DThe probe runs before any heavy setup. On a hit, iOS skips Ruby/Bundler/CocoaPods/
pod install; Android skipssetup-e2e-env/Gradle. Only the JS bundle is rebuilt and re-packed into the cached native shell.Benefits vs the previous
cirruslabs/cachelayer${ref_name}baked into key → every PR isolated; onlymain → PRfallback crossed branchessetup-e2e-env(cache key needsnode_modulesto compute fingerprint)mainpushubuntu-latest, pinned topull_request.head.shaWhat changed
ci.yml— newpost-build-source-hashjob emits the canonical fingerprint and exposes it as a job output consumed by both build jobs.find-reusable-build(3-tier scan),check-force-builds(label +[force-builds]commit-message escape hatch; reads commit message via REST API to survive shallow checkout),post-build-source-hash(factored out for reuse).build-{ios,android}-e2e.yml— probe → gate → lean-repack vs heavy-native paths. Lean paths skip the workyarn build:repack:*doesn't need.setup-e2e-env— newinstall-foundryinput (defaulttrue, opt-out for build workflows whereyarn setup:github-cialready runsinstall:foundryup).METRO_MAX_WORKERSbumped2 → 6on the lean path (no Gradle/Xcode competing for RAM).cirruslabs/cacheforMetaMask.app/release.apk/release-androidTest.apk. Gradle, Xcode DerivedData, and.metamaskcaches kept (gated to the heavy path).Safety
statuses: write) → emptysource-fingerprint→ all reuse steps skipped → fresh build runs. Never "no build".build-source-hashstatus gates the OTA path inpush-eas-update.yml, so a JS-only OTA cannot ship after native code changes.docs/ci-build-reuse.md(new in this PR).Changelog
CHANGELOG entry: null
Related issues
Refs: Prior art in MetaMask extension — MetaMask/metamask-extension#41435
No issue: CI infrastructure improvement; no Jira ticket.
Manual testing steps
Screenshots/Recordings
Before
N/A — CI-only change; no UI impact.
After
N/A — CI-only change; no UI impact.
Pre-merge author checklist
Performance checks (if applicable)
For performance guidelines and tooling, see the Performance Guide.
Pre-merge reviewer checklist
Note
Medium Risk
Changes CI build/reuse logic and caching paths for iOS/Android E2E artifacts, which could cause unexpected stale/invalid artifacts or missed rebuilds if the fingerprint/status or artifact lookup is wrong. Scoped to CI/workflows, but failures can block or slow builds across PRs.
Overview
Enables cross-run, cross-PR reuse of native E2E build artifacts by introducing a canonical
@expo/fingerprintpublished as abuild-source-hashcommit status and using it to locate/download matching artifacts from prior workflow runs.Build workflows now gate between a full native build vs a lean repack path: they first check a
force-buildsoverride (PR label or[force-builds]commit token), then attempt to find/download reusable artifacts; on a hit they skip heavy setup (Gradle/Xcode) and only run repack + lightweight dependency setup.CI wiring is updated to add the
post-build-source-hashjob and passsource-fingerprintinto iOS/Android build jobs (with addedactions/statuses/pull-requestsread permissions),setup-e2e-envgains aninstall-foundrytoggle to avoid redundant installs, and repack throughput is tuned (e.g.,METRO_MAX_WORKERSincreased on reuse paths) with clearer guidance when repack detects a broken cached iOS app.Reviewed by Cursor Bugbot for commit 89e6bc5. Bugbot is set up for automated code reviews on this repo. Configure here.