Skip to content

feat(ios): Default to consuming sentry-cocoa as an xcframework#6381

Merged
sentry-release-bot[bot] merged 18 commits into
mainfrom
alwx/feature/spm-by-default
Jul 6, 2026
Merged

feat(ios): Default to consuming sentry-cocoa as an xcframework#6381
sentry-release-bot[bot] merged 18 commits into
mainfrom
alwx/feature/spm-by-default

Conversation

@alwx

@alwx alwx commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

📢 Type of change

  • Enhancement

📜 Description

Vendor sentry-cocoa as a prebuilt Sentry-Dynamic.xcframework (downloaded from the GitHub release and SHA256-verified at pod install time), instead of building Sentry from source as a CocoaPod. Sidesteps the Xcode 16/26 archive bug that hits when the same xcframework is consumed through Xcode's SPM integration ("Sentry-Dynamic.xcframework-ios.signature" couldn't be copied to "Signatures"…).

Override with:

  • SENTRY_USE_XCFRAMEWORK=0 — fall back to the source-built Sentry CocoaPod (e.g. offline builds behind a restrictive proxy).

💡 Motivation and Context

CocoaPods source builds of sentry-cocoa are slow and diverge from where the RN community is moving (prebuilt binaries). SPM was the first attempt, but Xcode 16/26 archives fail with a duplicate-signature error on any signed SPM binary xcframework. Consuming the same xcframework through CocoaPods' vendored_frameworks avoids the Xcode-SPM archive pipeline and works on the full RN version range.

💚 How did you test it?

CI: sample-application (iOS matrix, both xcframework default and cocoapods fallback), iOS Size Analysis (archive), metrics (fastlane archive).

📝 Checklist

  • I added tests to verify changes
  • No new PII added or SDK only sends newly added PII if sendDefaultPII is enabled
  • I updated the docs if needed.
  • I updated the wizard if needed.
  • All tests passing
  • No breaking changes

🔮 Next steps

@github-actions

github-actions Bot commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Semver Impact of This PR

None (no version bump detected)

📋 Changelog Preview

This is how your changes will appear in the changelog.
Entries from this PR are highlighted with a left border (blockquote style).


  • feat(ios): Default to consuming sentry-cocoa as an xcframework by alwx in #6381
  • chore(deps): bump github/codeql-action/autobuild from 4.36.2 to 4.36.3 by dependabot in #6401
  • chore(deps): bump getsentry/craft/.github/workflows/changelog-preview.yml from 2.26.13 to 2.26.14 by dependabot in #6400
  • chore(deps): bump getsentry/craft from 2.26.13 to 2.26.14 by dependabot in #6402
  • chore(deps): bump github/codeql-action/analyze from 4.36.2 to 4.36.3 by dependabot in #6403
  • docs: Warn about possible Android new architecture build failures by antonis in #6408

🤖 This preview updates automatically when you update the PR.

@github-actions

github-actions Bot commented Jun 30, 2026

Copy link
Copy Markdown
Contributor
Messages
📖 Do not forget to update Sentry-docs with your feature once the pull request gets approved.

Generated by 🚫 dangerJS against 3eed101

@alwx

alwx commented Jul 1, 2026

Copy link
Copy Markdown
Contributor Author

@cursor review

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit c8143aa. Configure here.

@alwx alwx marked this pull request as ready for review July 1, 2026 13:19
@alwx

alwx commented Jul 1, 2026

Copy link
Copy Markdown
Contributor Author

It would probably be nice to include it to the next release but no stress

@antonis antonis added the ready-to-merge Triggers the full CI test suite label Jul 1, 2026
Comment thread CHANGELOG.md Outdated
Comment thread CHANGELOG.md Outdated
@sentry

sentry Bot commented Jul 1, 2026

Copy link
Copy Markdown

📲 Install Builds

Android

🔗 App Name App ID Version Configuration
Sentry RN io.sentry.reactnative.sample 8.17.2 (97) Release

⚙️ sentry-react-native Build Distribution Settings

