Skip to content

Commit 04444cd

Browse files
alwxclaude
andcommitted
feat(ios): Consume sentry-cocoa as a prebuilt xcframework by default
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>
1 parent af33f3b commit 04444cd

7 files changed

Lines changed: 304 additions & 31 deletions

File tree

.github/workflows/sample-application.yml

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ jobs:
4343
caller_ref: ${{ github.ref }}
4444

4545
build-ios:
46-
name: Build ${{ matrix.rn-architecture }} ios ${{ matrix.build-type }} ${{ matrix.ios-use-frameworks }}
46+
name: Build ${{ matrix.rn-architecture }} ios ${{ matrix.build-type }} ${{ matrix.ios-use-frameworks }} ${{ matrix.sentry-consumption }}
4747
runs-on: macos-26-xlarge
4848
needs: [diff_check, detect-changes]
4949
if: >-
@@ -60,6 +60,16 @@ jobs:
6060
rn-architecture: ["new"]
6161
ios-use-frameworks: ["no-frameworks"]
6262
build-type: ["dev", "production"]
63+
sentry-consumption: ["xcframework"]
64+
# `xcframework` is the default: RNSentry vendors a prebuilt
65+
# `Sentry-Dynamic.xcframework` downloaded from sentry-cocoa's release.
66+
# Keep a single CocoaPods job to catch regressions in the source-build
67+
# fallback (`SENTRY_USE_XCFRAMEWORK=0`).
68+
include:
69+
- rn-architecture: "new"
70+
ios-use-frameworks: "no-frameworks"
71+
build-type: "production"
72+
sentry-consumption: "cocoapods"
6373
steps:
6474
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
6575

