Files
Sauci/.agents/learnings/promoted/2026-08-31-expo-prebuild-native-regression.md
T
jjbruntonandClaude Fable 5 7a76936829 docs(agents): promote v1.0.8 release learnings
Record three confirmed v1.0.8 failure modes (expo prebuild native
regressions, npm 10/11 lockfile divergence, local EAS build
preconditions) and promote each into docs/releasing.md, a new
docs/development/dependencies.md, and the release-preflight script.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-31 16:03:02 +01:00

67 lines
2.8 KiB
Markdown

---
id: 2026-08-31-expo-prebuild-native-regression
date: 2026-08-31
status: promoted
scope: apps/mobile native projects (ios/, android/) and expo prebuild
evidence: v1.0.8 SDK 54 to 56 upgrade, commits 604eec3, 7aca39a, 6bd04a6, 79233f5, b8cb2add
destination: apps/mobile/scripts/release-preflight.mjs, apps/mobile/scripts/release-preflight.test.mjs, and docs/releasing.md
review_after: 2026-11-30
---
## Symptom
`expo prebuild --clean` during the SDK 54 to 56 upgrade (and the
@bacons/apple-targets 0.1 to 5.0 bump) silently regressed four checked-in
native invariants. Each regression was caught only by a release gate or by
manual diffing against the last shipped tag (3fc6f8a, v1.0.7), not by
prebuild itself.
## Reproduction
Run `expo prebuild --clean` in apps/mobile against the upgraded SDK and diff
the regenerated ios/ and android/ projects against the previously committed
projects.
## Cause
1. Widget identity: apple-targets 5.x derives PRODUCT_BUNDLE_IDENTIFIER from
the target folder name, changing com.sauci.app.LiveDrawWidget to
com.sauci.app.widget, and repointed CODE_SIGN_ENTITLEMENTS to the
gitignored ios/.targets/LiveDrawWidget/generated.entitlements.
2. Android manifest lost the tools:node="remove" attributes on
READ_MEDIA_IMAGES and READ_MEDIA_VIDEO, so the built AAB regained
Play-forbidden permissions (verified via bundletool dump on the rejected
build 50 AAB).
3. iOS Info.plist gained dev-launcher-only keys NSBonjourServices
(_expo._tcp), NSLocalNetworkUsageDescription, and RCTMetroPort.
4. android/gradle.properties reset to stock -Xmx2048m
-XX:MaxMetaspaceSize=512m, causing Metaspace OOM in kspReleaseKotlin/CMake
under RN 0.85.
Separately, a package absent from the new SDK's bundledNativeModules
(expo-av) has no compatible release and fails the iOS archive (EXAV.h
imports removed ExpoModulesCore headers).
## Remediation
Fixed by restoring widget identity and tracking
targets/widget/generated.entitlements with a pinned bundleIdentifier
(604eec3); restoring manifest tools:node="remove" attributes (7aca39a);
removing the dev-launcher-only Info.plist keys (6bd04a6); raising
gradle.properties memory to 4096m/1024m (79233f5); and migrating expo-av to
expo-video/expo-audio (b8cb2add).
Extend apps/mobile/scripts/release-preflight.mjs with executable checks for
items 2 and 3 (item 1 is already covered by the existing LiveDrawWidget
preflight check; item 4 hard-fails the build by itself). Add an "After
native regeneration" checklist to docs/releasing.md.
## Evidence
`node apps/mobile/scripts/release-preflight.mjs` fails if the tracked
AndroidManifest.xml lacks tools:node="remove" on READ_MEDIA_IMAGES or
READ_MEDIA_VIDEO, or if ios/Sauci/Info.plist contains NSBonjourServices,
NSLocalNetworkUsageDescription, or RCTMetroPort.
`node --test apps/mobile/scripts/release-preflight.test.mjs` covers the new
checks.