@github-actions

github-actions Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Android (new) Performance metrics 🚀

  Plain With Sentry Diff
Startup time 417.52 ms 449.31 ms 31.79 ms
Size 49.74 MiB 55.09 MiB 5.34 MiB

Baseline results on branch: main

Startup times

Revision Plain With Sentry Diff
0d9949d+dirty 414.88 ms 428.68 ms 13.81 ms
a736b76+dirty 405.78 ms 458.74 ms 52.96 ms
5569641+dirty 465.92 ms 532.22 ms 66.30 ms
580fb5c+dirty 515.72 ms 585.38 ms 69.66 ms
7ff4d0f+dirty 403.38 ms 427.06 ms 23.68 ms
6177334+dirty 404.80 ms 456.74 ms 51.94 ms
1e5d96d+dirty 423.33 ms 482.46 ms 59.13 ms
f170ec3+dirty 505.96 ms 551.88 ms 45.92 ms
20fbd51+dirty 594.38 ms 655.35 ms 60.97 ms
f3215d3+dirty 396.53 ms 436.66 ms 40.13 ms

App size

Revision Plain With Sentry Diff
0d9949d+dirty 43.94 MiB 48.99 MiB 5.05 MiB
a736b76+dirty 48.30 MiB 53.48 MiB 5.18 MiB
5569641+dirty 48.30 MiB 53.48 MiB 5.18 MiB
580fb5c+dirty 49.74 MiB 54.79 MiB 5.05 MiB
7ff4d0f+dirty 48.30 MiB 53.60 MiB 5.30 MiB
6177334+dirty 48.30 MiB 53.54 MiB 5.23 MiB
1e5d96d+dirty 49.74 MiB 54.81 MiB 5.07 MiB
f170ec3+dirty 48.30 MiB 53.57 MiB 5.26 MiB
20fbd51+dirty 49.74 MiB 54.81 MiB 5.07 MiB
f3215d3+dirty 48.30 MiB 53.49 MiB 5.19 MiB

@antonis antonis left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall LGTM other than the failed checks and the changelog suggestions to highlight that this might be a breaking change for some users. Maybe we can even add a warning at the top (e.g. like iOS does here).

@antonis

antonis commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Overall LGTM other than the failed checks and the changelog suggestions to highlight that this might be a breaking change for some users. Maybe we can even add a warning at the top (e.g. like iOS does here).

We can probably also add a link to the new doc that is part of #6174

@alwx alwx requested a review from antonis July 1, 2026 15:13
@github-actions

github-actions Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Android (legacy) Performance metrics 🚀

  Plain With Sentry Diff
Startup time 431.16 ms 444.02 ms 12.86 ms
Size 49.74 MiB 55.09 MiB 5.34 MiB

Baseline results on branch: main

Startup times

Revision Plain With Sentry Diff
0d9949d+dirty 403.57 ms 437.00 ms 33.43 ms
64630e5+dirty 419.18 ms 464.58 ms 45.40 ms
853723c+dirty 405.54 ms 440.08 ms 34.54 ms
1122a96+dirty 422.22 ms 464.33 ms 42.10 ms
5748023+dirty 446.69 ms 505.63 ms 58.94 ms
eb93136+dirty 416.18 ms 467.32 ms 51.14 ms
4e0ba9c+dirty 452.84 ms 473.36 ms 20.52 ms
c2e182c+dirty 471.64 ms 553.59 ms 81.95 ms
a0d8cf8+dirty 411.71 ms 467.57 ms 55.87 ms
d0e3b3e+dirty 421.53 ms 498.19 ms 76.66 ms

App size

