Skip to content

fix(ios): make the RNSentry SPEC CHECKSUM in Podfile.lock machine-independent - #6534

Open
alwx wants to merge 3 commits into
mainfrom
alwx/bugfix/6467
Open

fix(ios): make the RNSentry SPEC CHECKSUM in Podfile.lock machine-independent#6534
alwx wants to merge 3 commits into
mainfrom
alwx/bugfix/6467

Conversation

@alwx

@alwx alwx commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

📢 Type of change

  • Bugfix
  • New feature
  • Enhancement
  • Refactoring

📜 Description

Since #6413, RNSentry.podspec points FRAMEWORK_SEARCH_PATHS at the absolute pod-install-time path of the cached Sentry.xcframework (~/Library/Caches/sentry-react-native/xcframeworks/…), which leaks $HOME into the RNSentry SPEC CHECKSUM written to Podfile.lock.

This stages the cached bundle behind a machine-independent reference instead:

  • stage_sentry_xcframework_in_pods (new, sentry_utils.rb) symlinks Pods/sentry-xcframeworks/<sentry-cocoa version>/Sentry.xcframework → the cached bundle, recreating the link when it's missing or stale (e.g. SENTRY_XCFRAMEWORK_CACHE_DIR changed between installs) and pruning links left behind by earlier SDK versions.
  • The podspec now writes "$(PODS_ROOT)/sentry-xcframeworks/<version>/Sentry.xcframework/<slice>" into FRAMEWORK_SEARCH_PATHS — the same string on every machine, so the checksum is deterministic. $(PODS_ROOT) is defined in both per-pod and user/aggregate xcconfigs (unlike $(PODS_TARGET_SRCROOT)), and because the link lives inside Pods/ there is no Podfile-layout detection needed.
  • Staging only happens inside a real pod install (gated on Pod::Config.instance.podfile_path). Anywhere else — pod ipc spec, pod lib lint, a plain Specification.from_file$(PODS_ROOT) would point at an unrelated sandbox, so we fall back to the absolute cache path. Same fallback if the symlink can't be created: functional, just with a machine-specific checksum.

The download/cache/SHA256-verification flow is unchanged; the cache stays in ~/Library/Caches (still shared across projects, still safe under pnpm's read-only store and Yarn PnP).

Note: existing projects will see a one-time RNSentry checksum change in Podfile.lock on their next pod install; after that the value is stable across developers and CI. Teams that adopted the SENTRY_XCFRAMEWORK_CACHE_DIR=/tmp/… workaround from #6467 can drop it — and mixed setups (some machines with the override, some without) now converge on the same checksum, since the override no longer appears in the spec.

💡 Motivation and Context

Fixes #6467.

CocoaPods persists external-source pods as an evaluated podspec JSON in Pods/Local Podspecs/RNSentry.podspec.json (ExternalSources::AbstractExternalSource#store_podspec always calls sandbox.store_podspec(name, spec, true, true)), and Specification#checksum is the SHA1 of that file. The evaluated pod_target_xcconfig/user_target_xcconfig therefore carried the $HOME-dependent path straight into Podfile.lock.

Consequence: two developers (or a developer and CI) installing the exact same @sentry/react-native version get different RNSentry checksums, so a committed Podfile.lock flips on every pod install and teams gating CI on a clean lockfile get repeated failures. Same class of problem as react/react-native#31193.

Supersedes #6474, with two fixes on top of it:

  1. That PR fell back to <cwd>/Pods when Pod::Config was unavailable and still returned a $(PODS_ROOT) path. CocoaPods evaluates podspecs with the CWD set to the podspec's own directory, so that would have staged the link inside node_modules/@sentry/react-native/ while handing back a search path that dangles at build time — a hard module 'Sentry' not found instead of the safe absolute-path fallback.
  2. Version-scoped staging directories from previous SDK versions were never cleaned up, accumulating dangling symlinks in Pods/.

💚 How did you test it?

All on macOS with CocoaPods 1.16.2 / Xcode 26.1.

Checksum determinism — reproduced CocoaPods' exact computation (Digest::SHA1.hexdigest(spec.to_pretty_json)) while evaluating the podspec under two different $HOME values:

  • origin/main: 842e4309… vs 8b743fb4… — bug reproduced.
  • This branch: 43ccbce8… both times, and the two evaluated specs are byte-identical.
  • Pods/Local Podspecs/RNSentry.podspec.json after a real install contains zero /Users/… strings (down from the leaking path).
  • SENTRY_XCFRAMEWORK_CACHE_DIR=/tmp/sentry-xcf-alt pod install yields the same checksum as without the override, and re-points the stale symlink.

Real pod install in samples/react-native/ios and packages/core/RNSentryCocoaTester (different Podfile depths): $(PODS_ROOT) resolves correctly in both the per-pod xcconfig (PODS_ROOT = ${SRCROOT}) and the aggregate/user xcconfig (PODS_ROOT = ${SRCROOT}/Pods). Repeated installs keep the checksum stable and the symlink survives — Installer::SandboxDirCleaner only removes .xcodeproj children, target-support and header directories, so the staging dir is untouched.

Builds:

  • xcodebuild -scheme RNSentry -sdk iphonesimulatorBUILD SUCCEEDED (@import Sentry resolves through the symlink).
  • Full sample app xcodebuild -workspace sentryreactnativesample.xcworkspaceBUILD SUCCEEDED; nm on the resulting debug dylib shows 168 Sentry symbols. No Sentry CocoaPod exists in Podfile.lock, so linking necessarily went through the staged path. -showBuildSettings confirms FRAMEWORK_SEARCH_PATHS expands to …/ios/Pods/sentry-xcframeworks/9.19.1/Sentry.xcframework/ios-arm64_x86_64-simulator.

Edge cases: SENTRY_USE_XCFRAMEWORK=0 stages nothing and keeps the Sentry pod dependency; stale/wrong symlinks and leftover version directories are recreated/pruned; rm_rf unlinks the symlink without following it (shared cache verified intact afterwards); evaluation without a Podfile falls back to the absolute path and creates no stray directories. ruby -c passes on both files.

📝 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.
  • Public API changes reviewed by another Mobile SDK team member or implemented according to the develop docs spec.
  • No breaking changes.

Note on tests: the repo has no Ruby test infrastructure, so this is covered by the manual verification above plus the pod install jobs in sample-application.yml / native-tests.yml, which exercise the new staging path end-to-end.

🔮 Next steps

Add the ready-to-merge label to run the native/E2E/sample-build jobs before merging — those are the ones that exercise pod install across RN versions and the use_frameworks! variants.

…ependent

CocoaPods stores external-source pods as an evaluated podspec JSON in
Pods/Local Podspecs/ and derives the pod's SPEC CHECKSUM from that file, so
the absolute ~/Library/Caches/... path we wrote into FRAMEWORK_SEARCH_PATHS
leaked $HOME into Podfile.lock and made the RNSentry checksum differ per
machine.

Stage the cached Sentry.xcframework behind a symlink at
Pods/sentry-xcframeworks/<version>/Sentry.xcframework and reference it as
$(PODS_ROOT)/... instead. $(PODS_ROOT) is defined in both the per-pod and the
user/aggregate xcconfigs and the link lives inside Pods/, so no Podfile-layout
detection is needed and the string is identical on every machine — including
machines overriding SENTRY_XCFRAMEWORK_CACHE_DIR.

Fixes #6467
@github-actions

github-actions Bot commented Jul 28, 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).


  • fix(ios): make the RNSentry SPEC CHECKSUM in Podfile.lock machine-independent by alwx in #6534

🤖 This preview updates automatically when you update the PR.

@github-actions

github-actions Bot commented Jul 28, 2026

Copy link
Copy Markdown
Contributor
Fails
🚫 Please consider adding a changelog entry for the next release.

Instructions and example for changelog

Please add an entry to CHANGELOG.md to the "Unreleased" section. Make sure the entry includes this PR's number.

Example:

## Unreleased

### Fixes

- make the RNSentry SPEC CHECKSUM in Podfile.lock machine-independent ([#6534](https://github.com/getsentry/sentry-react-native/pull/6534))

If none of the above apply, you can opt out of this check by adding #skip-changelog to the PR description or adding a skip-changelog label.

Generated by 🚫 dangerJS against 6d1638b

@alwx
alwx marked this pull request as ready for review July 30, 2026 09:07
@antonis antonis added the ready-to-merge Triggers the full CI test suite label Jul 30, 2026
Comment thread CHANGELOG.md

### Fixes

- Make the `RNSentry` SPEC CHECKSUM in `Podfile.lock` machine-independent ([#6474](https://github.com/getsentry/sentry-react-native/pull/6474))

@antonis antonis Jul 30, 2026

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.

Q: Is this an internal only change or it has user facing area?

If not the later we can remove the changelog or move it in an internal section. Let's also move it to the unreleased section and revert the - Session Replay network details item move.

if it is user facing maybe we can use a Changes section

@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.

LGTM once the CI is green and the changelog fixed 🙇

@sentry

sentry Bot commented Jul 30, 2026

Copy link
Copy Markdown

📲 Install Builds

Android

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

⚙️ sentry-react-native Build Distribution Settings

@github-actions

Copy link
Copy Markdown
Contributor

Android (legacy) Performance metrics 🚀

  Plain With Sentry Diff
Startup time 414.35 ms 454.62 ms 40.27 ms
Size 49.74 MiB 55.38 MiB 5.63 MiB

Baseline results on branch: main

Startup times

Revision Plain With Sentry Diff
1d3572b+dirty 435.35 ms 487.32 ms 51.96 ms
d2eadf8+dirty 414.64 ms 454.56 ms 39.92 ms
7d8c8bd+dirty 417.45 ms 462.10 ms 44.65 ms
bf168a4+dirty 418.21 ms 489.74 ms 71.53 ms
890d145+dirty 504.54 ms 491.55 ms -12.99 ms
ad66da3+dirty 468.46 ms 533.56 ms 65.10 ms
15d4514+dirty 406.77 ms 428.06 ms 21.29 ms
a0a3177+dirty 441.27 ms 499.86 ms 58.59 ms
6acdf1d+dirty 513.58 ms 608.31 ms 94.72 ms
038a6d7+dirty 524.82 ms 531.92 ms 7.10 ms

App size

Revision Plain With Sentry Diff
1d3572b+dirty 49.74 MiB 55.38 MiB 5.63 MiB
d2eadf8+dirty 48.30 MiB 53.48 MiB 5.18 MiB
7d8c8bd+dirty 48.30 MiB 53.54 MiB 5.23 MiB
bf168a4+dirty 49.74 MiB 55.09 MiB 5.35 MiB
890d145+dirty 43.75 MiB 48.14 MiB 4.39 MiB
ad66da3+dirty 48.30 MiB 53.49 MiB 5.19 MiB
15d4514+dirty 48.30 MiB 53.60 MiB 5.30 MiB
a0a3177+dirty 49.74 MiB 55.37 MiB 5.63 MiB
6acdf1d+dirty 49.74 MiB 55.09 MiB 5.34 MiB
038a6d7+dirty 48.30 MiB 53.60 MiB 5.30 MiB

@github-actions

Copy link
Copy Markdown
Contributor

iOS (new) Performance metrics 🚀

  Plain With Sentry Diff
Startup time 3845.83 ms 1221.88 ms -2623.95 ms
Size 4.98 MiB 6.56 MiB 1.58 MiB

Baseline results on branch: main

Startup times

Revision Plain With Sentry Diff
2cac31b+dirty 3854.43 ms 1212.35 ms -2642.08 ms
244f6e8+dirty 3825.51 ms 1217.76 ms -2607.75 ms
9474ead+dirty 3823.33 ms 1208.31 ms -2615.03 ms
44c8b3f+dirty 3849.24 ms 1209.94 ms -2639.31 ms
61cc206+dirty 3822.60 ms 1206.17 ms -2616.43 ms
acd838e+dirty 3835.94 ms 1215.87 ms -2620.07 ms
b0d3373+dirty 3842.49 ms 1218.49 ms -2624.00 ms
fa21fca+dirty 3845.12 ms 1215.89 ms -2629.24 ms
0d9949d+dirty 1203.94 ms 1202.27 ms -1.67 ms
a5d243c+dirty 3827.92 ms 1220.10 ms -2607.81 ms

App size

Revision Plain With Sentry Diff
2cac31b+dirty 4.98 MiB 6.55 MiB 1.58 MiB
244f6e8+dirty 4.98 MiB 6.56 MiB 1.58 MiB
9474ead+dirty 5.15 MiB 6.71 MiB 1.55 MiB
44c8b3f+dirty 5.15 MiB 6.66 MiB 1.51 MiB
61cc206+dirty 4.98 MiB 6.55 MiB 1.57 MiB
acd838e+dirty 5.15 MiB 6.70 MiB 1.55 MiB
b0d3373+dirty 5.15 MiB 6.68 MiB 1.53 MiB
fa21fca+dirty 4.98 MiB 6.55 MiB 1.57 MiB
0d9949d+dirty 3.38 MiB 4.76 MiB 1.38 MiB
a5d243c+dirty 5.15 MiB 6.68 MiB 1.53 MiB

@github-actions

Copy link
Copy Markdown
Contributor

Android (new) Performance metrics 🚀

  Plain With Sentry Diff
Startup time 434.96 ms 492.46 ms 57.50 ms
Size 49.74 MiB 55.38 MiB 5.63 MiB

Baseline results on branch: main

Startup times

Revision Plain With Sentry Diff
1d3572b+dirty 444.48 ms 478.42 ms 33.94 ms
6177334+dirty 404.80 ms 456.74 ms 51.94 ms
5a23c47+dirty 406.83 ms 451.47 ms 44.64 ms
a3265b6+dirty 410.96 ms 444.76 ms 33.80 ms
bf168a4+dirty 430.60 ms 459.31 ms 28.71 ms
ca9d079+dirty 460.67 ms 512.54 ms 51.87 ms
ef27341+dirty 519.02 ms 553.42 ms 34.40 ms
23598c3+dirty 371.92 ms 420.65 ms 48.74 ms
7d6fd3a+dirty 435.06 ms 458.78 ms 23.72 ms
a50b33d+dirty 353.21 ms 398.48 ms 45.27 ms

App size

Revision Plain With Sentry Diff
1d3572b+dirty 49.74 MiB 55.38 MiB 5.63 MiB
6177334+dirty 48.30 MiB 53.54 MiB 5.23 MiB
5a23c47+dirty 49.74 MiB 54.82 MiB 5.07 MiB
a3265b6+dirty 48.30 MiB 53.58 MiB 5.28 MiB
bf168a4+dirty 49.74 MiB 55.09 MiB 5.35 MiB
ca9d079+dirty 48.30 MiB 53.58 MiB 5.28 MiB
ef27341+dirty 48.30 MiB 53.54 MiB 5.24 MiB
23598c3+dirty 43.94 MiB 49.02 MiB 5.08 MiB
7d6fd3a+dirty 43.94 MiB 49.00 MiB 5.06 MiB
a50b33d+dirty 43.94 MiB 48.94 MiB 5.00 MiB

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.

iOS: RNSentry SPEC CHECKSUM is machine-specific (absolute xcframework path in FRAMEWORK_SEARCH_PATHS) → Podfile.lock churn across devs/CI

2 participants