Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Capture app start errors before JS #4472

Draft
wants to merge 27 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
00e9040
ref(ios): Extract Cocoa SDK init into standalone file (#4442)
krystofwoldrich Jan 21, 2025
4c0b8f4
Merge branch 'main' into capture-app-start-errors
krystofwoldrich Jan 21, 2025
2cb7eb2
ref(android): Extracts Android native initialization to standalone st…
antonis Jan 22, 2025
7144a64
feat(experimental): Add native `startWithConfigureOptions` for Apple …
krystofwoldrich Jan 22, 2025
7850677
feat: Read `sentry.options.json` during cocoa init (#4447)
krystofwoldrich Jan 22, 2025
1e5dbde
Adds utility class for converting `JsonObject` to `WritableMap` (#4479)
antonis Jan 23, 2025
22a5f81
feat: Automatically load `sentry.options.json` file (#4476)
krystofwoldrich Feb 3, 2025
a1cb36d
feat(experimental): Initialize Android SDK from json configuration (#…
antonis Feb 4, 2025
95c36ef
Merge branch 'main' into capture-app-start-errors
krystofwoldrich Feb 5, 2025
14fe05d
misc: Add `sentry.options.json` example to the changelog (#4509)
krystofwoldrich Feb 5, 2025
15a7e6d
feat(init): Load options from `sentry.options.json` in JS (#4510)
krystofwoldrich Feb 6, 2025
b9ec093
release: 6.7.0-alpha.0
getsentry-bot Feb 6, 2025
dbdd4b5
Merge branch 'release/6.7.0-alpha.0' into capture-app-start-errors
Feb 6, 2025
b947d7f
misc(sample): Change RN Sample to use native file init by default (#4…
krystofwoldrich Feb 13, 2025
6b08b9a
chore(sample-rn): Remove duplicate init options from code (#4532)
krystofwoldrich Feb 13, 2025
a7ffa1f
chore(sample-rn): Always use fhe file option (including auto init) (#…
krystofwoldrich Feb 13, 2025
28cf7b4
internal(sample-rn): Add Detox for integration/e2e tests of the rn sa…
krystofwoldrich Feb 14, 2025
cf00d4d
internal(sample-rn): Add header and message envelope tests (#4536)
krystofwoldrich Feb 17, 2025
b754aa3
Merge remote-tracking branch 'origin/main' into capture-app-start-errors
krystofwoldrich Feb 18, 2025
0bf6636
fix(sample-e2e): Fix type errors missing sentry/core and afterAll (#4…
krystofwoldrich Feb 20, 2025
0f5cd7d
Merge remote-tracking branch 'origin/main' into capture-app-start-errors
krystofwoldrich Feb 20, 2025
e935360
chore(samples): Add package scripts for native builds, dsn and testin…
krystofwoldrich Feb 21, 2025
952dd05
Merge branch 'main' into capture-app-start-errors
krystofwoldrich Feb 24, 2025
ae342a3
test(e2e): Verify captured Errors Screen transaction (#4584)
krystofwoldrich Feb 25, 2025
770f9fb
test(e2e): Add auto init from JS tests (#4588)
krystofwoldrich Feb 25, 2025
cbb85b2
test(e2e): Add app start crash test for iOS (#4593)
krystofwoldrich Feb 25, 2025
b4ee16b
test(e2e): Avoid race conditions when waiting for captured message (#…
krystofwoldrich Feb 26, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
230 changes: 190 additions & 40 deletions .github/workflows/sample-application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@ concurrency:
env:
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
RN_SENTRY_POD_NAME: RNSentry
IOS_APP_ARCHIVE_PATH: sentry-react-native-sample.app.zip
ANDROID_APP_ARCHIVE_PATH: sentry-react-native-sample.apk.zip
REACT_NATIVE_SAMPLE_PATH: samples/react-native
IOS_DEVICE: 'iPhone 16'
IOS_VERSION: '18.1'
ANDROID_API_LEVEL: '30'

jobs:
diff_check:
Expand Down Expand Up @@ -66,7 +72,7 @@ jobs:
- uses: ruby/setup-ruby@v1
if: ${{ matrix.platform == 'ios' || matrix.platform == 'macos' }}
with:
working-directory: ${{ matrix.platform == 'ios' && ' samples/react-native' || ' samples/react-native-macos' }}
working-directory: ${{ matrix.platform == 'ios' && env.REACT_NATIVE_SAMPLE_PATH || ' samples/react-native-macos' }}
ruby-version: '3.3.0' # based on what is used in the sample
bundler-cache: true # runs 'bundle install' and caches installed gems automatically
cache-version: 1 # cache the installed gems
Expand All @@ -93,59 +99,39 @@ jobs:
if: ${{ matrix.platform == 'ios' || matrix.platform == 'macos' }}
working-directory: samples
run: |
[[ "${{ matrix.platform }}" == "ios" ]] && cd react-native/ios
[[ "${{ matrix.platform }}" == "macos" ]] && cd react-native-macos/macos
[[ "${{ matrix.platform }}" == "ios" ]] && cd react-native
[[ "${{ matrix.platform }}" == "macos" ]] && cd react-native-macos

[[ "${{ matrix.build-type }}" == "production" ]] && ENABLE_PROD=1 || ENABLE_PROD=0
[[ "${{ matrix.rn-architecture }}" == "new" ]] && ENABLE_NEW_ARCH=1 || ENABLE_NEW_ARCH=0
[[ "${{ matrix.build-type }}" == "production" ]] && export ENABLE_PROD=1 || export ENABLE_PROD=0
[[ "${{ matrix.rn-architecture }}" == "new" ]] && export ENABLE_NEW_ARCH=1 || export ENABLE_NEW_ARCH=0
[[ "${{ matrix.ios-use-frameworks }}" == "dynamic-frameworks" ]] && export USE_FRAMEWORKS=dynamic
echo "ENABLE_PROD=$ENABLE_PROD"
echo "ENABLE_NEW_ARCH=$ENABLE_NEW_ARCH"
PRODUCTION=$ENABLE_PROD RCT_NEW_ARCH_ENABLED=$ENABLE_NEW_ARCH bundle exec pod install
cat Podfile.lock | grep $RN_SENTRY_POD_NAME

./scripts/pod-install.sh

- name: Build Android App
if: ${{ matrix.platform == 'android' }}
working-directory: samples/react-native/android
working-directory: ${{ env.REACT_NATIVE_SAMPLE_PATH }}
run: |
if [[ ${{ matrix.rn-architecture }} == 'new' ]]; then
perl -i -pe's/newArchEnabled=false/newArchEnabled=true/g' gradle.properties
echo 'New Architecture enabled'
elif [[ ${{ matrix.rn-architecture }} == 'legacy' ]]; then
perl -i -pe's/newArchEnabled=true/newArchEnabled=false/g' gradle.properties
echo 'Legacy Architecture enabled'
else
echo 'No changes for architecture: ${{ matrix.rn-architecture }}'
fi
[[ "${{ matrix.build-type }}" == "production" ]] && CONFIG='Release' || CONFIG='Debug'
echo "Building $CONFIG"
./gradlew ":app:assemble$CONFIG" -PreactNativeArchitectures=x86
export RN_ARCHITECTURE="${{ matrix.rn-architecture }}"
[[ "${{ matrix.build-type }}" == "production" ]] && export CONFIG='release' || export CONFIG='debug'

./scripts/set-dsn-aos.mjs
./scripts/build-android.sh -PreactNativeArchitectures=x86

- name: Build iOS App
if: ${{ matrix.platform == 'ios' }}
working-directory: samples/react-native/ios
working-directory: ${{ env.REACT_NATIVE_SAMPLE_PATH }}
run: |
[[ "${{ matrix.build-type }}" == "production" ]] && CONFIG='Release' || CONFIG='Debug'
echo "Building $CONFIG"
mkdir -p "DerivedData"
derivedData="$(cd "DerivedData" ; pwd -P)"
set -o pipefail && xcodebuild \
-workspace sentryreactnativesample.xcworkspace \
-configuration "$CONFIG" \
-scheme sentryreactnativesample \
-sdk 'iphonesimulator' \
-destination 'generic/platform=iOS Simulator' \
ONLY_ACTIVE_ARCH=yes \
-derivedDataPath "$derivedData" \
build \
| tee xcodebuild.log \
| xcbeautify --quieter --is-ci --disable-colored-output
[[ "${{ matrix.build-type }}" == "production" ]] && export CONFIG='Release' || export CONFIG='Debug'

./scripts/set-dsn-ios.mjs
./scripts/build-ios.sh

- name: Build macOS App
if: ${{ matrix.platform == 'macos' }}
working-directory: samples/react-native-macos/macos
run: |
[[ "${{ matrix.build-type }}" == "production" ]] && CONFIG='Release' || CONFIG='Debug'
[[ "${{ matrix.build-type }}" == "production" ]] && export CONFIG='Release' || export CONFIG='Debug'
echo "Building $CONFIG"
mkdir -p "DerivedData"
derivedData="$(cd "DerivedData" ; pwd -P)"
Expand All @@ -160,9 +146,173 @@ jobs:
| tee xcodebuild.log \
| xcbeautify --quieter --is-ci --disable-colored-output

- name: Archive iOS App
if: ${{ matrix.platform == 'ios' && matrix.rn-architecture == 'new' && matrix.build-type == 'production' && matrix.ios-use-frameworks == 'no-frameworks' }}
working-directory: ${{ env.REACT_NATIVE_SAMPLE_PATH }}
run: |
zip -r \
${{ github.workspace }}/${{ env.IOS_APP_ARCHIVE_PATH }} \
sentryreactnativesample.app

- name: Archive Android App
if: ${{ matrix.platform == 'android' && matrix.rn-architecture == 'new' && matrix.build-type == 'production' }}
run: |
zip -j \
${{ env.ANDROID_APP_ARCHIVE_PATH }} \
${{ env.REACT_NATIVE_SAMPLE_PATH }}/app.apk \
${{ env.REACT_NATIVE_SAMPLE_PATH }}/app-androidTest.apk

- name: Upload iOS APP
if: ${{ matrix.platform == 'ios' && matrix.rn-architecture == 'new' && matrix.build-type == 'production' && matrix.ios-use-frameworks == 'no-frameworks' }}
uses: actions/upload-artifact@v4
with:
name: sample-rn-${{ matrix.rn-architecture }}-${{ matrix.build-type }}-${{ matrix.ios-use-frameworks}}-${{ matrix.platform }}
path: ${{ env.IOS_APP_ARCHIVE_PATH }}
retention-days: 1

- name: Upload Android APK
if: ${{ matrix.platform == 'android' && matrix.rn-architecture == 'new' && matrix.build-type == 'production' }}
uses: actions/upload-artifact@v4
with:
name: sample-rn-${{ matrix.rn-architecture }}-${{ matrix.build-type }}-${{ matrix.platform }}
path: ${{ env.ANDROID_APP_ARCHIVE_PATH }}
retention-days: 1

- name: Upload logs
if: ${{ always() }}
uses: actions/upload-artifact@v4
with:
name: build-sample-${{ matrix.rn-architecture }}-${{ matrix.platform }}-${{ matrix.build-type }}-${{ matrix.ios-use-frameworks}}-logs
path: samples/react-native/${{ matrix.platform }}/*.log
path: ${{ env.REACT_NATIVE_SAMPLE_PATH }}/${{ matrix.platform }}/*.log

test:
name: ${{ matrix.job-name }}
runs-on: ${{ matrix.runs-on }}
needs: [diff_check, build]
if: ${{ needs.diff_check.outputs.skip_ci != 'true' }}
strategy:
# we want that the matrix keeps running, default is to cancel them if it fails.
fail-fast: false
matrix:
include:
- job-name: 'Test iOS Release Auto Init'
platform: ios
runs-on: macos-15
rn-architecture: 'new'
ios-use-frameworks: 'no-frameworks'
build-type: 'production'
test-command: 'yarn test-ios-auto' # tests native auto init from JS

- job-name: 'Test iOS Release Manual Init'
platform: ios
runs-on: macos-15
rn-architecture: 'new'
ios-use-frameworks: 'no-frameworks'
build-type: 'production'
test-command: 'yarn test-ios-manual'

- job-name: 'Test Android Release Manual Init'
platform: android
runs-on: ubuntu-latest
rn-architecture: 'new'
build-type: 'production'
test-command: 'yarn test-android'

steps:
- uses: actions/checkout@v4

- name: Download iOS App Archive
if: ${{ matrix.platform == 'ios' }}
uses: actions/download-artifact@v4
with:
name: sample-rn-${{ matrix.rn-architecture }}-${{ matrix.build-type }}-${{ matrix.ios-use-frameworks}}-${{ matrix.platform }}
path: ${{ env.REACT_NATIVE_SAMPLE_PATH }}

- name: Download Android APK
if: ${{ matrix.platform == 'android' }}
uses: actions/download-artifact@v4
with:
name: sample-rn-${{ matrix.rn-architecture }}-${{ matrix.build-type }}-${{ matrix.platform }}
path: ${{ env.REACT_NATIVE_SAMPLE_PATH }}

- name: Unzip iOS App Archive
if: ${{ matrix.platform == 'ios' }}
working-directory: ${{ env.REACT_NATIVE_SAMPLE_PATH }}
run: unzip ${{ env.IOS_APP_ARCHIVE_PATH }}

- name: Unzip Android APK
if: ${{ matrix.platform == 'android' }}
working-directory: ${{ env.REACT_NATIVE_SAMPLE_PATH }}
run: unzip ${{ env.ANDROID_APP_ARCHIVE_PATH }}

- name: Enable Corepack
run: |
npm install -g [email protected]
corepack enable
- uses: actions/setup-node@v4
with:
node-version: 18
cache: 'yarn'
cache-dependency-path: yarn.lock

- name: Install JS Dependencies
run: yarn install

- name: Install Detox
run: npm install -g [email protected]

- name: Install Apple Simulator Utilities
if: ${{ matrix.platform == 'ios' }}
run: |
brew tap wix/brew
brew install applesimutils

- name: Setup KVM
if: ${{ matrix.platform == 'android' }}
shell: bash
run: |
# check if virtualization is supported...
sudo apt install -y --no-install-recommends cpu-checker coreutils && echo "CPUs=$(nproc --all)" && kvm-ok
# allow access to KVM to run the emulator
echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' \
| sudo tee /etc/udev/rules.d/99-kvm4all.rules
sudo udevadm control --reload-rules
sudo udevadm trigger --name-match=kvm

- uses: futureware-tech/simulator-action@dab10d813144ef59b48d401cd95da151222ef8cd # pin@v4
if: ${{ matrix.platform == 'ios' }}
with:
# the same envs are used by Detox ci.sim configuration
model: ${{ env.IOS_DEVICE }}
os_version: ${{ env.IOS_VERSION }}

- name: Run Detox iOS Tests
if: ${{ matrix.platform == 'ios' }}
working-directory: ${{ env.REACT_NATIVE_SAMPLE_PATH }}
run: ${{ matrix.test-command }}

- name: Run tests on Android
if: ${{ matrix.platform == 'android' }}
env:
# used by Detox ci.android configuration
ANDROID_AVD_NAME: 'test' # test is default reactivecircus/android-emulator-runner name
ANDROID_TYPE: 'android.emulator'
uses: reactivecircus/android-emulator-runner@62dbb605bba737720e10b196cb4220d374026a6d # [email protected]
with:
api-level: ${{ env.ANDROID_API_LEVEL }}
force-avd-creation: false
disable-animations: true
disable-spellchecker: true
target: 'aosp_atd'
channel: canary # Necessary for ATDs
emulator-options: >
-no-window
-no-snapshot-save
-gpu swiftshader_indirect
-noaudio
-no-boot-anim
-camera-back none
-camera-front none
-timezone US/Pacific
working-directory: ${{ env.REACT_NATIVE_SAMPLE_PATH }}
script: ${{ matrix.test-command }}
55 changes: 55 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,61 @@
- [changelog](https://github.com/getsentry/sentry-javascript-bundler-plugins/blob/main/CHANGELOG.md#320)
- [diff](https://github.com/getsentry/sentry-javascript-bundler-plugins/compare/3.1.2...3.2.0)


## 6.7.0-alpha.0

### Features

- Capture App Start errors and crashes by initializing Sentry from `sentry.options.json` ([#4472](https://github.com/getsentry/sentry-react-native/pull/4472))

Create `sentry.options.json` in the React Native project root and set options the same as you currently have in `Sentry.init` in JS.

```json
{
"dsn": "https://[email protected]/value",
}
```

Initialize Sentry on the native layers by newly provided native methods.

```kotlin
import io.sentry.react.RNSentrySDK

class MainApplication : Application(), ReactApplication {
override fun onCreate() {
super.onCreate()
RNSentrySDK.init(this)
}
}
```

```obj-c
#import <RNSentry/RNSentry.h>

@implementation AppDelegate
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[RNSentrySDK start];
return [super application:application didFinishLaunchingWithOptions:launchOptions];
}
@end
```

### Changes

- Load `optionsFile` into the JS bundle during Metro bundle process ([#4476](https://github.com/getsentry/sentry-react-native/pull/4476))
- Add experimental version of `startWithConfigureOptions` for Apple platforms ([#4444](https://github.com/getsentry/sentry-react-native/pull/4444))
- Add experimental version of `init` with optional `OptionsConfiguration<SentryAndroidOptions>` for Android ([#4451](https://github.com/getsentry/sentry-react-native/pull/4451))
- Add initialization using `sentry.options.json` for Apple platforms ([#4447](https://github.com/getsentry/sentry-react-native/pull/4447))
- Add initialization using `sentry.options.json` for Android ([#4451](https://github.com/getsentry/sentry-react-native/pull/4451))
- Merge options from file with `Sentry.init` options in JS ([#4510](https://github.com/getsentry/sentry-react-native/pull/4510))

### Internal

- Extract iOS native initialization to standalone structures ([#4442](https://github.com/getsentry/sentry-react-native/pull/4442))
- Extract Android native initialization to standalone structures ([#4445](https://github.com/getsentry/sentry-react-native/pull/4445))

## 6.7.0

### Features
Expand Down
2 changes: 1 addition & 1 deletion lerna.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@
"performance-tests/*"
],
"npmClient": "yarn"
}
}
2 changes: 1 addition & 1 deletion packages/core/RNSentry.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ Pod::Spec.new do |s|
s.preserve_paths = '*.js'

s.source_files = 'ios/**/*.{h,m,mm}'
s.public_header_files = 'ios/RNSentry.h'
s.public_header_files = 'ios/RNSentry.h', 'ios/RNSentrySDK.h'

s.compiler_flags = other_cflags

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"dsn": "invalid-dsn"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
invalid-options
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"dsn": "https://[email protected]/123456",
"enableTracing": true,
"tracesSampleRate": 1.0
}
Loading