Revision Plain With Sentry Diff
0d9949d+dirty 43.75 MiB 48.13 MiB 4.37 MiB
64630e5+dirty 49.74 MiB 54.82 MiB 5.07 MiB
853723c+dirty 48.30 MiB 53.58 MiB 5.28 MiB
1122a96+dirty 48.30 MiB 53.54 MiB 5.24 MiB
5748023+dirty 48.30 MiB 53.54 MiB 5.23 MiB
eb93136+dirty 48.30 MiB 53.58 MiB 5.28 MiB
4e0ba9c+dirty 48.30 MiB 53.49 MiB 5.19 MiB
c2e182c+dirty 49.74 MiB 54.85 MiB 5.11 MiB
a0d8cf8+dirty 48.30 MiB 53.49 MiB 5.19 MiB
d0e3b3e+dirty 49.74 MiB 55.09 MiB 5.34 MiB

Previous results on branch: alwx/feature/spm-by-default

Startup times

Revision Plain With Sentry Diff
feed452+dirty 448.30 ms 523.68 ms 75.38 ms

App size

Revision Plain With Sentry Diff
feed452+dirty 49.74 MiB 55.09 MiB 5.34 MiB

@antonis antonis left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since the dynamic approach didn't resolve the CI build issue and this partially a breaking change for the users I suggest to try the following:

  • Keep SPM opt-in till the React Native framework supports it
  • Have RNSentry.podspec consume sentry-cocoa as a vendored_frameworks xcframework downloaded from sentry-cocoa's GitHub releases, instead of either s.dependency 'Sentry' (CocoaPods trunk) or SPM.dependency (spm.rb bridge).
    Wdyt?

Comment thread packages/core/scripts/sentry_utils.rb
@alwx alwx changed the title feat(ios): Default to consuming sentry-cocoa via SPM feat(ios): Default to consuming sentry-cocoa as an xcframework Jul 2, 2026
Comment thread packages/core/RNSentry.podspec
Comment thread packages/core/scripts/sentry_utils.rb Outdated
Comment thread packages/core/scripts/sentry_utils.rb Outdated
Comment thread packages/core/scripts/sentry_utils.rb
Comment thread packages/core/scripts/sentry_utils.rb
Comment thread packages/core/RNSentry.podspec Outdated
Comment thread packages/core/RNSentry.podspec Outdated
Comment thread packages/core/ios/RNSentrySwiftLinkStub.swift
@github-actions

github-actions Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

iOS (legacy) Performance metrics 🚀

  Plain With Sentry Diff
Startup time 3854.07 ms 1224.33 ms -2629.74 ms
Size 4.98 MiB 6.46 MiB 1.49 MiB

Baseline results on branch: main

Startup times

Revision Plain With Sentry Diff
57e0069+dirty 3842.29 ms 1212.12 ms -2630.17 ms
0bd8916+dirty 3842.33 ms 1230.76 ms -2611.58 ms
774257e+dirty 3846.90 ms 1215.02 ms -2631.88 ms
acd838e+dirty 3849.78 ms 1230.00 ms -2619.78 ms
038a6d7+dirty 3849.69 ms 1228.40 ms -2621.28 ms
df5d108+dirty 1225.90 ms 1220.14 ms -5.76 ms
2c735cc+dirty 1229.67 ms 1221.50 ms -8.17 ms
5a010b7+dirty 3838.85 ms 1214.98 ms -2623.87 ms
f170ec3+dirty 3822.26 ms 1218.33 ms -2603.93 ms
4953e94+dirty 1212.06 ms 1214.83 ms 2.77 ms

App size

Revision Plain With Sentry Diff
57e0069+dirty 4.98 MiB 6.50 MiB 1.52 MiB
0bd8916+dirty 5.15 MiB 6.69 MiB 1.53 MiB
774257e+dirty 5.15 MiB 6.70 MiB 1.54 MiB
acd838e+dirty 5.15 MiB 6.70 MiB 1.55 MiB
038a6d7+dirty 5.15 MiB 6.70 MiB 1.55 MiB
df5d108+dirty 3.38 MiB 4.73 MiB 1.35 MiB
2c735cc+dirty 3.38 MiB 4.74 MiB 1.35 MiB
5a010b7+dirty 5.15 MiB 6.69 MiB 1.54 MiB
f170ec3+dirty 5.15 MiB 6.69 MiB 1.53 MiB
4953e94+dirty 3.38 MiB 4.73 MiB 1.35 MiB

