Skip to content

[build-tools] Restore maestro-runner WDA cache - #4195

Open
sjchmiela wants to merge 3 commits into
mainfrom
stanley/download-maestro-runner-wda-cache
Open

[build-tools] Restore maestro-runner WDA cache#4195
sjchmiela wants to merge 3 commits into
mainfrom
stanley/download-maestro-runner-wda-cache

Conversation

@sjchmiela

@sjchmiela sjchmiela commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

Why

maestro-runner needs WDA driver to run tests. By default it compiles it on first run which takes a minute.

How

Compiled WDA on all images, uploaded to turtle-v2 GCS and added optimistic download to eas/install_maestro. See https://github.com/expo/turtle-v2/pull/2603.

Test plan

https://staging.expo.dev/accounts/expo-services/projects/workflows-testing/workflows/01a0009e-b171-7497-9335-af1fc470a8d5

@codecov

codecov Bot commented Aug 14, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 91.89189% with 6 lines in your changes missing coverage. Please review.
✅ Project coverage is 63.77%. Comparing base (1c08266) to head (9890a1e).

Files with missing lines Patch % Lines
.../build-tools/src/steps/functions/installMaestro.ts 87.76% 6 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #4195      +/-   ##
==========================================
+ Coverage   63.73%   63.77%   +0.04%     
==========================================
  Files        1030     1032       +2     
  Lines       47448    47508      +60     
  Branches     9977     9989      +12     
==========================================
+ Hits        30237    30292      +55     
+ Misses      17110    17101       -9     
- Partials      101      115      +14     

☔ View full report in Codecov by Harness.
📢 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 Aug 14, 2026
@sjchmiela
sjchmiela marked this pull request as ready for review August 14, 2026 14:19
@sjchmiela
sjchmiela requested review from hSATAC and a lite review from Copilot and removed request for hSATAC August 14, 2026 14:19

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR restores a prebuilt WebDriverAgent (WDA) cache for maestro-runner on macOS build runtimes to avoid the first-run WDA compilation cost, by downloading an archive from turtle-v2 (optionally via a proxy) and materializing per-iOS-runtime cache directories. It also factors out shared proxy URL rewriting logic and adds small iOS/Xcode utility helpers with tests.

Changes:

  • Add WDA cache installation to eas/install_maestro for maestro-runner on Darwin (download + extract + copy to runtime-specific cache paths).
  • Add utilities to detect Xcode version and available iOS simulator runtime versions (with unit tests).
  • Extract getProxiedDownloadUrl into a shared utility and reuse it from xcactivitylog parsing.

Reviewed changes

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

Show a summary per file
File Description
packages/build-tools/src/utils/IosSimulatorUtils.ts Adds a helper to list available iOS runtime versions via xcrun simctl.
packages/build-tools/src/utils/download.ts Introduces shared proxy URL rewriting helper for GCS downloads.
packages/build-tools/src/utils/tests/IosSimulatorUtils.test.ts Adds unit coverage for the new runtime-version helper.
packages/build-tools/src/steps/utils/ios/xcactivitylog.ts Reuses shared proxy URL helper instead of local implementation.
packages/build-tools/src/steps/functions/installMaestro.ts Implements optimistic WDA cache download/extract/copy for maestro-runner on macOS.
packages/build-tools/src/steps/functions/tests/installMaestro.test.ts Adds tests validating WDA cache installation + fallback behavior.
packages/build-tools/src/ios/xcode.ts Adds a helper to parse Xcode version from xcodebuild -version.
packages/build-tools/src/ios/tests/xcode.test.ts Adds unit tests for Xcode version parsing + error case.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread packages/build-tools/src/utils/download.ts
@sjchmiela
sjchmiela force-pushed the stanley/download-maestro-runner-wda-cache branch from d7a1aaa to 9890a1e Compare August 20, 2026 10:20
@github-actions

Copy link
Copy Markdown

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

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 9 out of 9 changed files in this pull request and generated no new comments.

Suppressed comments (1)

packages/build-tools/src/ios/xcode.ts:11

  • getXcodeVersionAsync only throws a SystemError when parsing fails; if xcodebuild -version fails to spawn (missing binary, non-zero exit, permission issues), the raw spawn error will bubble up and may not be handled consistently by callers. The previous inlined implementation wrapped spawn failures in a SystemError with a cause, which provides clearer and more uniform error reporting.
export async function getXcodeVersionAsync({ env }: { env: NodeJS.ProcessEnv }): Promise<string> {
  const { stdout } = await spawn('xcodebuild', ['-version'], { stdio: 'pipe', env });
  const version = /^Xcode\s+(\d+(?:\.\d+)*)$/m.exec(stdout)?.[1];
  if (!version) {
    throw new SystemError(`Failed to determine Xcode version from: ${stdout.trim()}`);
  }
  return version;

@sjchmiela
sjchmiela requested a review from hSATAC August 20, 2026 11:16

@hSATAC hSATAC left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Looks good overall, approving. Left a few questions inline — I may be missing some context around the WDA/turtle-v2 side.

maestroRunnerHome,
'cache',
'wda-builds',
`sim-ios${runtimeVersion}-iphone`,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think this may miss the cache on patched runtimes.

simctl list runtimes --json gives us the full version (e.g. 26.3.1), but maestro-runner derives the cache key from the runtime identifier (iOS-26-326.3). So we'd write sim-ios26.3.1-iphone here while runner looks for sim-ios26.3-iphone.

I haven't checked what versions we currently have on the images, so maybe I'm missing something there. Should we derive this from identifier too, to match runner?

const archivePath = path.join(tempDirectory, 'wda-cache.tar.gz');
const directArchiveUrl =
`https://storage.googleapis.com/turtle-v2/maestro-runner-wda-cache/` +
`xcode-${encodeURIComponent(xcodeVersion)}-wda-${encodeURIComponent(wdaVersion)}.tar.gz`;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I'm not sure I understand how this lines up with the turtle-v2 upload side.

This looks for xcode-<xcodeVersion>-wda-<wdaVersion>.tar.gz, but turtle-v2#2603 seems to upload image-keyed artifacts like macos-sequoia-15.6-xcode-26.0-wda-11.1.3.tar.gz.

The existing xcode-* objects are there, so I assume there's another step I'm missing. Are we planning to change the turtle-v2 naming to match this?

If so, I think the two Xcode 16.4 images would also collapse to the same object name, so the artifact count/check there may need an update too.

logger.info(`Downloading the prebuilt WebDriverAgent cache for Xcode ${xcodeVersion}`);
if (proxiedArchiveUrl) {
try {
await downloadFile(proxiedArchiveUrl, archivePath, { retry: 3 });

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Should we add a timeout to these downloads?

AFAICT @expo/downloader passes this through to got, and got doesn't have a default timeout. If the connection stalls after being established, this best-effort cache download could hang until the build timeout instead of falling back.

xcactivitylog.ts uses timeout: 20_000 for the same proxied-download pattern.

import spawn from '@expo/turtle-spawn';

export async function getXcodeVersionAsync({ env }: { env: NodeJS.ProcessEnv }): Promise<string> {
const { stdout } = await spawn('xcodebuild', ['-version'], { stdio: 'pipe', env });

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Was dropping the SystemError wrapping around the xcodebuild -version spawn intentional?

Previously a spawn failure was wrapped as SystemError('Failed to get Xcode version', { cause }). Now only the parse failure is a SystemError, so things like a bad DEVELOPER_DIR would propagate as the raw spawn error at the maestro-runner version-selection call site.

The WDA cache path catches this anyway, so I think this only affects the other caller. Maybe intentional, just wanted to check.

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.

3 participants