@@ -95,6 +105,7 @@ jobs:
95105
[[ "${{ matrix.build-type }}" == "production" ]] && export ENABLE_PROD=1 || export ENABLE_PROD=0
96106
[[ "${{ matrix.rn-architecture }}" == "new" ]] && export ENABLE_NEW_ARCH=1 || export ENABLE_NEW_ARCH=0
97107
[[ "${{ matrix.ios-use-frameworks }}" == "dynamic-frameworks" ]] && export USE_FRAMEWORKS=dynamic
108+
[[ "${{ matrix.sentry-consumption }}" == "cocoapods" ]] && export SENTRY_USE_XCFRAMEWORK=0
98109
99110
./scripts/pod-install.sh
100111
@@ -112,15 +123,18 @@ jobs:
112123
./scripts/build-ios.sh
113124
114125
- name: Archive iOS App
115-
if: ${{ matrix.rn-architecture == 'new' && matrix.build-type == 'production' && matrix.ios-use-frameworks == 'no-frameworks' }}
126+
# Only upload from the xcframework job (the default consumption path)
127+
# to avoid duplicate artifact names when the CocoaPods regression job
128+
# runs.
129+
if: ${{ matrix.rn-architecture == 'new' && matrix.build-type == 'production' && matrix.ios-use-frameworks == 'no-frameworks' && matrix.sentry-consumption == 'xcframework' }}
116130
working-directory: ${{ env.REACT_NATIVE_SAMPLE_PATH }}
117131
run: |
118132
zip -r \
119133
${{ github.workspace }}/${{ env.IOS_APP_ARCHIVE_PATH }} \
120134
sentryreactnativesample.app
121135
122136
- name: Upload iOS APP
123-
if: ${{ matrix.rn-architecture == 'new' && matrix.build-type == 'production' && matrix.ios-use-frameworks == 'no-frameworks' }}
137+
if: ${{ matrix.rn-architecture == 'new' && matrix.build-type == 'production' && matrix.ios-use-frameworks == 'no-frameworks' && matrix.sentry-consumption == 'xcframework' }}
124138
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
125139
with:
126140
name: sample-rn-${{ matrix.rn-architecture }}-${{ matrix.build-type }}-${{ matrix.ios-use-frameworks}}-ios
@@ -131,7 +145,7 @@ jobs:
131145
if: ${{ always() }}
132146
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
133147
with:
134-
name: build-sample-${{ matrix.rn-architecture }}-ios-${{ matrix.build-type }}-${{ matrix.ios-use-frameworks}}-logs
148+
name: build-sample-${{ matrix.rn-architecture }}-ios-${{ matrix.build-type }}-${{ matrix.ios-use-frameworks}}-${{ matrix.sentry-consumption }}-logs
135149
path: ${{ env.REACT_NATIVE_SAMPLE_PATH }}/ios/*.log
136150

137151
build-android:

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,14 @@
1212

1313
- Add experimental `extendAppStart`/`finishExtendedAppStart`/`getExtendedAppStartSpan` to extend the standalone app start window and instrument post-init work ([#6392](https://github.com/getsentry/sentry-react-native/pull/6392))
1414

15+
### Changes
16+
17+
- Consume `sentry-cocoa` as a prebuilt xcframework by default on iOS ([#6413](https://github.com/getsentry/sentry-react-native/pull/6413))
18+
19+
**Warning**
20+
21+
**This may be a breaking change for some setups.** `pod install` now downloads `Sentry.xcframework` from sentry-cocoa's GitHub release (SHA256-verified) and vendors it, instead of building Sentry from source as a CocoaPod. If your iOS build breaks after upgrading (e.g. when another pod also depends on the `Sentry` CocoaPod), or if your `pod install` environment cannot reach `github.com`, set `SENTRY_USE_XCFRAMEWORK=0` before `pod install` to restore the previous source-build behavior.
22+
1523
### Fixes
1624

1725
- Skip iOS source maps upload on `Debug` builds ([#6405](https://github.com/getsentry/sentry-react-native/pull/6405))

packages/core/RNSentry.podspec

Lines changed: 98 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -45,41 +45,115 @@ Pod::Spec.new do |s|
4545
# is pulled in here; on Android it is compiled by the dedicated CMake target
4646
# in `android/CMakeLists.txt`. The files are guarded with
4747
# `RCT_NEW_ARCH_ENABLED` so they compile to empty TUs on Old Arch.
48-
s.source_files = 'ios/**/*.{h,m,mm}', 'cpp/**/*.{h,cpp}'
48+
#
49+
# We include `.swift` (for `RNSentrySwiftLinkStub.swift`) only on RN >=
50+
# 0.75. Adding a Swift file makes CocoaPods treat RNSentry as a Swift
51+
# pod, which then requires modular headers from its ObjC dependencies
52+
# (React-Core, React-hermes) — RN < 0.75 doesn't emit those, so
53+
# `pod install` fails with:
54+
# "The Swift pod `RNSentry` depends upon `React-hermes`, which does
55+
# not define modules."
56+
# The stub is only needed when linking Sentry.xcframework's Swift
57+
# symbols into a dynamic framework anyway (RN 0.86+ `use_frameworks!
58+
# :dynamic`), so gating on RN 0.75 is safe.
59+
supports_swift_stub = rn_version[:major] >= 1 || (rn_version[:major] == 0 && rn_version[:minor] >= 75)
60+
if supports_swift_stub
61+
s.source_files = 'ios/**/*.{h,m,mm,swift}', 'cpp/**/*.{h,cpp}'
62+
s.swift_versions = ['5.5']
63+
else
64+
s.source_files = 'ios/**/*.{h,m,mm}', 'cpp/**/*.{h,cpp}'
65+
end
4966
s.public_header_files = 'ios/RNSentry.h', 'ios/RNSentrySDK.h', 'ios/RNSentryStart.h', 'ios/RNSentryVersion.h', 'ios/RNSentryBreadcrumb.h', 'ios/RNSentryReplay.h', 'ios/RNSentryReplayBreadcrumbConverter.h', 'ios/Replay/RNSentryReplayMask.h', 'ios/Replay/RNSentryReplayUnmask.h', 'ios/RNSentryTimeToDisplay.h'
5067

5168
s.compiler_flags = other_cflags
5269