Previous results on branch: alwx/feature/spm-by-default

Startup times

Revision Plain With Sentry Diff
feed452+dirty 3852.78 ms 1227.60 ms -2625.18 ms

App size

Revision Plain With Sentry Diff
feed452+dirty 4.98 MiB 6.46 MiB 1.49 MiB

@github-actions

github-actions Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

iOS (new) Performance metrics 🚀

  Plain With Sentry Diff
Startup time 3833.29 ms 1222.52 ms -2610.77 ms
Size 4.98 MiB 6.46 MiB 1.49 MiB

Baseline results on branch: main

Startup times

Revision Plain With Sentry Diff
57e0069+dirty 3842.23 ms 1210.00 ms -2632.23 ms
41d6254+dirty 3849.78 ms 1233.91 ms -2615.86 ms
7d8c8bd+dirty 3847.98 ms 1230.77 ms -2617.21 ms
c823bb5+dirty 3845.16 ms 1210.33 ms -2634.83 ms
bc0d8cf+dirty 3834.64 ms 1223.91 ms -2610.73 ms
1e5d96d+dirty 3845.93 ms 1222.51 ms -2623.42 ms
7d6fd3a+dirty 1210.89 ms 1217.63 ms 6.74 ms
7436d0f+dirty 3861.51 ms 1231.07 ms -2630.44 ms
4953e94+dirty 1217.41 ms 1223.53 ms 6.12 ms
6acdf1d+dirty 3835.35 ms 1218.30 ms -2617.06 ms

App size

Revision Plain With Sentry Diff
57e0069+dirty 4.98 MiB 6.50 MiB 1.52 MiB
41d6254+dirty 5.15 MiB 6.70 MiB 1.54 MiB
7d8c8bd+dirty 5.15 MiB 6.68 MiB 1.53 MiB
c823bb5+dirty 5.15 MiB 6.69 MiB 1.53 MiB
bc0d8cf+dirty 5.15 MiB 6.67 MiB 1.51 MiB
1e5d96d+dirty 4.98 MiB 6.46 MiB 1.49 MiB
7d6fd3a+dirty 3.38 MiB 4.77 MiB 1.39 MiB
7436d0f+dirty 5.15 MiB 6.70 MiB 1.54 MiB
4953e94+dirty 3.38 MiB 4.73 MiB 1.35 MiB
6acdf1d+dirty 4.98 MiB 6.51 MiB 1.53 MiB

Previous results on branch: alwx/feature/spm-by-default

Startup times

Revision Plain With Sentry Diff
feed452+dirty 3856.69 ms 1226.78 ms -2629.91 ms

App size

Revision Plain With Sentry Diff
feed452+dirty 4.98 MiB 6.46 MiB 1.49 MiB

alwx and others added 15 commits July 6, 2026 16:01
…lision

The binary SPM products (`Sentry`, `Sentry-Dynamic`, ...) ship signed
xcframeworks whose `Signatures/*.signature` file collides during
`xcodebuild archive` on Xcode 16/26. Switching to the `SentrySPM`
source-compile product (backed by the `SentryObjCInternal` SPM target)
avoids the xcframework path entirely — SPM compiles sentry-cocoa from
source, so there is no `Signatures/` directory to duplicate.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…ture collision"

`SentrySPM` doesn't expose the `Sentry` module the way the binary
xcframework product does — RNSentry.mm fails to resolve
`#import <Sentry/SentryDefines.h>`, breaking every iOS build.

Back to `Sentry-Dynamic` (archive-only failure) while we pick a real fix.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Consuming sentry-cocoa through Xcode's SPM integration triggers a
signature-copy collision during `xcodebuild archive` on Xcode 16/26:

  xcodebuild: error: "Sentry-Dynamic.xcframework-ios.signature" couldn't
  be copied to "Signatures" because an item with the same name already
  exists.: File exists

