Skip to content

fix(expo): floor the iOS deployment target instead of pinning it to 16.4 - #1072

Merged
boorad merged 6 commits into
mainfrom
fix/expo-deployment-target-override
Aug 14, 2026
Merged

fix(expo): floor the iOS deployment target instead of pinning it to 16.4#1072
boorad merged 6 commits into
mainfrom
fix/expo-deployment-target-override

Conversation

@boorad

@boorad boorad commented Aug 14, 2026

Copy link
Copy Markdown
Collaborator

Summary

The Expo config plugin hardcoded iOS 16.4 in two places, which made it a ceiling as well as a floor: any app needing a higher target got silently downgraded. Reported with react-native-executorch, which requires iOS 17.0.

The fix reads the deployment target at mod time rather than scanning static plugins config, so 16.4 becomes a floor everywhere and an app that raises the target — by any means — keeps it.

Also carries an unrelated /review tooling change (see below).

Changes

Expo plugin (withXCode.ts)

  • withPodfileProperties — raises ios.deploymentTarget in Podfile.properties.json only when it's below 16.4.
  • withXcodeProject — same floor on the app target's IPHONEOS_DEPLOYMENT_TARGET. Only touches an explicit value; writing one that was inherited from the project level could itself be a downgrade.
  • Podfile post_install — compares with Gem::Version instead of to_f. to_f parses '16.10' as 16.1, so it considered 16.10 older than 16.4 and downgraded it; it also broke on 3-component versions.
  • Drops the expo-build-properties dependency — apps no longer need it installed for this plugin to work.
  • CIvalidate-js now runs the package's jest suite, and triggers on test/**.

Reading actual values also removed the need for a static config.plugins scan, so that code is deleted rather than fixed.

/review command (.agents/commands/review.md)

Unrelated to the fix, bundled here rather than as a separate PR.

/review previously refused to run when the session had prior history, telling the user to start a fresh session by hand. It now spawns a subagent with a clean context instead, picking the type from what the diff touches. Also switches the review base to origin/main and broadens the verification step to the toolchains a given diff actually touches. Mirrors the equivalent commands in our other repos.

Testing

bun run test in packages/react-native-quick-crypto — 15 tests.

The generated Ruby is a template string that nothing else in the toolchain parses, so it's tested against a real interpreter: ruby -c for syntax, plus executing the block over a set of build configs to assert the floor semantics. Those tests are mutation-checked — reverting to to_f fails them with - "16.10" / + "16.4".

The Ruby tests skip automatically when ruby isn't on PATH.

⚠️ Not validated end-to-end. The Podfile patch needs a real expo prebuild in a consumer app. The example app can't exercise it — example/ios/Podfile already pins IPHONEOS_DEPLOYMENT_TARGET, so the patch branch is a no-op in-repo.

Fixes #1066

boorad added 2 commits August 14, 2026 19:18
The config plugin hardcoded 16.4 in both withBuildProperties and the
Podfile post_install patch, overriding apps that need a higher target
(e.g. react-native-executorch requires 17.0).

Read the app's own expo-build-properties deploymentTarget and only raise
it when it's below our 16.4 minimum.
Reads the target at mod time (withPodfileProperties + withXcodeProject)
rather than scanning static plugins config, so 16.4 is a floor everywhere
and an app that raises the target by any means keeps it.

The Podfile post_install fallback now compares with Gem::Version rather
than to_f, which treated '16.10' as 16.1 and silently downgraded it.

Drops the expo-build-properties dependency - apps no longer need it
installed for this plugin to work.

Tests cover the generated Ruby against a real interpreter, and CI now
runs the package's jest suite.
@boorad boorad self-assigned this Aug 14, 2026
@vercel

vercel Bot commented Aug 14, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
react-native-quick-crypto Ready Ready Preview Aug 14, 2026 11:30pm

Request Review

…topping

/review previously refused to run when the session had prior history,
telling the user to start a fresh session by hand. Now it spawns a
subagent with a clean context, picking the type from what the diff
touches (crypto/cpp/typescript specialist, or general-purpose).

Also switches the review base to origin/main, since a stale local main
silently drags already-merged commits into scope, and broadens the
verification step to the toolchains a given diff actually touches.

Mirrors the equivalent commands in the spicy and trading repos.
@github-actions

github-actions Bot commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

🤖 End-to-End Test Results - iOS

Status: ✅ Passed
Platform: iOS
Run: 31850558303

📸 Final Test Screenshot

Maestro Test Results - ios

Screenshot automatically captured from End-to-End tests and will expire in 30 days


This comment is automatically updated on each test run.

boorad added 2 commits August 14, 2026 19:23
…tree

The jest suites only ever ran locally, where @babel/runtime hoists to the
workspace root from example/. On a clean install it isn't resolvable from
packages/react-native-quick-crypto, so both suites failed to run as soon
as CI started invoking them.
git diff A..B compares endpoints, not the merge-base, so anything merged
into origin/main since the branch point rendered as an inverse diff - the
exact scope explosion step 1 was added to prevent. Observed live: 8 files
instead of 2.

Note that git log takes two dots and git diff takes three, so the fix
documents that rather than looking like a typo to the next editor.

Also puts uncommitted work in scope and disambiguates bun run test.
…udit

Both are reached through react-native's own tree, which enters the audit
as a peer of react-native-quick-base64. metro is the bundler - it is not
in a consumer's runtime bundle, which is exactly what this job's comment
says it means to exclude.

Excluding it at install time doesn't work: bun audit resolves peers from
the registry regardless of what is installed, so --omit=peer and
[install] peer = false both leave the chain in the graph. --ignore is the
only lever, and it is per-advisory, so anything new still fails the job.
@github-actions

Copy link
Copy Markdown
Contributor

🤖 End-to-End Test Results - Android

Status: ✅ Passed
Platform: Android
Run: 31850558208

📸 Final Test Screenshot

Maestro Test Results - android

Screenshot automatically captured from End-to-End tests and will expire in 30 days


This comment is automatically updated on each test run.

@boorad
boorad merged commit 53ef5f7 into main Aug 14, 2026
10 checks passed
@boorad
boorad deleted the fix/expo-deployment-target-override branch August 14, 2026 23:49
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.

🐛 withXCode.js creates problems with deploymentTarget forcing it to 16.4

1 participant