53-
s.pod_target_xcconfig = {
70+
pod_target_xcconfig = {
5471
'DEFINES_MODULE' => 'YES'
5572
}
5673

5774
sentry_cocoa_version = '9.19.1'
5875

59-
# Opt-in to consuming sentry-cocoa via Swift Package Manager.
60-
# When `SENTRY_USE_SPM=1` is set, RNSentry pulls `Sentry` from the
61-
# sentry-cocoa SPM package as a binary xcframework instead of from
62-
# the Sentry CocoaPods source build. Defaults to CocoaPods consumption
63-
# for backward compatibility with the full RN version range we support.
76+
# Consume sentry-cocoa as a prebuilt `Sentry.xcframework` by default.
6477
#
65-
# Requires React Native >= 0.75 because the SPM helper
66-
# (`react-native/scripts/cocoapods/spm.rb`) is loaded transitively from
67-
# the Podfile via `react_native_pods.rb`.
68-
if ENV['SENTRY_USE_SPM'] == '1'
69-
unless defined?(SPM) && SPM.respond_to?(:dependency)
70-
raise 'SENTRY_USE_SPM=1 is set but the SPM helper is not loaded. ' \
71-
'This requires React Native >= 0.75 and a Podfile that imports ' \
72-
'react_native_pods.rb.'
78+
# The xcframework is downloaded from sentry-cocoa's GitHub Release,
79+
# SHA256-verified, and cached under `~/Library/Caches/sentry-react-native/
80+
# xcframeworks/<version>/` (override with `SENTRY_XCFRAMEWORK_CACHE_DIR`).
81+
# Slice paths are then wired into the pod and app target via
82+
# `FRAMEWORK_SEARCH_PATHS` below. Consuming the xcframework this way
83+
# avoids compiling sentry-cocoa from source (fast install) and
84+
# sidesteps the Xcode 16/26 archive bug that affects the same
85+
# xcframework when consumed through Xcode's SPM integration
86+
# (`Signatures/*.signature` collision during archive).
87+
#
88+
# Set `SENTRY_USE_XCFRAMEWORK=0` to fall back to the source-built
89+
# `Sentry` CocoaPod (e.g. for offline builds behind a restrictive proxy).
90+
#
91+
# `SENTRY_USE_SPM` was the name in earlier drafts of this PR; honor it as a
92+
# deprecated alias so CI or local envs still exporting `SENTRY_USE_SPM=0`
93+
# don't silently take the new xcframework path.
94+
env_use_xcframework = ENV['SENTRY_USE_XCFRAMEWORK']
95+
if env_use_xcframework.nil? && !ENV['SENTRY_USE_SPM'].nil?
96+
Pod::UI.warn '[Sentry] SENTRY_USE_SPM is deprecated; use SENTRY_USE_XCFRAMEWORK instead.' if defined?(Pod::UI)
97+
env_use_xcframework = ENV['SENTRY_USE_SPM']
98+
end
99+
use_xcframework = case env_use_xcframework
100+
when '0' then false
101+
else true
102+
end
103+
104+
if use_xcframework
105+
sentry_xcframework_dir = ensure_sentry_xcframework(sentry_cocoa_version, 'Sentry')
106+
107+
# We deliberately do NOT set `s.vendored_frameworks` even though the
108+
# xcframework is downloaded and referenced below. CocoaPods doesn't
109+
# stage vendored xcframeworks for `path:` (development) pods anyway
110+
# — it did nothing for us functionally — and pointing it at a path
111+
# inside `node_modules/@sentry/react-native/ios/Vendor/` used to be
112+
# actively harmful, because that path only existed when the SDK was
113+
# cached into the package directory (broken under pnpm's isolated
114+
# store / Yarn PnP where node_modules is read-only). Framework
115+
# linking still happens: `@import Sentry;` in RNSentry.mm + user
116+
# code triggers clang's `-fmodules-autolink`, which emits the
117+
# `-framework Sentry` linker directive automatically once the
118+
# module is discovered via `FRAMEWORK_SEARCH_PATHS` below.
119+
120+
# Xcode's `-F <dir>` doesn't descend into `.xcframework` bundles — it
121+
# looks for `Sentry.framework` directly at the given path. Point a
122+
# separate framework search path at each slice, gated by the matching
123+
# SDK selector so `#import <Sentry/…>` resolves against exactly one
124+
# slice per build. An unconditional search-path list would let Xcode's
125+
# Swift module precompiler stumble into a slice for a different arch
126+
# and fail with "unsupported Swift architecture".
127+
#
128+
# We hardcode the slice → SDK map in `SENTRY_XCFRAMEWORK_SLICES_BY_SDK`
129+
# (see `sentry_utils.rb`) rather than scanning the extracted bundle —
130+
# sentry-cocoa's `Sentry.xcframework` layout is stable across releases.
131+
# Add a slice there if a future release ships one.
132+
#
133+
# Point the search paths at the pod-install-time absolute path to the
134+
# xcframework. `${PODS_TARGET_SRCROOT}` is only defined in per-pod
135+
# xcconfigs, not in aggregate/user-target xcconfigs, and a
136+
# `${PODS_ROOT}`-relative fallback works for one Podfile layout but
137+
# breaks for another (e.g. the RN sample apps put node_modules at a
138+
# different depth from RNSentryCocoaTester). Using the absolute path
139+
# avoids the layout-detection dance — the path is regenerated on
140+
# every `pod install`, so it's not something anyone commits.
141+
xcframework_search_paths = SENTRY_XCFRAMEWORK_SLICES_BY_SDK.each_with_object({}) do |(sdk, slice_ids), acc|
142+
paths = slice_ids.map { |slice| %("#{File.join(sentry_xcframework_dir, slice)}") }
143+
acc["FRAMEWORK_SEARCH_PATHS[sdk=#{sdk}*]"] = (['$(inherited)'] + paths).join(' ')
73144
end
74-
SPM.dependency(s,
75-
url: 'https://github.com/getsentry/sentry-cocoa',
76-
requirement: { kind: 'exactVersion', version: sentry_cocoa_version },
77-
products: ['Sentry']
78-
)
145+
146+
pod_target_xcconfig.merge!(xcframework_search_paths)
147+
s.user_target_xcconfig = xcframework_search_paths
79148
else
80149
s.dependency 'Sentry', sentry_cocoa_version
81150
end
82151

152+
# Assign before `install_modules_dependencies` so it can merge its
153+
# RN-specific settings on top. Assigning after would clobber those and
154+
# break header resolution across the pod.
155+
s.pod_target_xcconfig = pod_target_xcconfig
156+
83157
if defined? install_modules_dependencies
84158
# Default React Native dependencies for 0.71 and above (new and legacy architecture)
85159
install_modules_dependencies(s)
@@ -88,10 +162,13 @@ Pod::Spec.new do |s|
88162

89163
if is_new_arch_enabled then
90164
# New Architecture on React Native 0.70 and older
91-
s.pod_target_xcconfig.merge!({
165+
pod_target_xcconfig.merge!({
92166
"HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/boost\"",
93167
"CLANG_CXX_LANGUAGE_STANDARD" => "c++17"
94168
})
169+
# `install_modules_dependencies` is not defined on RN < 0.71 so re-assigning
170+
# here is safe — nothing else has written to `s.pod_target_xcconfig` yet.
171+
s.pod_target_xcconfig = pod_target_xcconfig
95172

96173
s.dependency "React-RCTFabric" # Required for Fabric Components (like RCTViewComponentView)
97174
s.dependency "React-Codegen"
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// This file exists to force Xcode to link the Swift runtime compatibility
2+
// libraries (e.g. libswiftCompatibility56, libswiftCompatibilityConcurrency)
3+
// into RNSentry. Those libs are required by our vendored `Sentry.xcframework`
4+
// static Swift library and Xcode only auto-links them when the consuming
5+
// target itself contains Swift code — without this stub, linking a dynamic
6+
// RNSentry framework fails with:
7+
// Undefined symbols: "__swift_FORCE_LOAD_$_swiftCompatibility56"
8+
9+
// A private, unused constant so the compiler emits a real object file. A
10+
// pure-comment file compiles to nothing and would defeat the purpose of
11+
// the stub.
12+
private let _rnSentrySwiftLinkStub: Void = ()

packages/core/scripts/sentry_utils.rb

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,128 @@ def should_use_folly_flags(rn_version)
4040
def is_new_hermes_runtime(rn_version)
4141
return (rn_version[:major] >= 1 || (rn_version[:major] == 0 && rn_version[:minor] >= 81))
4242
end
43+
44+
require 'digest'
45+
require 'fileutils'
46+
require 'open-uri'
47+
48+
# SHA256 checksums of `<product>.xcframework.zip` assets published in
49+
# sentry-cocoa GitHub releases (same value as the SPM binary target checksum
50+
# in sentry-cocoa's `Package.swift`). Register the checksum for each
51+
# sentry-cocoa version we ship a prebuilt xcframework for.
52+
#
53+
# Kept in sync with `sentry_cocoa_version` in `RNSentry.podspec` by
54+
# `scripts/update-cocoa.sh set-version <new>`, which downloads the new
55+
# release archive, computes its SHA256, and rewrites the entry below.
56+
SENTRY_COCOA_XCFRAMEWORK_CHECKSUMS = {
57+
# `Sentry.xcframework.zip` — the static product. Its enclosing xcframework
58+
# name matches the framework name inside (both `Sentry`), which CocoaPods
59+
# requires to generate `-framework Sentry` correctly and to resolve the
60+
# `Sentry` module. `Sentry-Dynamic.xcframework` would ship the same
61+
# `Sentry.framework` inside but under a mismatched enclosing name, so
62+
# CocoaPods generates `-framework Sentry-Dynamic` and fails at link.
63+
'9.19.1' => {
64+
'Sentry' => 'd6d545af17e49851cda2747b0f45cde78ce08ea37709dde5a956c6b4671224e8',
65+
},
66+
}.freeze
67+
68+
# Static map from xcframework slice directory name to the Xcode SDK selector
69+
# it should be attached to. `sentry-cocoa`'s `Sentry.xcframework` layout is
70+
# stable across releases — same slice names come out of every build — so we
71+
# hardcode the mapping rather than scanning the extracted bundle. Add a
72+
# new entry here if `sentry-cocoa` ever ships a new platform slice.
73+
SENTRY_XCFRAMEWORK_SLICES_BY_SDK = {
74+
'iphoneos' => %w[ios-arm64_arm64e],
75+
'iphonesimulator' => %w[ios-arm64_x86_64-simulator],
76+
'maccatalyst' => %w[ios-arm64_arm64e_x86_64-maccatalyst],
77+
'macosx' => %w[macos-arm64_arm64e_x86_64],
78+
'appletvos' => %w[tvos-arm64_arm64e],
79+
'appletvsimulator' => %w[tvos-arm64_x86_64-simulator],
80+
'watchos' => %w[watchos-arm64_arm64_32_arm64e_armv7k],
81+
'watchsimulator' => %w[watchos-arm64_x86_64-simulator],
82+
'xros' => %w[xros-arm64_arm64e],
83+
'xrsimulator' => %w[xros-arm64_x86_64-simulator],
84+
}.freeze
85+
86+
# Ensures `<cache>/<version>/<product>.xcframework` exists.
87+
#
88+
# On first invocation, downloads the prebuilt xcframework zip from
89+
# sentry-cocoa's GitHub release, verifies its SHA256 checksum against
90+
# `SENTRY_COCOA_XCFRAMEWORK_CHECKSUMS`, and extracts it. Subsequent
91+
# invocations are no-ops. Returns the absolute path to the extracted
92+
# xcframework, which callers pass to `FRAMEWORK_SEARCH_PATHS`.
93+
#
94+
# The cache lives under a user-writable directory (`~/Library/Caches/
95+
# sentry-react-native/xcframeworks/` on macOS by default; override with
96+
# `SENTRY_XCFRAMEWORK_CACHE_DIR`). Cannot live under the pod's own source
97+
# tree because pnpm's isolated store makes `node_modules/@sentry/
98+
# react-native/ios/` read-only, and `Yarn PnP` doesn't materialize the
99+
# package directory at all — writing there fails with `EACCES`.
100+
# Deduplicating cache across multiple RN projects on the same machine
101+
# is a nice side effect.
102+
#
103+
# Consuming sentry-cocoa this way (vs. through Xcode's SPM integration)
104+
# avoids the Xcode 16/26 archive bug where a signed SPM binary xcframework's
105+
# `Signatures/*.signature` file collides during the archive step.
106+
def ensure_sentry_xcframework(version, product = 'Sentry')
107+
cache_root = ENV['SENTRY_XCFRAMEWORK_CACHE_DIR'] ||
108+
File.expand_path('~/Library/Caches/sentry-react-native/xcframeworks')
109+
vendor_dir = File.join(cache_root, version)
110+
target_dir = File.join(vendor_dir, "#{product}.xcframework")
111+
# Treat the presence of `Info.plist` inside the xcframework as the "healthy"
112+
# sentinel rather than just the directory existence. A directory without
113+
# `Info.plist` most likely came from an interrupted `unzip` and would
114+
# otherwise silently short-circuit re-download here.
115+
target_manifest = File.join(target_dir, 'Info.plist')
116+
return target_dir if File.file?(target_manifest)
117+
118+
expected_checksum = SENTRY_COCOA_XCFRAMEWORK_CHECKSUMS.dig(version, product)
119+
unless expected_checksum
120+
raise "sentry-cocoa xcframework checksum not registered for #{product} " \
121+
"#{version}. Add it to SENTRY_COCOA_XCFRAMEWORK_CHECKSUMS in " \
122+
"packages/core/scripts/sentry_utils.rb after bumping the version."
123+
end
124+
125+
# Wipe any stale partial extract from a previous interrupted run so we
126+
# always start from a clean tree.
127+
FileUtils.rm_rf(target_dir)
128+
FileUtils.mkdir_p(vendor_dir)
129+
zip_path = File.join(vendor_dir, "#{product}.xcframework.zip")
130+
url = "https://github.com/getsentry/sentry-cocoa/releases/download/" \
131+
"#{version}/#{product}.xcframework.zip"
132+
133+
Pod::UI.puts "[Sentry] Downloading #{product} #{version} from GitHub Releases…" if defined?(Pod::UI)
134+
begin
135+
URI.open(url, redirect: true) do |remote|
136+
File.open(zip_path, 'wb') { |f| IO.copy_stream(remote, f) }
137+
end
138+
rescue OpenURI::HTTPError, SocketError, StandardError => e
139+
FileUtils.rm_f(zip_path)
140+
raise "Failed to download #{url}: #{e.class}: #{e.message}"
141+
end
142+
143+
actual_checksum = Digest::SHA256.file(zip_path).hexdigest
144+
unless actual_checksum == expected_checksum
145+
FileUtils.rm_f(zip_path)
146+
raise "Checksum mismatch for #{product} #{version}: expected " \
147+
"#{expected_checksum}, got #{actual_checksum}"
148+
end
149+
150+
unless system('unzip', '-q', '-o', zip_path, '-d', vendor_dir)
151+
raise "Failed to extract #{zip_path}"
152+
end
153+
FileUtils.rm_f(zip_path)
154+
155+
# Guard against a release archive whose internal layout changed (e.g. a
156+
# nested folder). Without this check, a wrong layout silently succeeds and
157+
# then fails much later during `pod install` with a confusing "framework
158+
# not found" error.
159+
unless File.file?(target_manifest)
160+
raise "Expected #{target_manifest} after extracting #{product}.xcframework.zip. " \
161+
"The sentry-cocoa release archive layout may have changed — update " \
162+
"the extraction logic in packages/core/scripts/sentry_utils.rb."
163+
end
164+
165+
target_dir
166+
end
167+

scripts/clang-format.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ cmd="find . -type f \( \
6464
-path \"**android/build/**\" -or \
6565
-path \"**.cxx/**\" -or \
6666
-path \"**build/generated/**\" -or \
67+
-path \"**/DerivedData/**\" -or \
6768
-path \"**/Carthage/Checkouts/*\" -or \
6869
-path \"**/libs/**\" -or \
6970
-path \"**/.yalc/**\" -or \

0 commit comments

Comments
 (0)