Skip to content

Commit 70e349c

Browse files
authored
Merge pull request #1180 from Instabug/dev
Release:v12.9.0
2 parents ee7f33d + 430c088 commit 70e349c

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

57 files changed

+1936
-138
lines changed

.circleci/config.yml

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
version: 2.1
22

33
orbs:
4-
android: circleci/[email protected]
4+
android: circleci/android@2.5.0
55
advanced-checkout: vsco/[email protected]
6-
node: circleci/node@5.1.0
6+
node: circleci/node@5.2.0
77

88
references:
99
release_dependencies: &release_dependencies
@@ -26,7 +26,7 @@ commands:
2626
steps:
2727
- node/install:
2828
install-yarn: true
29-
node-version: 'v18.17.0'
29+
node-version: 'v20.11.1'
3030
- node/install-packages:
3131
pkg-manager: yarn
3232
# Network concurrency is set to 1 for installation from GitHub to work.
@@ -113,13 +113,13 @@ jobs:
113113
test_android:
114114
executor:
115115
name: android/android-machine
116-
tag: '2022.03.1'
116+
tag: default
117117
working_directory: ~/project/examples/default
118118
environment:
119119
INSTABUG_SOURCEMAPS_UPLOAD_DISABLE: true
120120
steps:
121121
- advanced-checkout/shallow-checkout
122-
- node/install-yarn
122+
# - node/install-yarn
123123
- install_node_modules
124124
- android/run-tests:
125125
working-directory: android
@@ -227,13 +227,13 @@ jobs:
227227
e2e_android:
228228
executor:
229229
name: android/android-machine
230-
tag: 2022.03.1
230+
tag: default
231231
resource-class: large
232232
environment:
233233
INSTABUG_SOURCEMAPS_UPLOAD_DISABLE: true
234234
steps:
235235
- advanced-checkout/shallow-checkout
236-
- node/install-yarn
236+
# - node/install-yarn
237237
- install_node_modules
238238
- node/install-packages:
239239
pkg-manager: yarn

CHANGELOG.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,16 @@
11
# Changelog
22

3-
## [Unreleased](https://github.com/Instabug/Instabug-React-Native/compare/v12.8.0...dev)
3+
## [12.9.0](https://github.com/Instabug/Instabug-React-Native/compare/v12.8.0...dev)(April 2, 2024)
4+
5+
### Added
6+
7+
- Adds symbol files upload script ([#1137](https://github.com/Instabug/Instabug-React-Native/pull/1137))
8+
- Support enabling NDK crash capturing on Android ([#1132](https://github.com/Instabug/Instabug-React-Native/pull/1132)).
9+
10+
### Changed
11+
12+
- Bump Instabug Android SDK to v12.9.0 ([#1168](https://github.com/Instabug/Instabug-React-Native/pull/1168)). [See release notes](https://github.com/Instabug/android/releases/tag/v12.9.0).
13+
- Bump Instabug iOS SDK to v12.9.0 ([#1168](https://github.com/Instabug/Instabug-React-Native/pull/1168)). [See release notes](https://github.com/instabug/instabug-ios/releases/tag/12.9.0).
414

515
### Fixed
616

android/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ android {
5757
minSdkVersion getExtOrDefault('minSdkVersion').toInteger()
5858
targetSdkVersion getExtOrDefault('targetSdkVersion').toInteger()
5959
versionCode 1
60-
versionName "12.8.0"
60+
versionName "12.9.0"
6161
multiDexEnabled true
6262
ndk {
6363
abiFilters "armeabi-v7a", "x86"

android/native.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
project.ext.instabug = [
2-
version: '12.8.0'
2+
version: '12.9.0'
33
]
44

55
dependencies {

android/src/main/java/com/instabug/reactlibrary/RNInstabugAPMModule.java

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@ public void run() {
220220
}
221221

222222
/**
223-
* Send Apm network log by Reflection
223+
* Send Apm network log by Reflection
224224
*/
225225
@ReactMethod
226226
public void networkLog(String networkData) throws JSONException {
@@ -242,8 +242,8 @@ public void networkLog(String networkData) throws JSONException {
242242
final Integer statusCode = (Integer) jsonObject.get("responseCode");
243243
final long requestDuration = ((Number) jsonObject.get("duration")).longValue();
244244
final long requestStartTime = ((Number) jsonObject.get("startTime")).longValue() * 1000;
245-
final String requestHeaders = (String) jsonObject.get("requestHeaders").toString();
246-
final String responseHeaders = (String) jsonObject.get("responseHeaders").toString();
245+
final String requestHeaders = (String) jsonObject.get("requestHeaders").toString();
246+
final String responseHeaders = (String) jsonObject.get("responseHeaders").toString();
247247
final String errorMessage;
248248
if(errorDomain.equals("")) {
249249
errorMessage = null;
@@ -254,25 +254,21 @@ public void networkLog(String networkData) throws JSONException {
254254
String gqlQueryName = null;
255255
if(jsonObject.has("gqlQueryName")){
256256
gqlQueryName = (String) jsonObject.get("gqlQueryName");
257-
}
257+
}
258258
final String serverErrorMessage = (String) jsonObject.get("serverErrorMessage");
259-
259+
260260
try {
261261
Method method = getMethod(Class.forName("com.instabug.apm.networking.APMNetworkLogger"), "log", long.class, long.class, String.class, String.class, long.class, String.class, String.class, String.class, String.class, String.class, long.class, int.class, String.class, String.class, String.class, String.class);
262262
if (method != null) {
263263
method.invoke(apmNetworkLogger, requestStartTime, requestDuration, requestHeaders, requestBody, requestBodySize, requestMethod, requestUrl, requestContentType, responseHeaders, responseBody, responseBodySize, statusCode, responseContentType, errorMessage, gqlQueryName, serverErrorMessage);
264264
} else {
265265
Log.e("IB-CP-Bridge", "apmNetworkLogByReflection was not found by reflection");
266266
}
267-
} catch (ClassNotFoundException e) {
268-
e.printStackTrace();
269-
} catch (IllegalAccessException e) {
270-
e.printStackTrace();
271-
} catch (InvocationTargetException e) {
267+
} catch (Throwable e) {
272268
e.printStackTrace();
273269
}
274270
}
275-
catch(Exception e) {
271+
catch(Throwable e) {
276272
e.printStackTrace();
277273
}
278274
}

android/src/main/java/com/instabug/reactlibrary/RNInstabugCrashReportingModule.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,28 @@ public void run() {
113113
}
114114
}
115115
});
116+
}
116117

118+
/**
119+
* Enables and disables capturing native C++ NDK crash reporting.
120+
*
121+
* @param isEnabled boolean indicating enabled or disabled.
122+
*/
123+
@ReactMethod
124+
public void setNDKCrashesEnabled(final boolean isEnabled) {
125+
MainThreadHandler.runOnMainThread(new Runnable() {
126+
@Override
127+
public void run() {
128+
try {
129+
if (isEnabled) {
130+
CrashReporting.setNDKCrashesState(Feature.State.ENABLED);
131+
} else {
132+
CrashReporting.setNDKCrashesState(Feature.State.DISABLED);
133+
}
134+
} catch (Exception e) {
135+
e.printStackTrace();
136+
}
137+
}
138+
});
117139
}
118140
}

android/src/test/java/com/instabug/reactlibrary/RNInstabugCrashReportingModuleTest.java

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,85 @@
11
package com.instabug.reactlibrary;
22

3+
import static org.mockito.ArgumentMatchers.any;
4+
import static org.mockito.Mockito.mock;
5+
import static org.mockito.Mockito.mockStatic;
6+
7+
import android.os.Looper;
8+
9+
import com.instabug.crash.CrashReporting;
10+
import com.instabug.library.Feature;
11+
import com.instabug.reactlibrary.util.GlobalMocks;
12+
import com.instabug.reactlibrary.utils.MainThreadHandler;
13+
14+
import org.junit.After;
15+
import org.junit.Before;
316
import org.junit.Test;
17+
import org.mockito.MockedStatic;
18+
import org.mockito.Mockito;
19+
import org.mockito.invocation.InvocationOnMock;
20+
import org.mockito.stubbing.Answer;
421

522

623
public class RNInstabugCrashReportingModuleTest {
24+
private final RNInstabugCrashReportingModule rnModule = new RNInstabugCrashReportingModule(null);
25+
26+
// Mock Objects
27+
private MockedStatic<Looper> mockLooper;
28+
private MockedStatic<MainThreadHandler> mockMainThreadHandler;
29+
private MockedStatic<CrashReporting> mockCrashReporting;
30+
31+
32+
@Before
33+
public void mockMainThreadHandler() throws Exception {
34+
// Mock static functions
35+
mockLooper = mockStatic(Looper.class);
36+
mockMainThreadHandler = mockStatic(MainThreadHandler.class);
37+
mockCrashReporting = mockStatic(CrashReporting.class);
38+
// Mock Looper class
39+
Looper mockMainThreadLooper = mock(Looper.class);
40+
Mockito.when(Looper.getMainLooper()).thenReturn(mockMainThreadLooper);
41+
42+
43+
// Override runOnMainThread
44+
Answer<Boolean> handlerPostAnswer = new Answer<Boolean>() {
45+
@Override
46+
public Boolean answer(InvocationOnMock invocation) throws Throwable {
47+
invocation.getArgument(0, Runnable.class).run();
48+
return true;
49+
}
50+
};
51+
Mockito.doAnswer(handlerPostAnswer).when(MainThreadHandler.class);
52+
MainThreadHandler.runOnMainThread(any(Runnable.class));
53+
}
54+
55+
@After
56+
public void tearDown() {
57+
// Remove static mocks
58+
mockLooper.close();
59+
mockMainThreadHandler.close();
60+
mockCrashReporting.close();
61+
}
62+
63+
/********Crashes*********/
64+
65+
@Test
66+
public void testSetNDKCrashesEnabledGivenTrue() {
67+
// when
68+
rnModule.setNDKCrashesEnabled(true);
69+
70+
//then
71+
mockCrashReporting.verify(() -> CrashReporting.setNDKCrashesState(Feature.State.ENABLED));
72+
}
73+
74+
@Test
75+
public void testSetNDKCrashesEnabledGivenFalse() {
76+
// when
77+
rnModule.setNDKCrashesEnabled(false);
78+
79+
//then
80+
mockCrashReporting.verify(() -> CrashReporting.setNDKCrashesState(Feature.State.DISABLED));
81+
}
82+
783
@Test
884
public void givenString$sendHandledJSCrash_whenQuery_thenShouldCallNativeApiWithArgs() throws Exception {
985
// JSONObject json = mock(JSONObject.class);

android/src/test/java/com/instabug/reactlibrary/RNInstabugRepliesModuleTest.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import com.facebook.react.bridge.WritableMap;
1111
import com.instabug.chat.Replies;
1212
import com.instabug.library.Feature;
13+
import com.instabug.reactlibrary.utils.InstabugUtil;
1314
import com.instabug.reactlibrary.utils.MapUtil;
1415
import com.instabug.reactlibrary.utils.MainThreadHandler;
1516

@@ -42,13 +43,15 @@ public class RNInstabugRepliesModuleTest {
4243
private MockedStatic<Looper> mockLooper;
4344
private MockedStatic <MainThreadHandler> mockMainThreadHandler;
4445
private MockedStatic <Replies> mockReplies;
46+
private MockedStatic <InstabugUtil> mockInstabugUtil;
4547

4648
@Before
4749
public void mockMainThreadHandler() throws Exception {
4850
// Mock static functions
4951
mockReplies = mockStatic(Replies.class);
5052
mockLooper = mockStatic(Looper.class);
5153
mockMainThreadHandler = mockStatic(MainThreadHandler.class);
54+
mockInstabugUtil = mockStatic(InstabugUtil.class);
5255

5356
// Mock Looper class
5457
Looper mockMainThreadLooper = mock(Looper.class);
@@ -71,6 +74,7 @@ public void tearDown() {
7174
mockLooper.close();
7275
mockMainThreadHandler.close();
7376
mockReplies.close();
77+
mockInstabugUtil.close();
7478
}
7579

7680
/********Replies*********/

cli/UploadSoFiles.ts

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
import axios from 'axios';
2+
import { Command, Option } from 'commander';
3+
import FormData from 'form-data';
4+
import fs from 'fs';
5+
6+
interface UploadSoFilesOptions {
7+
arch: 'x86' | 'x86_64' | 'arm64-v8a' | 'armeabi-v7a';
8+
file: string;
9+
token: string;
10+
name: string;
11+
api_key: string;
12+
}
13+
/**
14+
* This script uploads .so files to the specified endpoint used in NDK crash reporting.
15+
* Usage: node upload-so-files.js --arch <arch> --file <path> --api_key <key> --token <token> --name <name>
16+
*/
17+
18+
export const UploadSoFilesCommand = new Command();
19+
20+
UploadSoFilesCommand.name('upload-so-files')
21+
.addOption(
22+
new Option('-arch, --arch <value>', 'arch')
23+
.choices(['x86', 'x86_64', 'arm64-v8a', 'armeabi-v7a'])
24+
.makeOptionMandatory(),
25+
)
26+
.addOption(
27+
new Option(
28+
'-f, --file <path>',
29+
'The path of the symbol files in Zip format',
30+
).makeOptionMandatory(),
31+
)
32+
.addOption(new Option('--api_key <value>', 'Your App key').makeOptionMandatory())
33+
.addOption(
34+
new Option('-t, --token <value>', 'Your App Token')
35+
.env('INSTABUG_APP_TOKEN')
36+
.makeOptionMandatory(),
37+
)
38+
.addOption(
39+
new Option('-n, --name <value>', 'The app version name')
40+
.env('INSTABUG_APP_VERSION_NAME')
41+
.makeOptionMandatory(),
42+
)
43+
.action(function (this: Command) {
44+
const options = this.opts<UploadSoFilesOptions>();
45+
UploadSoFiles(options);
46+
})
47+
.showHelpAfterError();
48+
49+
const UploadSoFiles = async (opts: UploadSoFilesOptions) => {
50+
const fileName = opts.file;
51+
if (fileName == null) {
52+
console.error('Failed to upload So Files: invalid file path');
53+
process.exit(1);
54+
}
55+
56+
if (fs.existsSync(fileName) === false) {
57+
console.error('Failed to upload So Files: File not found');
58+
process.exit(1);
59+
}
60+
var fileExt = fileName.split('.').pop();
61+
62+
if (fileExt !== 'zip') {
63+
console.error('Failed to upload So Files: You can only upload ZIP files');
64+
process.exit(1);
65+
}
66+
67+
const fileBlob = fs.readFileSync(opts.file);
68+
69+
const form = new FormData();
70+
form.append('app_version', opts.name);
71+
form.append('so_file', fileBlob, fileName);
72+
form.append('application_token', opts.token);
73+
form.append('api_key', opts.api_key);
74+
form.append('arch', opts.arch);
75+
76+
console.log('Uploading So files...');
77+
const uploadEndpoint = 'https://api.instabug.com/api/web/public/so_files';
78+
try {
79+
await axios.post(uploadEndpoint, form, {
80+
headers: form.getHeaders(),
81+
});
82+
83+
console.log(`Successfully uploaded So Files for version: ${opts.name} with arch ${opts.arch}`);
84+
} catch (err) {
85+
console.error('Failed to upload So Files:', axios.isAxiosError(err) ? err.response?.data : err);
86+
process.exit(1);
87+
}
88+
};

cli/index.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import { Command } from 'commander';
33

44
import { uploadSourcemapsCommand } from './UploadSourcemaps';
5+
import { UploadSoFilesCommand } from './UploadSoFiles';
56

67
const program = new Command();
78

@@ -10,6 +11,7 @@ program
1011
.version('1.0.0-beta1')
1112
.description('A CLI for uploading source maps to Instabug dashboard.')
1213
.usage('[command]')
13-
.addCommand(uploadSourcemapsCommand);
14+
.addCommand(uploadSourcemapsCommand)
15+
.addCommand(UploadSoFilesCommand);
1416

1517
program.parse(process.argv);

examples/default/.env

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
GOOGLE_MAPS_API_KEY = API_KEY

0 commit comments

Comments
 (0)