Repository navigation
💚 app: raise ios deployment targets - #1429
cruzdanilo wants to merge 1 commit into
Conversation
🦋 Changeset detectedLatest commit: 42e5595 The changes in this PR will be included in the next version bump. This PR includes changesets to release 0 packagesWhen changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
Warning Review limit reachedYou've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Next included review available in 15 minutes. View limit details
WalkthroughThe OneSignal iOS deployment target is set to 15.1. A React Native patch applies the minimum supported deployment target to pod and resource-bundle targets. The package configuration registers the patch, and an empty changeset file is added. ChangesiOS Deployment Target Alignment
Priority: ➖ Normal Estimated code review effort: 2 (Simple) | ~10 minutes Change: Bug fix Suggested reviewers: Merge Risk: 🟠 High · up to
|
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
this commit clears the deployment-target errors. the next xcode 27.1 error is in expo-router 55: not fixing it now: every xcode 27.1 fix changes the expo fingerprint, and the fingerprint has to stay frozen so ota keeps working. this waits for the next fingerprint-breaking upgrade, which needs an expo-router fix or a newer sdk on top of this commit. Generated by Claude Code |
850f134 to
be91245
Compare
37003e9 to
0e608c9
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
ℹ️ Review info
⚙️ Run configuration
- Configuration used: Organization UI
- Review profile: ASSERTIVE
- Plan: Advanced
- Run ID:
e176d817-203e-42d6-9f60-081e509c5a94
⛔ Files ignored due to path filters: 1
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing: 4
.changeset/sturdy-pods-align.mdapp.config.tspackage.jsonpatches/react-native.patch
Included review availability: This review used your included allowance. Your plan provides up to 1 included review per hour; 0 remain after this review.
| "onesignal-expo-plugin", | ||
| { | ||
| mode: env.NODE_ENV === "production" ? "production" : "development", | ||
| iPhoneDeploymentTarget: "15.1", |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
🔎 Supported by static analysis
🏁 Script executed:
git diff --no-ext-diff --unified=20 be91245dcdc099be97f7aa9b891a4087ac742d6f 0e608c93dea3f966e29c0e50e419e41e6354f707 -- app.config.ts
rg -n 'ios_build|Xcode|image|fingerprint|expo-router|subtitle' .eas .github app.config.ts package.jsonRepository: exactly/exa
Length of output: 4565
🏁 Script executed:
set -u
printf '%s\n' '--- changed files ---'
git diff --name-status be91245dcdc099be97f7aa9b891a4087ac742d6f 0e608c93dea3f966e29c0e50e419e41e6354f707
printf '%s\n' '--- production workflow ---'
nl -ba .eas/workflows/production.yaml
printf '%s\n' '--- local workflow ios section ---'
nl -ba .eas/workflows/local.yaml | sed -n '100,165p'
printf '%s\n' '--- dependency declarations and lockfile matches ---'
rg -n -F --glob 'package.json' -e '"expo-router"' -e '"expo"' -e '"expo-build-properties"' -e '"onesignal-expo-plugin"'
rg -n -F --glob '*lock*' --glob 'yarn.lock' --glob 'package-lock.json' --glob 'pnpm-lock.yaml' -e 'expo-router@' -e 'expo-router:' -e 'onesignal-expo-plugin'
printf '%s\n' '--- relevant source and patches ---'
rg -n -F --glob '!node_modules/**' --glob '!dist/**' --glob '!build/**' -e 'LinkPreviewNativeActionView' -e 'subtitle' -e 'iPhoneDeploymentTarget' -e 'react-native.patch' .
printf '%s\n' '--- app config and package scripts ---'
nl -ba app.config.ts | sed -n '70,165p'
nl -ba package.json | sed -n '1,180p'
printf '%s\n' '--- package manager files ---'
find . -maxdepth 2 -type f \( -name 'yarn.lock' -o -name 'package-lock.json' -o -name 'pnpm-lock.yaml' -o -name 'bun.lockb' -o -name 'bun.lock' \) -printRepository: exactly/exa
Length of output: 41021
🏁 Script executed:
set -u
printf '%s\n' '--- EAS build profiles and image configuration ---'
nl -ba eas.json
printf '%s\n' '--- all build/profile/image references ---'
rg -n -F --glob '.eas/**' --glob 'eas.json' --glob 'package.json' -e 'e2e:production' -e 'ios' -e 'image' -e 'resourceClass' -e 'distribution' -e 'developmentClient'
printf '%s\n' '--- full PR diff for mobile build inputs ---'
git diff --no-ext-diff --unified=12 be91245dcdc099be97f7aa9b891a4087ac742d6f 0e608c93dea3f966e29c0e50e419e41e6354f707 -- package.json pnpm-lock.yaml patches/react-native.patch .changeset/sturdy-pods-align.md
printf '%s\n' '--- exact locked package blocks ---'
sed -n '9660,9695p' pnpm-lock.yaml
sed -n '12435,12465p' pnpm-lock.yaml
printf '%s\n' '--- repository references to reported build/error ---'
rg -n -F --hidden --glob '!node_modules/**' --glob '!dist/**' --glob '!build/**' -e 'b61d1692' -e 'LinkPreviewNativeActionView.swift' -e 'subtitle.*iOS 16' -e 'Xcode 27.1' -e 'expo-router 55' -e 'fingerprint' .Repository: exactly/exa
Length of output: 45647
🌐 Web query:
official expo-router 55.0.8 LinkPreviewNativeActionView.swift subtitle iOS 16
💡 Result:
In the Expo **SDK 55** source for `LinkPreviewNativeActionView.swift`, both `menuAction.subtitle = subtitle` and `baseUiAction.subtitle = subtitle` are **outside** an `if #available(iOS 16.0, *)` check. The nearby availability checks guard other properties, not these subtitle assignments. That supports the concern that this code may fail to compile when the deployment target is below iOS 16. ([github.com](https://github.com/expo/expo/blob/sdk-55/packages/expo-router/ios/LinkPreview/LinkPreviewNativeActionView.swift))
**Version caveat:** I verified the `sdk-55` branch, not the exact `expo-router@55.0.8` published package, so I can’t confirm those lines are identical in that patch release. The npm listing confirms `55.0.8` exists. ([github.com](https://github.com/expo/expo/blob/sdk-55/packages/expo-router/ios/LinkPreview/LinkPreviewNativeActionView.swift))
Citations:
- 1: https://github.com/expo/expo/blob/sdk-55/packages/expo-router/ios/LinkPreview/LinkPreviewNativeActionView.swift
- 2: https://github.com/expo/expo/blob/sdk-55/packages/expo-router/ios/LinkPreview/LinkPreviewNativeActionView.swift
🏁 Script executed:
python3 - <<'PY'
import io, json, tarfile, urllib.request
urls = [
"https://registry.npmjs.org/expo-router/55.0.8",
"https://registry.npmjs.org/react-native/0.83.4",
]
for url in urls:
print("---", url, "---")
with urllib.request.urlopen(url, timeout=20) as response:
data = json.load(response)
print("version:", data.get("version"))
print("dist.tarball:", data.get("dist", {}).get("tarball"))
if data.get("name") == "expo-router":
tarball = data["dist"]["tarball"]
with urllib.request.urlopen(tarball, timeout=20) as response:
archive = tarfile.open(fileobj=io.BytesIO(response.read()), mode="r:gz")
for member in archive.getmembers():
if member.name.endswith("ios/LinkPreview/LinkPreviewNativeActionView.swift"):
print("SOURCE", member.name)
text = archive.extractfile(member).read().decode()
for n, line in enumerate(text.splitlines(), 1):
if "subtitle" in line or "available" in line or "menuAction" in line or "baseUiAction" in line:
print(f"{n}: {line}")
PY
printf '%s\n' '--- fingerprint configuration ---'
nl -ba fingerprint.config.cjs
printf '%s\n' '--- base/head native-target inputs ---'
git show be91245dcdc099be97f7aa9b891a4087ac742d6f:app.config.ts | nl -ba | sed -n '95,115p'
git show be91245dcdc099be97f7aa9b891a4087ac742d6f:package.json | nl -ba | sed -n '245,262p'
git show be91245dcdc099be97f7aa9b891a4087ac742d6f:pnpm-lock.yaml | rg -n -F -m 1 -e 'react-native@0.83.4:' -e 'expo-router@55.0.8:' -e 'react-native:' -e 'expo-router:'Repository: exactly/exa
Length of output: 3997
🌐 Web query:
Expo expo-router LinkPreviewNativeActionView subtitle iOS 16 fix issue
💡 Result:
If you’re seeing **`'subtitle' is only available in iOS 16.0 or newer`** in `LinkPreviewNativeActionView.swift`, the code assigns `subtitle` to both `UIMenu` and `UIAction` without an iOS availability check. ([raw.githubusercontent.com](https://raw.githubusercontent.com/expo/expo/main/packages/expo-router/ios/LinkPreview/LinkPreviewNativeActionView.swift))
**Workaround:** set your app’s iOS deployment target to **16.0 or later** (and ensure the CocoaPods targets are compatible), then regenerate/reinstall the iOS project. Expo’s `ios.deploymentTarget` controls the app’s minimum iOS version. (GitHub issue 8447 in multica-ai/multica (link omitted to avoid creating a cross-reference))
If you need to support iOS 15 or earlier, the source shown doesn’t establish an Expo fix; the native code would need to guard both subtitle assignments with `if #available(iOS 16.0, *)`. Note the reported error is from an Expo Router 55.0.24 setup with Xcode 27, so verify against your installed version. (GitHub issue 8447 in multica-ai/multica (link omitted to avoid creating a cross-reference))
Citations:
- 1: https://raw.githubusercontent.com/expo/expo/main/packages/expo-router/ios/LinkPreview/LinkPreviewNativeActionView.swift
- 2: GitHub issue 8447 in multica-ai/multica (link omitted to avoid creating a cross-reference)
- 3: GitHub issue 8447 in multica-ai/multica (link omitted to avoid creating a cross-reference)
🏁 Script executed:
python3 - <<'PY'
import io, json, tarfile, urllib.request
url = "https://registry.npmjs.org/react-native/0.83.4"
with urllib.request.urlopen(url, timeout=20) as response:
metadata = json.load(response)
tarball = metadata["dist"]["tarball"]
with urllib.request.urlopen(tarball, timeout=20) as response:
archive = tarfile.open(fileobj=io.BytesIO(response.read()), mode="r:gz")
for member in archive.getmembers():
name = member.name
if name.endswith("scripts/cocoapods/utils.rb") or name.endswith("scripts/cocoapods/helpers.rb") or name.endswith("scripts/cocoapods/constants.rb"):
text = archive.extractfile(member).read().decode(errors="replace")
print("---", name, "---")
for n, line in enumerate(text.splitlines(), 1):
if "min_ios_version_supported" in line or "IPHONEOS_DEPLOYMENT_TARGET" in line:
print(f"{n}: {line}")
PY
printf '%s\n' '--- current app iOS config ---'
nl -ba app.config.ts | sed -n '1,75p'
printf '%s\n' '--- base and head deployment-target references ---'
for rev in be91245dcdc099be97f7aa9b891a4087ac742d6f 0e608c93dea3f966e29c0e50e419e41e6354f707; do
echo "--- $rev ---"
git grep -n -E 'deploymentTarget|IPHONEOS_DEPLOYMENT_TARGET|iPhoneDeploymentTarget|min_ios_version_supported' "$rev" -- app.config.ts package.json pnpm-lock.yaml patches eas.json .eas 2>/dev/null || true
done
printf '%s\n' '--- exact expo-router source excerpt from the published package ---'
python3 - <<'PY'
import io, json, tarfile, urllib.request
url = "https://registry.npmjs.org/expo-router/55.0.8"
with urllib.request.urlopen(url, timeout=20) as response:
metadata = json.load(response)
with urllib.request.urlopen(metadata["dist"]["tarball"], timeout=20) as response:
archive = tarfile.open(fileobj=io.BytesIO(response.read()), mode="r:gz")
member = next(m for m in archive.getmembers() if m.name.endswith("ios/LinkPreview/LinkPreviewNativeActionView.swift"))
lines = archive.extractfile(member).read().decode().splitlines()
for n in range(100, 146):
print(f"{n}: {lines[n-1]}")
PYRepository: exactly/exa
Length of output: 7277
🏁 Script executed:
python3 - <<'PY'
import io, json, tarfile, urllib.request
metadata = json.load(urllib.request.urlopen("https://registry.npmjs.org/react-native/0.83.4", timeout=20))
archive = tarfile.open(fileobj=io.BytesIO(urllib.request.urlopen(metadata["dist"]["tarball"], timeout=20).read()), mode="r:gz")
for member in archive.getmembers():
if member.name.endswith("scripts/cocoapods/helpers.rb"):
lines = archive.extractfile(member).read().decode(errors="replace").splitlines()
for n in range(75, 92):
print(f"{member.name}:{n}: {lines[n-1]}")
PYRepository: exactly/exa
Length of output: 1258
Make expo-router compatible with the iOS 15.1 target before merging.
expo-router@55.0.8 assigns subtitle to iOS 16-only APIs without availability guards. The fresh build required by this fingerprint change can therefore fail on the latest Xcode image. This failure is pre-existing in expo-router, but it blocks the new build required by this PR. Upgrade to a compatible release or apply the availability fix. Raising the app target to iOS 16 is an alternative, but it removes iOS 15.1 support.
0e608c9 to
6a6d1b7
Compare
6a6d1b7 to
43e6d70
Compare
43e6d70 to
2bd789b
Compare
2bd789b to
8ff366f
Compare
8ff366f to
42e5595
Compare
Requested by danilo · project thread
before: the first fresh ios build on eas's latest image (xcode 27.1), e2e:local on the
@exactly/mobile@1.2.36tag, failed in xcodebuild. xcode 27 rejects any target below ios 15.0, and five were below it: the resource bundles of sdwebimage (9.0), reachabilityswift (12.0), rnsvg's filters (12.4) and asyncstorage (13.4), and the onesignal notification service extension (11.0). every other ios build since the image change reused a binary built on the old image, so the next native change or production ios build would hit it too. the last production and beta ios builds (10-14, 10-16) ran on the old image.after: those pod resource bundles and the extension target ios 15.1, like the app.
how:
react_native_post_installraises each pod to its 15.1 minimum, but only the pod's main target, not its resource bundles.patches/react-native.patchbackports the upstream fix verbatim (Fix iOS deployment targets for CocoaPods resource bundles react/react-native#58687). it is on react native's main but in no release yet, so the patch goes away with the upgrade that ships it.iPhoneDeploymentTargetoption sets 15.1.da028c61to3334b138, androidb26eff2fto97d6e49f), so the next release needs new store builds.evidence: e2e:local run 01a1505d on the same tree, building both apps fresh (in progress).
Generated by Claude Code
Summary by CodeRabbit