Skip to content

[build-tools] Add 3rd party precompiled modules support#3573

Open
sjchmiela wants to merge 6 commits intomainfrom
stanley/add-precompiled-deps-support-2
Open

[build-tools] Add 3rd party precompiled modules support#3573
sjchmiela wants to merge 6 commits intomainfrom
stanley/add-precompiled-deps-support-2

Conversation

@sjchmiela
Copy link
Copy Markdown
Contributor

@sjchmiela sjchmiela commented Apr 2, 2026

Summary

Reintroduces support for third-party precompiled iOS modules in EAS Build as a best-effort optimization.

First-party prebuilds are now distributed through npm packages, so this change only covers downloading and preparing third-party precompiled module artifacts on the worker.

What changed

  • add worker/build-tools support for preparing third-party precompiled module archives before pod install
  • start third-party archive downloads during SPIN_UP_BUILDER so preparation can overlap with earlier build work
  • wait for third-party preparation before pod install, but only up to 15 seconds
  • continue with pod install if preparation fails or times out
  • stage extracted artifacts and only publish them to the final directory once preparation succeeds
  • route downloads through the CocoaPods proxy when available, with fallback to the direct URL
  • expose EXPO_USE_PRECOMPILED_MODULES=1 when EAS_USE_PRECOMPILED_MODULES=1
  • expose EXPO_PRECOMPILED_MODULES_PATH only when third-party downloads are enabled

Env behavior

  • EAS_USE_PRECOMPILED_MODULES=1

    • sets EXPO_USE_PRECOMPILED_MODULES=1
    • sets EXPO_PRECOMPILED_MODULES_PATH
    • starts third-party archive download/preparation
  • EAS_USE_PRECOMPILED_MODULES unset

    • does not set Expo precompiled-module env vars
    • does not start third-party preparation
  • EAS_USE_PRECOMPILED_MODULES=1 and EAS_DISABLE_THIRD_PARTY_PRECOMPILED_MODULES=1

    • sets EXPO_USE_PRECOMPILED_MODULES=1
    • does not set EXPO_PRECOMPILED_MODULES_PATH
    • does not start third-party download/preparation

Implementation notes

  • downloads two third-party zip artifacts and extracts them into a shared destination
  • downloads run concurrently; extraction is serialized
  • timeout only bounds how long pod install waits
  • final publish uses a synchronous critical section so timeout cannot interleave between removing the old directory and moving the staged one into place

Test coverage

  • unit tests for env gating, proxy fallback, timeout behavior, failure handling, and pod-install wait behavior
  • integration test that extracts fixture Debug/Release archives and verifies the merged output tree

@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 2, 2026

Subscribed to pull request

