Skip to content

Commit 47299fb

Browse files
Merge c391854 into a7ffa1f
2 parents a7ffa1f + c391854 commit 47299fb

File tree

13 files changed

+900
-19
lines changed

13 files changed

+900
-19
lines changed

.github/workflows/sample-application.yml

Lines changed: 155 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,12 @@ concurrency:
1414
env:
1515
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
1616
RN_SENTRY_POD_NAME: RNSentry
17+
IOS_APP_ARCHIVE_PATH: sentry-react-native-sample.app.zip
18+
ANDROID_APP_ARCHIVE_PATH: sentry-react-native-sample.apk.zip
19+
REACT_NATIVE_SAMPLE_PATH: samples/react-native
20+
IOS_DEVICE: 'iPhone 16'
21+
IOS_VERSION: '18.1'
22+
ANDROID_API_LEVEL: '30'
1723

1824
jobs:
1925
diff_check:
@@ -66,7 +72,7 @@ jobs:
6672
- uses: ruby/setup-ruby@v1
6773
if: ${{ matrix.platform == 'ios' || matrix.platform == 'macos' }}
6874
with:
69-
working-directory: ${{ matrix.platform == 'ios' && ' samples/react-native' || ' samples/react-native-macos' }}
75+
working-directory: ${{ matrix.platform == 'ios' && env.REACT_NATIVE_SAMPLE_PATH || ' samples/react-native-macos' }}
7076
ruby-version: '3.3.0' # based on what is used in the sample
7177
bundler-cache: true # runs 'bundle install' and caches installed gems automatically
7278
cache-version: 1 # cache the installed gems
@@ -106,7 +112,7 @@ jobs:
106112
107113
- name: Build Android App
108114
if: ${{ matrix.platform == 'android' }}
109-
working-directory: samples/react-native/android
115+
working-directory: ${{ env.REACT_NATIVE_SAMPLE_PATH }}/android
110116
run: |
111117
if [[ ${{ matrix.rn-architecture }} == 'new' ]]; then
112118
perl -i -pe's/newArchEnabled=false/newArchEnabled=true/g' gradle.properties
@@ -119,11 +125,14 @@ jobs:
119125
fi
120126
[[ "${{ matrix.build-type }}" == "production" ]] && CONFIG='Release' || CONFIG='Debug'
121127
echo "Building $CONFIG"
122-
./gradlew ":app:assemble$CONFIG" -PreactNativeArchitectures=x86
128+
[[ "${{ matrix.build-type }}" == "production" ]] && TEST_TYPE='release' || TEST_TYPE='debug'
129+
echo "Building $TEST_TYPE"
130+
131+
./gradlew ":app:assemble$CONFIG" app:assembleAndroidTest -DtestBuildType=$TEST_TYPE -PreactNativeArchitectures=x86
123132
124133
- name: Build iOS App
125134
if: ${{ matrix.platform == 'ios' }}
126-
working-directory: samples/react-native/ios
135+
working-directory: ${{ env.REACT_NATIVE_SAMPLE_PATH }}/ios
127136
run: |
128137
[[ "${{ matrix.build-type }}" == "production" ]] && CONFIG='Release' || CONFIG='Debug'
129138
echo "Building $CONFIG"
@@ -160,9 +169,150 @@ jobs:
160169
| tee xcodebuild.log \
161170
| xcbeautify --quieter --is-ci --disable-colored-output
162171
172+
- name: Archive iOS App
173+
if: ${{ matrix.platform == 'ios' && matrix.rn-architecture == 'new' && matrix.build-type == 'production' && matrix.ios-use-frameworks == 'no-frameworks' }}
174+
run: |
175+
cd ${{ env.REACT_NATIVE_SAMPLE_PATH }}/ios/DerivedData/Build/Products/Release-iphonesimulator
176+
zip -r \
177+
${{ github.workspace }}/${{ env.IOS_APP_ARCHIVE_PATH }} \
178+
sentryreactnativesample.app
179+
180+
- name: Archive Android App
181+
if: ${{ matrix.platform == 'android' && matrix.rn-architecture == 'new' && matrix.build-type == 'production' }}
182+
run: |
183+
mv ${{ env.REACT_NATIVE_SAMPLE_PATH }}/android/app/build/outputs/apk/release/app-release.apk app.apk
184+
mv ${{ env.REACT_NATIVE_SAMPLE_PATH }}/android/app/build/outputs/apk/androidTest/release/app-release-androidTest.apk app-androidTest.apk
185+
zip -j \
186+
${{ env.ANDROID_APP_ARCHIVE_PATH }} \
187+
app.apk \
188+
app-androidTest.apk
189+
190+
- name: Upload iOS APP
191+
if: ${{ matrix.platform == 'ios' && matrix.rn-architecture == 'new' && matrix.build-type == 'production' && matrix.ios-use-frameworks == 'no-frameworks' }}
192+
uses: actions/upload-artifact@v4
193+
with:
194+
name: sample-rn-${{ matrix.rn-architecture }}-${{ matrix.build-type }}-${{ matrix.ios-use-frameworks}}-${{ matrix.platform }}
195+
path: ${{ env.IOS_APP_ARCHIVE_PATH }}
196+
retention-days: 1
197+
198+
- name: Upload Android APK
199+
if: ${{ matrix.platform == 'android' && matrix.rn-architecture == 'new' && matrix.build-type == 'production' }}
200+
uses: actions/upload-artifact@v4
201+
with:
202+
name: sample-rn-${{ matrix.rn-architecture }}-${{ matrix.build-type }}-${{ matrix.platform }}
203+
path: ${{ env.ANDROID_APP_ARCHIVE_PATH }}
204+
retention-days: 1
205+
163206
- name: Upload logs
164207
if: ${{ always() }}
165208
uses: actions/upload-artifact@v4
166209
with:
167210
name: build-sample-${{ matrix.rn-architecture }}-${{ matrix.platform }}-${{ matrix.build-type }}-${{ matrix.ios-use-frameworks}}-logs
168-
path: samples/react-native/${{ matrix.platform }}/*.log
211+
path: ${{ env.REACT_NATIVE_SAMPLE_PATH }}/${{ matrix.platform }}/*.log
212+
213+
test:
214+
name: Test ${{ matrix.platform }} ${{ matrix.build-type }}
215+
runs-on: ${{ matrix.runs-on }}
216+
needs: [diff_check, build]
217+
if: ${{ needs.diff_check.outputs.skip_ci != 'true' }}
218+
strategy:
219+
# we want that the matrix keeps running, default is to cancel them if it fails.
220+
fail-fast: false
221+
matrix:
222+
include:
223+
- platform: ios
224+
runs-on: macos-15
225+
rn-architecture: 'new'
226+
ios-use-frameworks: 'no-frameworks'
227+
build-type: 'production'
228+
229+
- platform: android
230+
runs-on: ubuntu-latest
231+
rn-architecture: 'new'
232+
build-type: 'production'
233+
234+
steps:
235+
- uses: actions/checkout@v4
236+
237+
- name: Download iOS App Archive
238+
if: ${{ matrix.platform == 'ios' }}
239+
uses: actions/download-artifact@v4
240+
with:
241+
name: sample-rn-${{ matrix.rn-architecture }}-${{ matrix.build-type }}-${{ matrix.ios-use-frameworks}}-${{ matrix.platform }}
242+
path: ${{ env.REACT_NATIVE_SAMPLE_PATH }}
243+
244+
- name: Download Android APK
245+
if: ${{ matrix.platform == 'android' }}
246+
uses: actions/download-artifact@v4
247+
with:
248+
name: sample-rn-${{ matrix.rn-architecture }}-${{ matrix.build-type }}-${{ matrix.platform }}
249+
path: ${{ env.REACT_NATIVE_SAMPLE_PATH }}
250+
251+
- name: Unzip iOS App Archive
252+
if: ${{ matrix.platform == 'ios' }}
253+
working-directory: ${{ env.REACT_NATIVE_SAMPLE_PATH }}
254+
run: unzip ${{ env.IOS_APP_ARCHIVE_PATH }}
255+
256+
- name: Unzip Android APK
257+
if: ${{ matrix.platform == 'android' }}
258+
working-directory: ${{ env.REACT_NATIVE_SAMPLE_PATH }}
259+
run: unzip ${{ env.ANDROID_APP_ARCHIVE_PATH }}
260+
261+
- name: Enable Corepack
262+
run: |
263+
npm install -g [email protected]
264+
corepack enable
265+
- uses: actions/setup-node@v4
266+
with:
267+
node-version: 18
268+
cache: 'yarn'
269+
cache-dependency-path: yarn.lock
270+
271+
- name: Install JS Dependencies
272+
run: yarn install
273+
274+
- name: Install Detox
275+
run: npm install -g [email protected]
276+
277+
- name: Install Apple Simulator Utilities
278+
if: ${{ matrix.platform == 'ios' }}
279+
run: |
280+
brew tap wix/brew
281+
brew install applesimutils
282+
283+
- uses: futureware-tech/simulator-action@dab10d813144ef59b48d401cd95da151222ef8cd # pin@v4
284+
if: ${{ matrix.platform == 'ios' }}
285+
with:
286+
# the same envs are used by Detox ci.sim configuration
287+
model: ${{ env.IOS_DEVICE }}
288+
os_version: ${{ env.IOS_VERSION }}
289+
290+
- name: Run Detox iOS Tests
291+
if: ${{ matrix.platform == 'ios' }}
292+
working-directory: ${{ env.REACT_NATIVE_SAMPLE_PATH }}
293+
run: detox test --configuration ci.sim
294+
295+
- name: Run tests on Android
296+
if: ${{ matrix.platform == 'android' }}
297+
env:
298+
# used by Detox ci.android configuration
299+
ANDROID_AVD_NAME: 'test' # test is default reactivecircus/android-emulator-runner name
300+
uses: reactivecircus/android-emulator-runner@62dbb605bba737720e10b196cb4220d374026a6d # [email protected]
301+
with:
302+
api-level: ${{ env.ANDROID_API_LEVEL }}
303+
force-avd-creation: false
304+
disable-animations: true
305+
disable-spellchecker: true
306+
target: 'aosp_atd'
307+
channel: canary # Necessary for ATDs
308+
emulator-options: >
309+
-no-window
310+
-no-snapshot-save
311+
-gpu swiftshader_indirect
312+
-noaudio
313+
-no-boot-anim
314+
-camera-back none
315+
-camera-front none
316+
-timezone US/Pacific
317+
working-directory: ${{ env.REACT_NATIVE_SAMPLE_PATH }}
318+
script: detox test --configuration ci.android

samples/react-native/.detoxrc.js

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
const process = require('process');
2+
3+
/** @type {Detox.DetoxConfig} */
4+
module.exports = {
5+
testRunner: {
6+
args: {
7+
$0: 'jest',
8+
config: 'e2e/jest.config.js',
9+
},
10+
jest: {
11+
setupTimeout: 120000,
12+
},
13+
},
14+
apps: {
15+
'ios.debug': {
16+
type: 'ios.app',
17+
binaryPath:
18+
'ios/build/Build/Products/Debug-iphonesimulator/sentryreactnativesample.app',
19+
build:
20+
'xcodebuild -workspace ios/sentryreactnativesample.xcworkspace -scheme sentryreactnativesample -configuration Debug -sdk iphonesimulator -derivedDataPath ios/build',
21+
},
22+
'ios.release': {
23+
type: 'ios.app',
24+
binaryPath:
25+
'ios/build/Build/Products/Release-iphonesimulator/sentryreactnativesample.app',
26+
build:
27+
'xcodebuild -workspace ios/sentryreactnativesample.xcworkspace -scheme sentryreactnativesample -configuration Release -sdk iphonesimulator -derivedDataPath ios/build',
28+
},
29+
'android.debug': {
30+
type: 'android.apk',
31+
binaryPath: 'android/app/build/outputs/apk/debug/app-debug.apk',
32+
build:
33+
'cd android && ./gradlew app:assembleDebug app:assembleAndroidTest -DtestBuildType=debug',
34+
reversePorts: [8081],
35+
},
36+
'android.release': {
37+
type: 'android.apk',
38+
binaryPath: 'android/app/build/outputs/apk/release/app-release.apk',
39+
build:
40+
'cd android && ./gradlew app:assembleRelease app:assembleAndroidTest -DtestBuildType=release',
41+
},
42+
'ci.android': {
43+
type: 'android.apk',
44+
binaryPath: 'app.apk',
45+
testBinaryPath: 'app-androidTest.apk',
46+
},
47+
'ci.ios': {
48+
type: 'ios.app',
49+
binaryPath: 'sentryreactnativesample.app',
50+
},
51+
},
52+
devices: {
53+
simulator: {
54+
type: 'ios.simulator',
55+
device: {
56+
type: 'iPhone 16',
57+
},
58+
},
59+
attached: {
60+
type: 'android.attached',
61+
device: {
62+
adbName: '.*',
63+
},
64+
},
65+
emulator: {
66+
type: 'android.emulator',
67+
device: {
68+
avdName: 'Pixel_9_API_35',
69+
},
70+
},
71+
'ci.emulator': {
72+
type: 'android.emulator',
73+
device: {
74+
avdName: process.env.ANDROID_AVD_NAME,
75+
},
76+
},
77+
'ci.simulator': {
78+
type: 'ios.simulator',
79+
device: {
80+
type: process.env.IOS_DEVICE,
81+
os: process.env.IOS_VERSION,
82+
},
83+
},
84+
},
85+
configurations: {
86+
'ios.sim.debug': {
87+
device: 'simulator',
88+
app: 'ios.debug',
89+
},
90+
'ios.sim.release': {
91+
device: 'simulator',
92+
app: 'ios.release',
93+
},
94+
'android.att.debug': {
95+
device: 'attached',
96+
app: 'android.debug',
97+
},
98+
'android.att.release': {
99+
device: 'attached',
100+
app: 'android.release',
101+
},
102+
'android.emu.debug': {
103+
device: 'emulator',
104+
app: 'android.debug',
105+
},
106+
'android.emu.release': {
107+
device: 'emulator',
108+
app: 'android.release',
109+
},
110+
'ci.android': {
111+
device: 'ci.emulator',
112+
app: 'ci.android',
113+
},
114+
'ci.sim': {
115+
device: 'ci.simulator',
116+
app: 'ci.ios',
117+
},
118+
},
119+
};

samples/react-native/android/app/build.gradle

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,10 @@ android {
139139
versionCode 39
140140
versionName "6.7.0-alpha.0"
141141
buildConfigField "boolean", "SENTRY_DISABLE_NATIVE_START", System.getenv('SENTRY_DISABLE_NATIVE_START') ?: String.valueOf(sentryDisableNativeStart)
142+
143+
// Detox
144+
testBuildType System.getProperty('testBuildType', 'debug')
145+
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
142146
}
143147

144148
signingConfigs {
@@ -193,11 +197,15 @@ android {
193197
signingConfig signingConfigs.debug
194198
minifyEnabled enableProguardInReleaseBuilds
195199
proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
200+
proguardFile "${rootProject.projectDir}/../node_modules/detox/android/detox/proguard-rules-app.pro"
196201
}
197202
}
198203
}
199204

200205
dependencies {
206+
androidTestImplementation('com.wix:detox:+')
207+
implementation 'androidx.appcompat:appcompat:1.7.0'
208+
201209
// The version of react-native is set by the React Native Gradle Plugin
202210
implementation("com.facebook.react:react-android")
203211

samples/react-native/android/app/proguard-rules.pro

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,7 @@
88
# http://developer.android.com/guide/developing/tools/proguard.html
99

1010
# Add any project specific keep options here:
11+
12+
# Detox Release tests were failing on missing kotlin.Result
13+
# It should be covered by node_modules/detox/android/detox/proguard-rules-app.pro but it seems missing
14+
-keep class kotlin.** { *; }
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package io.sentry.reactnative.sample;
2+
3+
import androidx.test.ext.junit.runners.AndroidJUnit4;
4+
import androidx.test.filters.LargeTest;
5+
import androidx.test.rule.ActivityTestRule;
6+
import com.wix.detox.Detox;
7+
import com.wix.detox.config.DetoxConfig;
8+
import org.junit.Rule;
9+
import org.junit.Test;
10+
import org.junit.runner.RunWith;
11+
12+
@RunWith(AndroidJUnit4.class)
13+
@LargeTest
14+
public class DetoxTest {
15+
@Rule
16+
public ActivityTestRule<MainActivity> mActivityRule =
17+
new ActivityTestRule<>(MainActivity.class, false, false);
18+
19+
@Test
20+
public void runDetoxTests() {
21+
DetoxConfig detoxConfig = new DetoxConfig();
22+
detoxConfig.idlePolicyConfig.masterTimeoutSec = 90;
23+
detoxConfig.idlePolicyConfig.idleResourceTimeoutSec = 60;
24+
detoxConfig.rnContextLoadTimeoutSec = (BuildConfig.DEBUG ? 180 : 60);
25+
26+
Detox.runTests(mActivityRule, detoxConfig);
27+
}
28+
}

samples/react-native/android/app/src/main/AndroidManifest.xml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@
99
android:roundIcon="@mipmap/ic_launcher_round"
1010
android:allowBackup="false"
1111
android:theme="@style/AppTheme"
12-
android:supportsRtl="true">
12+
android:supportsRtl="true"
13+
android:networkSecurityConfig="@xml/network_security_config">
1314
<activity
1415
android:name=".MainActivity"
1516
android:label="@string/app_name"

0 commit comments

Comments
 (0)