The collision is specific to Xcode's SPM archive pipeline. Consuming
the same prebuilt xcframework through CocoaPods' `vendored_frameworks`
avoids that pipeline entirely — the archive step goes through the
regular CocoaPods embed path, which does not produce the duplicate
signature copy.

RNSentry.podspec now downloads `Sentry-Dynamic.xcframework.zip` from
sentry-cocoa's GitHub release on first `pod install`, verifies the
SHA256 checksum against a version-pinned table in `sentry_utils.rb`,
and vendors the extracted xcframework via `s.vendored_frameworks`.
Subsequent `pod install` runs reuse the cached copy under
`packages/core/ios/Vendor/`.

Set `SENTRY_USE_XCFRAMEWORK=0` to fall back to the source-built
`Sentry` CocoaPod (e.g. for offline builds behind a restrictive proxy).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…odule

Sentry-Dynamic.xcframework contains a framework named `Sentry.framework`
inside, so `@import Sentry;` needs `-framework Sentry`. CocoaPods
derives the `-framework` flag from the xcframework's own filename, so
with `Sentry-Dynamic.xcframework` it generates `-framework Sentry-Dynamic`
and RNSentry fails to compile with `Module 'Sentry' not found`.

Switch to `Sentry.xcframework` (the static product) — enclosing name
matches the framework name inside, so CocoaPods generates the correct
`-framework Sentry` and the module resolves. Static also means no embed
step, so no chance of the archive-signature collision either.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Sentinel-check `Sentry.xcframework/Info.plist` instead of directory
  existence so an interrupted `unzip` doesn't leave a partial tree that
  short-circuits future re-downloads (cursor-bot low).
- `rm_rf(target_dir)` before extracting so a stale partial tree from an
  earlier failure doesn't survive the next attempt.
- Verify `Info.plist` after extraction so a release with a changed
  archive layout fails fast with a clear message instead of silently
  succeeding and later confusing `pod install` (sentry-bot medium).
- Honor `SENTRY_USE_SPM=0` as a deprecated alias for the CocoaPods
  fallback so CI/local envs still exporting the old draft variable
  don't silently opt into the new xcframework path (cursor-bot medium).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…ramework

Even with `s.vendored_frameworks = 'ios/Vendor/Sentry.xcframework'`,
CocoaPods didn't propagate a framework search path into RNSentry's own
compile phase, so `#import <Sentry/SentryDefines.h>` failed with
"file not found". Set `FRAMEWORK_SEARCH_PATHS` explicitly via
`pod_target_xcconfig` so the pod can resolve the `Sentry` framework
module from the vendored xcframework's parent directory.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
`s.pod_target_xcconfig` is setter-only in the CocoaPods version used by
RN 0.86, so calling `s.pod_target_xcconfig.merge!(…)` crashed pod install
with `undefined method 'pod_target_xcconfig' for Pod::Specification`.

Accumulate the settings into a local hash across the conditional branches
and assign to `s.pod_target_xcconfig` once at the end. Same fix applied
to the pre-existing new-arch/RN<0.71 branch (which had the same latent
bug).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Assigning `s.pod_target_xcconfig` at the end of the podspec (after
`install_modules_dependencies`) clobbered every setting RN's helper had
written, so the RN-provided HEADER_SEARCH_PATHS were dropped and every
`#import <Sentry/…>` (as well as any other framework header lookup) failed
during RNSentry's compile phase.

Assign the base `pod_target_xcconfig` (with DEFINES_MODULE and the
Sentry FRAMEWORK_SEARCH_PATHS) BEFORE `install_modules_dependencies` so
it merges its RN settings on top rather than the other way around. For
the RN < 0.71 branch — where `install_modules_dependencies` doesn't
exist — the local hash is mutated after that assignment, so re-assign
inside that branch.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…H_PATHS

Confirmed by local repro: Xcode's `-F <dir>` does NOT descend into an
`.xcframework` bundle at search-path lookup time. Given
`FRAMEWORK_SEARCH_PATHS = ".../ios/Vendor"`, Xcode only sees
`Sentry.xcframework` as an opaque directory and never finds
`Sentry.framework` inside — so `#import <Sentry/SentryDefines.h>`
fails with `Module 'Sentry' not found`.

