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>
2.8 KiB
id, date, status, scope, evidence, destination, review_after
| id | date | status | scope | evidence | destination | review_after |
|---|---|---|---|---|---|---|
| 2026-08-31-expo-prebuild-native-regression | 2026-08-31 | promoted | apps/mobile native projects (ios/, android/) and expo prebuild | v1.0.8 SDK 54 to 56 upgrade, commits 604eec3, 7aca39a, 6bd04a6, 79233f5, b8cb2add |
apps/mobile/scripts/release-preflight.mjs, apps/mobile/scripts/release-preflight.test.mjs, and docs/releasing.md | 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
- 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.
- 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).
- iOS Info.plist gained dev-launcher-only keys NSBonjourServices (_expo._tcp), NSLocalNetworkUsageDescription, and RCTMetroPort.
- 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.