chore(deps): upgrade to Expo SDK 56 (React Native 0.85)#87
Conversation
Bump the module and both test apps from Expo SDK 55 to 56: - expo ^56.0.12, expo-module-scripts 56.0.3, react-native 0.85.3, react 19.2.3 - iOS min deployment 15.1 -> 16.4 (podspec, Package.swift, with-ios-tests plugin) - Android fallbacks compileSdk/targetSdk 34->35, minSdk 21->24 - CI Xcode 26.3 -> 26.4 Make the podspec precompile-friendly: wrap only source_files/exclude_files in the try_link_with_prebuilt_xcframework guard (mirroring expo-modules-core's own podspec) so a future Expo-published prebuilt xcframework can short-circuit source compilation. Deps, vendored frameworks, and resources stay unconditional. Note: SDK 56 has no supported third-party SPM/precompiled-module path yet, so the CocoaPods podspec remains the integration path. Sentry-cocoa pin follows the resolved @sentry/react-native 8.15.1: 9.15.0 -> 9.18.0 (podspec + Package.swift + Package.resolved), sentry-android-core 8.43 -> 8.44. SDK 56 tries to downgrade @sentry/react-native to 7.x, so pin it (and typescript) via expo.install.exclude in both apps. Drop top-level `splash` from the test apps (invalid in the SDK 56 config schema). Minor: type-only import in ComapeoCoreModule.ts (verbatimModuleSyntax), worktree-safe git exclude path resolution in eslint.config.js, and unused test params removed in server-helper.test.mjs. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
|
Warning Review the following alerts detected in dependencies. According to your organization's Security Policy, it is recommended to resolve "Warn" alerts. Learn more about Socket for GitHub.
|
The macos-15 runner image tops out at Xcode 26.3, so the 26.4 select step failed immediately (`invalid developer directory`). Expo SDK 56 requires Xcode >= 26.4, which only the macos-26 image provides (ships 26.0.1 through 26.5, incl. 26.4.1). Move all iOS jobs to macos-26 and pin Xcode_26.4.1. Refresh the now-stale runner/Xcode and sentry-cocoa (9.18.0) comments. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The E2E release builds (assembleRelease / archive) failed at the "Bundle React Native code and images" Metro step with `Cannot find module 'babel-preset-expo'` on both iOS and Android. Under SDK 55 babel-preset-expo was hoisted to each app's node_modules root; the SDK 56 install left only a stale nested copy (expo/node_modules/babel-preset-expo@55.0.18), which Metro's babel.config.js (`presets: ['babel-preset-expo']`) can't resolve from the app root. Add it as a direct dep (~56.0.0) in both apps. Debug builds didn't surface this because they don't run the release JS bundle. Verified locally: `expo export --platform ios` for apps/e2e now bundles 746 modules to Hermes bytecode. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… SDK 56)
expo-module-scripts@56 turned `expo-module prepare` into a noop
("Run `expo-module configure` once per package manually instead"), so
the `prepare` lifecycle no longer compiled `build/`. The E2E apps
resolve `@comapeo/core-react-native` (via Metro `extraNodeModules`) to
this package's `build/index.js`; with `build/` never generated at
`npm install` time in CI, the bundle resolved the module to empty
exports, so `comapeo` / `comapeoServicesClient` came back `undefined`
at runtime and every map-server / basic spec failed (the app didn't
crash — the imports were simply undefined).
Other CI jobs were unaffected: android-tests / ios-tests install with
`--ignore-scripts` (no `prepare`, no `build/` needed — they exercise
native code), and the local release run passed only because `build/`
had been compiled by an explicit `npm run build`.
Switch `prepare` to `expo-module build`. This also fixes publishing,
which under the noop would otherwise have shipped without `build/`.
Verified: `rm -rf build && npm install` now regenerates build/index.js
and build/ComapeoCoreModule.js with the IPC client factories.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… 0.85
Two regressions introduced by the SDK 55->56 (RN 0.83->0.85) bump; both
paths were identical on main and worked there. They only surface in the
E2E release bundle (debug builds and the swift/instrumented suites don't
bundle the module's JS).
1. Metro resolution. The example/e2e apps resolved the workspace module
via `extraNodeModules: { '@comapeo/core-react-native': '../..' }`.
RN 0.85's Metro no longer honours `extraNodeModules` pointing at a
package that defines an `exports` map — it resolves to an empty module,
so every export (`comapeo`, `comapeoServicesClient`, ...) read back
`undefined` and every spec failed with "Cannot read property X of
undefined". Replace the hack with an idempotent node_modules symlink
created at metro-config load, so Metro resolves the package through the
normal node_modules path (which honours `exports`). Disabling package
exports is not an option — `@comapeo/ipc/client.js` needs its exports
map to resolve.
2. type-fest. `import { type JsonValue }` compiles (verbatimModuleSyntax)
to `import {} from "type-fest"` — a runtime import of a types-only
package with no resolvable `main`. SDK 55's Metro tolerated it; RN
0.85's stricter resolver errors. Use `import type` so tsc elides it.
Verified: apps/e2e release build + the real maestro flow on an emulator
now bundles the full module (1335 vs 743 modules) and reports
`jasmine done: passed` with zero spec failures.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
## Optic Release Automation This **draft** PR is opened by Github action [optic-release-automation-action](https://github.com/nearform-actions/optic-release-automation-action). A new **draft** GitHub release [v1.0.0-pre.2](https://github.com/digidem/comapeo-core-react-native/releases/tag/untagged-c499977757c9745e56b2) has been created. Release author: @gmaclennan #### If you want to go ahead with the release, please merge this PR. When you merge: - The GitHub release will be published - The npm package with tag pre will be published according to the publishing rules you have configured - No major or minor tags will be updated as configured #### If you close the PR - The new draft release will be deleted and nothing will change ## What's Changed * Android Testing Infrastructure & Bug Fixes by @gmaclennan in #3 * chore: prebuild example/android; harden instrumented tests by @gmaclennan in #10 * Integrate @comapeo/core via IPC over Unix sockets by @gmaclennan in #5 * chore: adjust repo setup by @achou11 in #12 * chore: minor fixes based on expo-doctor by @achou11 in #13 * Add iOS support & test infrastructure by @gmaclennan in #6 * chore: add architecture docs & plans by @gmaclennan in #11 * update some native deps used in backend by @achou11 in #14 * iOS Phase 1: unified JS bundle + smoke test (simulator-only) by @gmaclennan in #15 * iOS Phase 2: xcframework Embed & Sign for native addons by @gmaclennan in #16 * Phase 2 Android: jniLibs packaging + unified rollup loader plugin by @gmaclennan in #17 * chore: post-Phase-2 cleanup — comments, plan docs, agents.md by @gmaclennan in #33 * android: read abiFilters from reactNativeArchitectures (#30) by @gmaclennan in #35 * refactor: simplify build-backend.ts; rollup writes directly to native asset trees by @gmaclennan in #34 * chore: fix eslint configuration by @achou11 in #41 * android: audit 16 KB page alignment on every shipped .so by @gmaclennan in #43 * Add rootkey persistence and lifecycle state management by @gmaclennan in #36 * chore: move example app into apps directory by @achou11 in #18 * refactor: per-component lifecycle state with derived ComapeoState by @gmaclennan in #47 * android: fold waitForFile into connect retry loop by @gmaclennan in #52 * chore: add e2e testing app by @achou11 in #49 * fix(android): drop setUnlockedDeviceRequired from rootkey wrapper key by @gmaclennan in #57 * fix(backend): cache stopping/error frames for late joiners by @gmaclennan in #58 * fix(ios-tests): wait for STOPPING before signalling node exit by @gmaclennan in #59 * fix(android): drain JNI stdio pumps before returning from node::Start by @gmaclennan in #60 * Sentry integration: Phase 1 + Phase 2a + Phase 2b by @gmaclennan in #54 * feat(backend): polywasm-backed undici on iOS, re-enable maps plugin by @gmaclennan in #62 * ci: drop unreliable Android emulator snapshot caching by @gmaclennan in #64 * feat(sentry): land Phase 3 — backend loader + RPC tracing by @gmaclennan in #63 * fix(ios-tests): serialise STOPPING/STOPPED observers in testFullLifecycleStateTransitions by @gmaclennan in #71 * use npm list instead of custom traversal to get native module versions by @achou11 in #70 * feat(sentry): land Phases 6 + 7a — Android exit reasons & iOS MetricKit app-exit telemetry by @gmaclennan in #72 * fix(sentry): make exit telemetry lossless and stop cross-process clobbering by @gmaclennan in #84 * chore(e2e): add e2e tests on browserstack via Maestro by @achou11 in #56 * feat(sentry): migrate to @sentry/react-native v8; exit telemetry as Application Metrics by @gmaclennan in #73 * Map server integration by @gmaclennan in #86 * chore(deps): upgrade to Expo SDK 56 (React Native 0.85) by @gmaclennan in #87 * chore(ci): add release workflow by @gmaclennan in #90 * chore: fix npm script and release build script by @gmaclennan in #91 * chore(pack): don't try to package build files by @gmaclennan in #92 * fix: start fastify listening by @gmaclennan in #93 * perf(backend): switch bundler from rollup to rolldown by @gmaclennan in #94 * fix(ci): ignore-scripts in ios npm installs by @gmaclennan in #96 * fix(ci): replace --ignore-scripts with npm strict-allow-scripts allowlist by @gmaclennan in #106 * feat(config): let the consuming app supply the default project config by @gmaclennan in #95 * chore(release): merge prerelease branch. by @gmaclennan in #110 ## New Contributors * @achou11 made their first contribution in #12 **Full Changelog**: https://github.com/digidem/comapeo-core-react-native/commits/v1.0.0-pre.2 <!-- <release-meta>{"id":342868678,"version":"v1.0.0-pre.2","npmTag":"pre","opticUrl":"https://optic-zf3votdk5a-ew.a.run.app/api/generate/"}</release-meta> -->
## Optic Release Automation This **draft** PR is opened by Github action [optic-release-automation-action](https://github.com/nearform-actions/optic-release-automation-action). A new **draft** GitHub release [v1.0.0-pre.2](https://github.com/digidem/comapeo-core-react-native/releases/tag/untagged-352a6c41c12fd02dec37) has been created. Release author: @gmaclennan #### If you want to go ahead with the release, please merge this PR. When you merge: - The GitHub release will be published - The npm package with tag pre will be published according to the publishing rules you have configured - No major or minor tags will be updated as configured #### If you close the PR - The new draft release will be deleted and nothing will change <!-- Release notes generated using configuration in .github/release.yml at 7fe80b4 --> ## What's Changed ### 🚀 Features * Integrate @comapeo/core via IPC over Unix sockets by @gmaclennan in #5 * Add iOS support & test infrastructure by @gmaclennan in #6 * iOS Phase 1: unified JS bundle + smoke test (simulator-only) by @gmaclennan in #15 * iOS Phase 2: xcframework Embed & Sign for native addons by @gmaclennan in #16 * Phase 2 Android: jniLibs packaging + unified rollup loader plugin by @gmaclennan in #17 * android: read abiFilters from reactNativeArchitectures (#30) by @gmaclennan in #35 * Add rootkey persistence and lifecycle state management by @gmaclennan in #36 * Sentry integration: Phase 1 + Phase 2a + Phase 2b by @gmaclennan in #54 * feat(backend): polywasm-backed undici on iOS, re-enable maps plugin by @gmaclennan in #62 * feat(sentry): land Phase 3 — backend loader + RPC tracing by @gmaclennan in #63 * feat(sentry): land Phases 6 + 7a — Android exit reasons & iOS MetricKit app-exit telemetry by @gmaclennan in #72 * feat(sentry): migrate to @sentry/react-native v8; exit telemetry as Application Metrics by @gmaclennan in #73 * Map server integration by @gmaclennan in #86 * feat(config): let the consuming app supply the default project config by @gmaclennan in #95 ### 🐛 Bug Fixes * fix(android): drop setUnlockedDeviceRequired from rootkey wrapper key by @gmaclennan in #57 * fix(backend): cache stopping/error frames for late joiners by @gmaclennan in #58 * fix(ios-tests): wait for STOPPING before signalling node exit by @gmaclennan in #59 * fix(android): drain JNI stdio pumps before returning from node::Start by @gmaclennan in #60 * fix(ios-tests): serialise STOPPING/STOPPED observers in testFullLifecycleStateTransitions by @gmaclennan in #71 * fix(sentry): make exit telemetry lossless and stop cross-process clobbering by @gmaclennan in #84 * fix: start fastify listening by @gmaclennan in #93 * fix(ci): ignore-scripts in ios npm installs by @gmaclennan in #96 * fix(ci): replace --ignore-scripts with npm strict-allow-scripts allowlist by @gmaclennan in #106 * fix(release): stop `npm pack --dry-run` leaking dry-run into backend install by @gmaclennan in #129 ### ⚡ Performance * perf(backend): switch bundler from rollup to rolldown by @gmaclennan in #94 ### ⬆️ Dependencies * update some native deps used in backend by @achou11 in #14 * chore(deps): upgrade to Expo SDK 56 (React Native 0.85) by @gmaclennan in #87 ### 🏗️ Maintenance * Android Testing Infrastructure & Bug Fixes by @gmaclennan in #3 * chore: prebuild example/android; harden instrumented tests by @gmaclennan in #10 * chore: adjust repo setup by @achou11 in #12 * chore: minor fixes based on expo-doctor by @achou11 in #13 * chore: add architecture docs & plans by @gmaclennan in #11 * chore: post-Phase-2 cleanup — comments, plan docs, agents.md by @gmaclennan in #33 * refactor: simplify build-backend.ts; rollup writes directly to native asset trees by @gmaclennan in #34 * chore: fix eslint configuration by @achou11 in #41 * android: audit 16 KB page alignment on every shipped .so by @gmaclennan in #43 * chore: move example app into apps directory by @achou11 in #18 * refactor: per-component lifecycle state with derived ComapeoState by @gmaclennan in #47 * android: fold waitForFile into connect retry loop by @gmaclennan in #52 * chore: add e2e testing app by @achou11 in #49 * ci: drop unreliable Android emulator snapshot caching by @gmaclennan in #64 * use npm list instead of custom traversal to get native module versions by @achou11 in #70 * chore(e2e): add e2e tests on browserstack via Maestro by @achou11 in #56 * chore(ci): add release workflow by @gmaclennan in #90 * chore: fix npm script and release build script by @gmaclennan in #91 * chore(pack): don't try to package build files by @gmaclennan in #92 * chore(release): merge prerelease branch. by @gmaclennan in #110 * ci(e2e): retry BrowserStack builds on infra-class flakes by @gmaclennan in #113 ### Other Changes * ci: derive changelog labels from PR titles + add Dependabot by @gmaclennan in #114 ## New Contributors * @achou11 made their first contribution in #12 * @optic-release-automation[bot] made their first contribution in #112 **Full Changelog**: https://github.com/digidem/comapeo-core-react-native/commits/v1.0.0-pre.2 <!-- <release-meta>{"id":342970724,"version":"v1.0.0-pre.2","npmTag":"pre","opticUrl":"https://optic-zf3votdk5a-ew.a.run.app/api/generate/"}</release-meta> -->
Context
Upgrades the module and both test apps from Expo SDK 55 → 56 (React Native 0.83.6 → 0.85.3, React 19.2, min iOS 15.1 → 16.4, Hermes v1 default, Xcode 26.4).
The original ask was to "convert to SPM + precompiled xcframeworks." Research into the SDK 56 source established that there is no supported public path for a third-party npm module to drop its podspec for a hand-authored
Package.swift— Apple autolinking still requires the podspec. So this keeps the CocoaPods podspec and makes it precompile-friendly instead (see below).ios/Package.swiftremains a macOS-test-only manifest.Changes
expo ^56.0.12,expo-module-scripts 56.0.3,react-native 0.85.3,react 19.2.3; both test apps in lockstep.Package.swift.iOS(.v16),with-ios-testsplugin).source_files/exclude_fileswrapped in thetry_link_with_prebuilt_xcframeworkguard (mirroringexpo-modules-core's own podspec); deps, vendored frameworks, and resources stay unconditional.build.gradlefallbackscompileSdk/targetSdk 34 → 35,minSdk 21 → 24;sentry-android-core 8.43 → 8.44.9.15.0 → 9.18.0(podspec +Package.swift+Package.resolved) following resolved@sentry/react-native 8.15.1; enforced bycheck-sentry-cocoa-pin.mjs.expo.install.excludefor@sentry/react-native(SDK 56 tries to downgrade it to 7.x) andtypescript, in both apps.splashfrom the test apps (invalid in the SDK 56 config schema).verbatimModuleSyntax), worktree-safe git exclude path ineslint.config.js, unused test params removed.26.3 → 26.4.Verification
npm run build,npm run lint,swift test(100/100 macOS unit tests)expo-doctor21/21 in bothapps/e2eandapps/example🤖 Generated with Claude Code