Instead of a single parent-of-xcframework path, enumerate every slice
directory inside the extracted xcframework (via `Dir.children` — no plist
gem needed) and register each as a framework search path. Xcode then
picks the matching slice based on the target platform/arch. The list is
computed at pod-install time, so future sentry-cocoa releases can add
new slices without a code change.

Apply the same paths to `s.user_target_xcconfig` so the host app target
(any user code writing `#import <Sentry/…>` directly) also resolves the
module.

Verified locally: RNSentry pod and the sample app both compile — only
the RN bundle script (unrelated to Sentry) blocks the local build.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Two problems with the previous flat-slice-list approach:

1. Xcode's Swift module precompiler walked slices that don't match the
   current build target (e.g. watchos-* on an iOS build) and errored
   with 'unsupported Swift architecture'. Fix: split slices by target
   SDK and emit conditional FRAMEWORK_SEARCH_PATHS[sdk=...*] entries
   so each SDK build only sees the slices it can actually consume.

2. PODS_TARGET_SRCROOT is defined in a pod's own xcconfig but not in
   the aggregate/user-target xcconfig. Using it in user_target_xcconfig
   made the app-target search paths resolve to nothing, so app code
   writing @import Sentry failed with 'Module Sentry not found'. Use
   PODS_ROOT/../.. for the user-target xcconfig - from the app's Pods
   dir that's the RN app root where node_modules/@sentry/react-native/
   lives.

Slice-to-SDK mapping is computed at pod-install time from the extracted
xcframework so future sentry-cocoa releases pick up new slices
automatically.

Verified locally: sample's SentryNativeInitializer.m now resolves
@import Sentry.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Two follow-up fixes for the vendored xcframework path:

1. RNSentryCocoaTester (in packages/core/RNSentryCocoaTester/) had its
   test target fail with 'Sentry/Sentry.h' file not found because its
   Podfile layout is different from the RN sample apps — the previous
   ${PODS_ROOT}/../.. path assumed a RN app root with node_modules,
   which doesn't apply here. Switch user_target_xcconfig to the
   absolute path known at pod-install time (via File.expand_path on
   the podspec dir). Absolute paths are baked into Pods xcconfigs on
   every install, so shareability across machines isn't a concern —
   Pods/ is regenerated per install anyway. This also removes the need
   for a separate 'pod_target' vs 'user_target' path.

2. Build RN 0.86.0 legacy hermes ios production dynamic (use_frameworks!
   :linkage => :dynamic mode) failed with:
     Undefined symbols: __swift_FORCE_LOAD_$_swiftCompatibility56
   Sentry.xcframework contains Swift code, but RNSentry.podspec's
   source_files was Objective-C++ only, so Xcode never auto-linked
   the Swift runtime compatibility libraries required by the static
   Swift symbols embedded in Sentry.xcframework. Add an empty
   RNSentrySwiftLinkStub.swift and include `.swift` in source_files
   glob so Xcode treats RNSentry as Swift-consuming and pulls in the
   compat libs.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Adding a Swift file to RNSentry.podspec's source_files (to force Xcode
to link Swift runtime compat libs when consuming Sentry.xcframework)
made CocoaPods treat RNSentry as a 'Swift pod'. On RN < 0.75,
React-hermes doesn't define modular headers, so pod install fails:
  The Swift pod `RNSentry` depends upon `React-hermes`, which does
  not define modules.

The Swift compat lib linkage is only needed when linking
Sentry.xcframework's static Swift symbols into a dynamic framework
(use_frameworks! :dynamic), which is a RN 0.86+ scenario anyway. Gate
the .swift file on RN >= 0.75 to preserve pod install on the older
matrix cells.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Move the SPM/xcframework entry out of the already-released `## 8.17.0`
  section into a new `## Unreleased` section (danger check). The merge
  from main pulled 8.17.0's release notes on top and swept the entry
  inside them.