File Patterns Mentions
**/* @douglowder

Generated by CodeMention

@codecov
Copy link
Copy Markdown

codecov bot commented Apr 2, 2026

Codecov Report

❌ Patch coverage is 95.09804% with 5 lines in your changes missing coverage. Please review.
✅ Project coverage is 54.43%. Comparing base (a439721) to head (902b9d1).
⚠️ Report is 2 commits behind head on main.

Files with missing lines Patch % Lines
...ckages/build-tools/src/utils/precompiledModules.ts 94.45% 5 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3573      +/-   ##
==========================================
+ Coverage   54.27%   54.43%   +0.17%     
==========================================
  Files         820      822       +2     
  Lines       35011    35143     +132     
  Branches     7248     7263      +15     
==========================================
+ Hits        18998    19126     +128     
- Misses      15926    15930       +4     
  Partials       87       87              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@sjchmiela sjchmiela added the no changelog PR that doesn't require a changelog entry label Apr 2, 2026
@sjchmiela sjchmiela requested a review from Copilot April 2, 2026 20:13
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Reintroduces third-party precompiled iOS module preparation in worker builds (previously in #3556), updating the download URLs and wiring the preparation into iOS pod-install flows.

Changes:

  • Add build-tools utilities to download/extract third-party precompiled module archives and wait (with timeout) before pod install.
  • Start preparation early in worker builds and expose env vars (EXPO_USE_PRECOMPILED_MODULES, optionally EXPO_PRECOMPILED_MODULES_PATH) for flagged iOS jobs.
  • Add unit + integration test coverage and fixtures for the precompiled modules preparation behavior.

Reviewed changes

Copilot reviewed 12 out of 14 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
packages/worker/src/env.ts Enables precompiled-module env vars for flagged iOS jobs and sets the modules path when third-party downloads are enabled.
packages/worker/src/config.ts Adds the configured third-party precompiled modules download URLs to worker config.
packages/worker/src/build.ts Starts background preparation early in the worker lifecycle.
packages/worker/src/unit/env.test.ts Adds tests covering env var behavior for enabled/disabled third-party module downloads.
packages/build-tools/src/utils/precompiledModules.ts Implements download/extract/publish logic, plus wait-with-timeout coordination.
packages/build-tools/src/utils/tests/precompiledModules.test.ts Unit tests for proxy download, fallback, extraction, failure handling, and timeout behavior.
packages/build-tools/src/utils/integration-tests/precompiledModules.test.ts Integration test validating merged Debug/Release extraction into the expected destination tree.
packages/build-tools/src/utils/integration-tests/fixtures/precompiledModules/xcframeworks-Debug.zip Adds debug fixture archive used by the integration test.
packages/build-tools/src/utils/integration-tests/fixtures/precompiledModules/xcframeworks-Release.zip Adds release fixture archive used by the integration test.
packages/build-tools/src/steps/functions/installPods.ts Waits (best-effort) for preparation before running pod install in the steps-based flow.
packages/build-tools/src/steps/functions/tests/installPods.test.ts Tests the new wait-and-continue behavior for the steps-based pod install.
packages/build-tools/src/ios/pod.ts Waits (best-effort) for preparation before running pod install in the legacy pod flow.
packages/build-tools/src/ios/tests/pod.test.ts Tests that legacy pod install waits for prep and continues on prep failure.
packages/build-tools/src/index.ts Exports the new precompiled modules helpers from @expo/build-tools.

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

Comment on lines +184 to +193
url: string;
archivePath: string;
cocoapodsProxyUrl?: string;
logger: bunyan;
signal: AbortSignal;
}): Promise<void> {
const proxiedUrl = cocoapodsProxyUrl
? (() => {
const parsedUrl = new URL(url);
return `${cocoapodsProxyUrl}/${parsedUrl.hostname}${parsedUrl.pathname}${parsedUrl.search}${parsedUrl.hash}`;
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

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

The timeout/abort logic won't cancel an in-flight download: @expo/downloader doesn't accept an AbortSignal, and the calls here don't set any per-request timeout. This means a slow/hung download can keep running (and hold disk space in tmp) even after waitForThirdPartyPrecompiledModulesPreparationAsync() times out. Consider adding a reasonable download timeout (possibly configurable) and/or extending the downloader usage to support cancellation via AbortSignal.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I know

Comment on lines +101 to +104
thirdPartyPrecompiledModulesUrls: [
'https://storage.googleapis.com/turtle-v2/precompiled-modules/b3e34ec259271164e537f6d33b446130ebc666aa/xcframeworks-Debug.zip',
'https://storage.googleapis.com/turtle-v2/precompiled-modules/b3e34ec259271164e537f6d33b446130ebc666aa/xcframeworks-Release.zip',
],
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

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

These precompiled-module URLs are hard-coded in worker runtime config. That makes rotating the artifact set (or switching buckets/versions) require a worker release rather than a runtime config update, unlike other URLs (npm/maven/cocoapods) that come from WORKER_RUNTIME_CONFIG_BASE64. Consider sourcing this list from runtime config (with these as defaults) to make rollouts and emergency rollbacks operationally safer.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I know

@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 2, 2026

⏩ The changelog entry check has been skipped since the "no changelog" label is present.

@sjchmiela sjchmiela requested a review from chrfalch April 2, 2026 20:23
@sjchmiela sjchmiela changed the title Add precompiled iOS module preparation to worker builds [build-tools] Add 3rd party precompiled modules support Apr 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

no changelog PR that doesn't require a changelog entry

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants