Skip to content

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

Draft
alwx wants to merge 1 commit into
mainfrom
alwx/bugfix/6467
Draft

fix(ios): make the RNSentry SPEC CHECKSUM in Podfile.lock machine-independent#6534
alwx wants to merge 1 commit 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

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
  • chore(deps): add sharp ^0.35.0 resolution (dev-only advisory) by antonis in #6525
  • chore(deps): add body-parser ^2.3.0 resolution (dev-only advisory) by antonis in #6524
  • chore(deps): add morgan ^1.11.0 resolution (dev-only advisory) by antonis in #6523
  • chore(deps): bump postcss to ^8.5.18 (dev-only advisory) by antonis in #6522
  • chore(deps): bump brace-expansion 5.x to ^5.0.8 (dev-only advisory) by antonis in #6521
  • ci: Disable yarn age gate when bumping first-party @sentry deps by antonis in #6513
  • feat(core): Attach TurboModule breakdown to active spans on spanEnd by alwx in #6478
  • feat(core): Export instrumentStateGraph and deprecate instrumentLangGraph by antonis in #6520
  • chore(deps): bump the codeql-action group across 1 directory with 3 updates by dependabot in #6517
  • chore(deps): bump ruby/setup-ruby from 1.319.0 to 1.321.0 by dependabot in #6518
  • chore(deps): bump actions/checkout from 7.0.0 to 7.0.1 by dependabot in #6519
  • chore(deps): update JavaScript SDK to v10.68.0 by github-actions in #6516
  • chore(deps): bump tar from 7.5.20 to 7.5.21 by dependabot in #6515
  • chore(deps): bump lerna to ^9.0.7 to resolve remaining dev-tooling advisories by antonis in #6499
  • chore(deps): Migrate to @sentry/bundler-plugins by antonis in #6501
  • chore: update changelog warning with fix version by antonis in #6509
  • chore(deps): bump actions/setup-node from 6.4.0 to 7.0.0 by dependabot in #6463
  • chore(deps): bump json from 2.17.1.2 to 2.19.9 in /performance-tests by dependabot in #6512
  • chore(deps): update CLI to v3.6.2 by github-actions in #6511
  • chore(deps): update Sentry Android Gradle Plugin to v6.16.0 by github-actions in #6508
  • chore(deps): update Android SDK to v8.50.1 by github-actions in #6503

🤖 This preview updates automatically when you update the PR.

@github-actions

Copy link
Copy Markdown
Contributor
Fails
🚫 Pull request is not ready for merge, please add the "ready-to-merge" label to the pull request
🚫 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 7c7cd0c

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

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

1 participant