- Add a private constant to RNSentrySwiftLinkStub.swift. A pure-comment
  Swift file compiles to nothing, which would defeat the whole reason
  for the stub (forcing Xcode to link Swift runtime compatibility libs
  when consuming Sentry.xcframework's static Swift symbols).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- sentry_utils.rb: replace system('curl',…) with URI.open from stdlib
  open-uri. Same net behavior, no shell escaping to worry about, pure Ruby.

- sentry_utils.rb + RNSentry.podspec: drop the runtime slice-enumeration
  helpers. Sentry.xcframework's layout has been stable across releases,
  so hardcode the slice → SDK map into a frozen constant
  (SENTRY_XCFRAMEWORK_SLICES_BY_SDK) and iterate it directly in the
  podspec. Less code, no filesystem scan on every pod install. If
  sentry-cocoa ever ships a new platform slice, add a line to the
  constant.

- scripts/update-cocoa.sh: extend set-version to also refresh the
  Sentry.xcframework.zip SHA256 checksum in sentry_utils.rb. Before
  this, bumping sentry-cocoa required editing the checksum by hand — a
  silent recipe for typos that would break every user's pod install
  with a checksum-mismatch error. Now the script downloads the new
  archive, computes SHA256, and rewrites both the version key and the
  Sentry value in place with a sanity-check.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Repro on a bare RN app installed via `pnpm install
--config.node-linker=isolated` (pnpm's strict store makes package
directories read-only): pod install failed with

    Permission denied @ dir_s_mkdir - .../node_modules/.pnpm/
    @sentry+react-native.../ios/Vendor

Under pnpm's isolated store (and Yarn PnP), the SDK package directory
is either a read-only symlink into a shared store or not materialized
on disk at all — writing our xcframework cache there is not portable.
Move the cache to `~/Library/Caches/sentry-react-native/xcframeworks/
<version>/` (macOS user cache, always writable, deduped across
projects on the same machine). Override with `SENTRY_XCFRAMEWORK_CACHE_DIR`
for CI or enterprise setups.

Also drop `s.vendored_frameworks = 'ios/Vendor/Sentry.xcframework'`.
It was decorative — CocoaPods doesn't stage vendored xcframeworks for
`path:` (development) pods, which is why we already had to wire
FRAMEWORK_SEARCH_PATHS manually. Linking still happens: clang's
`-fmodules-autolink` (default) emits the `-framework Sentry`
directive as soon as `@import Sentry;` in RNSentry.mm resolves the
module through the search paths. With the vendored_frameworks entry
gone, the podspec no longer points at a path that only existed inside
node_modules.

Verified locally against a bare RN 0.86 sample installed via pnpm
strict + chmod a-w on the package's ios/ directory: pod install
succeeds, build succeeds, app boots, native crash → dSYM upload path
still works.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@alwx alwx force-pushed the alwx/feature/spm-by-default branch from aae21ec to 3eed101 Compare July 6, 2026 14:04

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 3eed101. Configure here.

# `Info.plist` most likely came from an interrupted `unzip` and would
# otherwise silently short-circuit re-download here.
target_manifest = File.join(target_dir, 'Info.plist')
return target_dir if File.file?(target_manifest)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cached xcframework skips checksum

Medium Severity

When Info.plist already exists under the versioned cache directory, ensure_sentry_xcframework returns immediately and never re-checks the zip SHA256 from SENTRY_COCOA_XCFRAMEWORK_CHECKSUMS. Upgrading @sentry/react-native after a checksum fix for the same sentry-cocoa version can leave a stale or tampered binary in use.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 3eed101. Configure here.

@sentry-release-bot sentry-release-bot Bot merged commit 3eed101 into main Jul 6, 2026
82 of 96 checks passed
@sentry-release-bot sentry-release-bot Bot deleted the alwx/feature/spm-by-default branch July 6, 2026 14:26
@alwx alwx restored the alwx/feature/spm-by-default branch July 6, 2026 14:35
alwx added a commit that referenced this pull request Jul 7, 2026
pod install now downloads Sentry.xcframework.zip from sentry-cocoa's
GitHub release (SHA256-verified) and caches it under
~/Library/Caches/sentry-react-native/xcframeworks/<version>/, instead of
building Sentry from source as a CocoaPod. Sentry symbols are then
statically linked into the app binary (no framework embed, no dylib
dep) via `FRAMEWORK_SEARCH_PATHS[sdk=…*]` + clang's -fmodules-autolink.

Motivation:
 - CocoaPods trunk is winding down; we needed a path off it that also
   sidesteps the Xcode 16/26 archive bug that hits any signed SPM
   binary xcframework (`Signatures/*.signature` collision).
 - Consuming via CocoaPods' `vendored_frameworks` pipeline goes
   through a different code path and is unaffected.

Fallback: set `SENTRY_USE_XCFRAMEWORK=0` before pod install to restore
the source-built `Sentry` CocoaPod (for offline builds behind a
restrictive proxy, or projects with another pod that transitively
depends on the Sentry CocoaPod).

Cache location is user-writable (not inside node_modules), which
means pnpm's isolated store and Yarn PnP work without changes.
Override the cache root with `SENTRY_XCFRAMEWORK_CACHE_DIR`.

Verified end-to-end against alpha.3 on:
 - Real device signed archive (Apple accepts, codesign strict-verify passes)
 - Native crash → dSYM upload → Sentry frames symbolicated
 - RN 0.71 archive (via SKIP_BUNDLING) with 21k Sentry symbols in dSYM
 - EAS Build with npm, pnpm-isolated, and `SENTRY_USE_XCFRAMEWORK=0`
 - Second EAS build after version bump (no stale-cache pollution)

Reapplies the content of PR #6381 (merged prematurely as part of the
alpha.3 release, then rolled back via #6412) with the pnpm cache-location
fix baked in from the start this time.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
alwx added a commit that referenced this pull request Jul 7, 2026
…6413)

pod install now downloads Sentry.xcframework.zip from sentry-cocoa's
GitHub release (SHA256-verified) and caches it under
~/Library/Caches/sentry-react-native/xcframeworks/<version>/, instead of
building Sentry from source as a CocoaPod. Sentry symbols are then
statically linked into the app binary (no framework embed, no dylib
dep) via `FRAMEWORK_SEARCH_PATHS[sdk=…*]` + clang's -fmodules-autolink.

Motivation:
 - CocoaPods trunk is winding down; we needed a path off it that also
   sidesteps the Xcode 16/26 archive bug that hits any signed SPM
   binary xcframework (`Signatures/*.signature` collision).
 - Consuming via CocoaPods' `vendored_frameworks` pipeline goes
   through a different code path and is unaffected.

Fallback: set `SENTRY_USE_XCFRAMEWORK=0` before pod install to restore
the source-built `Sentry` CocoaPod (for offline builds behind a
restrictive proxy, or projects with another pod that transitively
depends on the Sentry CocoaPod).

Cache location is user-writable (not inside node_modules), which
means pnpm's isolated store and Yarn PnP work without changes.
Override the cache root with `SENTRY_XCFRAMEWORK_CACHE_DIR`.

Verified end-to-end against alpha.3 on:
 - Real device signed archive (Apple accepts, codesign strict-verify passes)
 - Native crash → dSYM upload → Sentry frames symbolicated
 - RN 0.71 archive (via SKIP_BUNDLING) with 21k Sentry symbols in dSYM
 - EAS Build with npm, pnpm-isolated, and `SENTRY_USE_XCFRAMEWORK=0`
 - Second EAS build after version bump (no stale-cache pollution)

Reapplies the content of PR #6381 (merged prematurely as part of the
alpha.3 release, then rolled back via #6412) with the pnpm cache-location
fix baked in from the start this time.

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready-to-merge Triggers the full CI test suite

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants