Skip to content

Commit 9757ab5

Browse files
Merge branch 'main' into feat-screenshots
2 parents 5b1dc60 + 4835cf8 commit 9757ab5

File tree

9 files changed

+173
-54
lines changed

9 files changed

+173
-54
lines changed

CHANGELOG.md

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

3-
## Unreleased
3+
## 4.10.1
44

55
### Features
66

@@ -9,6 +9,8 @@
99
### Fixes
1010

1111
- Android builds without ext config, auto create assets dir for modules ([#2652](https://github.com/getsentry/sentry-react-native/pull/2652))
12+
- Exit gracefully if source map file for collecting modules doesn't exist ([#2655](https://github.com/getsentry/sentry-react-native/pull/2655))
13+
- Create only one clean-up tasks for modules collection ([#2657](https://github.com/getsentry/sentry-react-native/pull/2657))
1214

1315
### Dependencies
1416

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "@sentry/react-native",
33
"homepage": "https://github.com/getsentry/sentry-react-native",
44
"repository": "https://github.com/getsentry/sentry-react-native",
5-
"version": "4.10.0",
5+
"version": "4.10.1",
66
"description": "Official Sentry SDK for react-native",
77
"typings": "dist/js/index.d.ts",
88
"types": "dist/js/index.d.ts",

scripts/collect-modules.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,4 +40,4 @@ else
4040
modulesPaths="$MODULES_PATHS"
4141
fi
4242

43-
$nodePath $collectModulesScript $sourceMap $modulesOutput $modulesPaths
43+
$nodePath "$collectModulesScript" "$sourceMap" "$modulesOutput" "$modulesPaths"

sentry.gradle

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -194,19 +194,24 @@ gradle.projectsEvaluated {
194194
}
195195
previousCliTask = cliTask
196196
cliTask.finalizedBy modulesTask
197+
}
197198

198-
def modulesCleanUpTask = tasks.create(name: nameModulesCleanup, type: Delete) {
199-
description = "clean up collected modules generated file"
200-
group = 'sentry.io'
199+
def modulesCleanUpTask = tasks.create(name: nameModulesCleanup, type: Delete) {
200+
description = "clean up collected modules generated file"
201+
group = 'sentry.io'
201202

202-
delete modulesOutput
203-
}
203+
delete modulesOutput
204+
}
204205

205-
def packageTasks = tasks.findAll { task -> "package${variant}".equalsIgnoreCase(task.name) && task.enabled }
206-
packageTasks.each { packageTask ->
207-
packageTask.dependsOn modulesTask
208-
packageTask.finalizedBy modulesCleanUpTask
209-
}
206+
def variantTaskName = variant.replaceAll("[\\s\\-()]", "") // variant is dev-release beta-release etc.
207+
// task.name could be packageDev-debugRelease but in that case currentVariants == null
208+
// because of the regex in `extractCurrentVariants` and this code doesn't run
209+
def packageTasks = tasks.findAll {
210+
task -> "package${variantTaskName}".equalsIgnoreCase(task.name) && task.enabled
211+
}
212+
packageTasks.each { packageTask ->
213+
packageTask.dependsOn modulesTask
214+
packageTask.finalizedBy modulesCleanUpTask
210215
}
211216

212217
/** Delete sourcemap files */

src/js/tools/ModulesCollector.ts

Lines changed: 72 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
import { logger } from '@sentry/utils';
2-
import { existsSync, readFileSync } from 'fs';
2+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';
33
import { posix, sep } from 'path';
4+
5+
logger.enable();
6+
47
const { dirname, join, resolve, sep: posixSep } = posix;
58

69
interface Package {
@@ -14,13 +17,17 @@ interface Package {
1417
export default class ModulesCollector {
1518

1619
/** Collect method */
17-
public static collect(sources: string[], modulesPaths: string[]): Record<string, string> {
20+
public static collect(sources: unknown[], modulesPaths: string[]): Record<string, string> {
1821
const normalizedModulesPaths = modulesPaths.map((modulesPath) => resolve(modulesPath.split(sep).join(posixSep)));
1922

2023
const infos: Record<string, string> = {};
2124
const seen: Record<string, true> = {};
2225

23-
sources.forEach((path: string) => {
26+
sources.forEach((path: unknown) => {
27+
if (typeof path !== 'string') {
28+
return;
29+
}
30+
2431
let dir = path; // included source file path
2532
let candidate: Package | null = null;
2633

@@ -60,7 +67,7 @@ export default class ModulesCollector {
6067
version: info.version,
6168
};
6269
} catch (error) {
63-
logger.warn(`Failed to read ${pkgPath}`);
70+
logger.error(`Failed to read ${pkgPath}`);
6471
}
6572

6673
return upDirSearch(); // processed package.json file, continue up search
@@ -72,4 +79,65 @@ export default class ModulesCollector {
7279
return infos;
7380
}
7481

82+
/**
83+
* Runs collection of modules.
84+
*/
85+
public static run({
86+
sourceMapPath,
87+
outputModulesPath,
88+
modulesPaths,
89+
collect,
90+
}: Partial<{
91+
sourceMapPath: string,
92+
outputModulesPath: string,
93+
modulesPaths: string[],
94+
collect: (sources: unknown[], modulesPaths: string[]) => Record<string, string>,
95+
}>): void {
96+
if (!sourceMapPath) {
97+
logger.error('First argument `source-map-path` is missing!');
98+
return;
99+
}
100+
if (!outputModulesPath) {
101+
logger.error('Second argument `modules-output-path` is missing!');
102+
return;
103+
}
104+
if (!modulesPaths || modulesPaths.length === 0) {
105+
logger.error('Third argument `modules-paths` is missing!');
106+
return;
107+
}
108+
109+
logger.info('Reading source map from', sourceMapPath);
110+
logger.info('Saving modules to', outputModulesPath);
111+
logger.info('Resolving modules from paths', outputModulesPath);
112+
113+
if (!existsSync(sourceMapPath)) {
114+
logger.error(`Source map file does not exist at ${sourceMapPath}`);
115+
return;
116+
}
117+
for (const modulesPath of modulesPaths) {
118+
if (!existsSync(modulesPath)) {
119+
logger.error(`Modules path does not exist at ${modulesPath}`);
120+
return;
121+
}
122+
}
123+
124+
const map: { sources?: unknown } = JSON.parse(readFileSync(sourceMapPath, 'utf8'));
125+
if (!map.sources || !Array.isArray(map.sources)) {
126+
logger.error(`Modules not collected. No sources found in the source map (${sourceMapPath})!`);
127+
return;
128+
}
129+
130+
const sources: unknown[] = map.sources;
131+
const modules = collect
132+
? collect(sources, modulesPaths)
133+
: ModulesCollector.collect(sources, modulesPaths);
134+
135+
const outputModulesDirPath = dirname(outputModulesPath);
136+
if (!existsSync(outputModulesDirPath)) {
137+
mkdirSync(outputModulesDirPath, { recursive: true });
138+
}
139+
writeFileSync(outputModulesPath, JSON.stringify(modules, null, 2));
140+
logger.info(`Modules collected and saved to: ${outputModulesPath}`);
141+
}
142+
75143
}

src/js/tools/collectModules.ts

Lines changed: 7 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,12 @@
1-
import { logger } from '@sentry/utils';
2-
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';
3-
import { dirname } from 'path';
4-
import { argv, exit } from 'process';
1+
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
2+
import { argv } from 'process';
53

64
import ModulesCollector from './ModulesCollector';
75

8-
const sourceMapPath: string | undefined = argv[2]; // eslint-disable-line @typescript-eslint/no-unsafe-member-access
9-
const outputModulesPath: string | undefined = argv[3]; // eslint-disable-line @typescript-eslint/no-unsafe-member-access
10-
const modulesPaths: string[] = argv[4] // eslint-disable-line @typescript-eslint/no-unsafe-member-access
11-
? argv[4].split(',') // eslint-disable-line @typescript-eslint/no-unsafe-member-access
6+
const sourceMapPath: string | undefined = argv[2];
7+
const outputModulesPath: string | undefined = argv[3];
8+
const modulesPaths: string[] = argv[4]
9+
? argv[4].split(',')
1210
: [];
1311

14-
if (!sourceMapPath) {
15-
exitGracefully('First argument `source-map-path` is missing!');
16-
}
17-
if (!outputModulesPath) {
18-
exitGracefully('Second argument `modules-output-path` is missing!');
19-
}
20-
if (modulesPaths.length === 0) {
21-
exitGracefully('Third argument `modules-paths` is missing!');
22-
}
23-
24-
const map: { sources?: string[] } = JSON.parse(readFileSync(sourceMapPath, 'utf8'));
25-
if (!map.sources) {
26-
exitGracefully(`Modules not collected. No sources found in the source map (${sourceMapPath})!`);
27-
}
28-
29-
const sources: string[] = map.sources;
30-
const modules = ModulesCollector.collect(sources, modulesPaths);
31-
32-
const outputModulesDirPath = dirname(outputModulesPath);
33-
if (!existsSync(outputModulesDirPath)) {
34-
mkdirSync(outputModulesDirPath, { recursive: true });
35-
}
36-
writeFileSync(outputModulesPath, JSON.stringify(modules, null, 2));
37-
38-
function exitGracefully(message: string): never {
39-
logger.error(message);
40-
exit(0);
41-
};
12+
ModulesCollector.run({ sourceMapPath, outputModulesPath, modulesPaths });

src/js/version.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
export const SDK_PACKAGE_NAME = 'npm:@sentry/react-native';
22
export const SDK_NAME = 'sentry.javascript.react-native';
3-
export const SDK_VERSION = '4.10.0';
3+
export const SDK_VERSION = '4.10.1';

test/tools/collectModules.test.ts

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
import { existsSync, readFileSync, rmdirSync,unlinkSync } from 'fs';
2+
import { dirname } from 'path';
3+
14
import ModulesCollector from '../../src/js/tools/ModulesCollector';
25

36
describe('collectModules', () => {
@@ -42,4 +45,71 @@ describe('collectModules', () => {
4245
'module-2': 'unknown'
4346
});
4447
});
48+
49+
test('should skip non string source value', () => {
50+
const modules = ModulesCollector.collect(
51+
[1, {}],
52+
[
53+
`${__dirname}/fixtures/root-module/modules`,
54+
],
55+
);
56+
57+
expect(modules).toEqual({});
58+
});
59+
60+
test('should gracefully return if source map does not exist', () => {
61+
const mockCollect = jest.fn().mockReturnValue({});
62+
ModulesCollector.run({
63+
sourceMapPath: 'not-exist',
64+
outputModulesPath: `${__dirname}/fixtures/mock.json`,
65+
modulesPaths: [
66+
`${__dirname}/fixtures/root-module/modules`,
67+
],
68+
collect: mockCollect,
69+
});
70+
71+
expect(mockCollect).not.toHaveBeenCalled();
72+
});
73+
74+
test('should gracefully return if one of the modules paths does not exist', () => {
75+
const mockCollect = jest.fn().mockReturnValue({});
76+
ModulesCollector.run({
77+
sourceMapPath: `${__dirname}/fixtures/mock.map`,
78+
outputModulesPath: `${__dirname}/fixtures/mock.json`,
79+
modulesPaths: [
80+
`${__dirname}/fixtures/root-module/modules`,
81+
'not-exist',
82+
],
83+
collect: mockCollect,
84+
});
85+
86+
expect(mockCollect).not.toHaveBeenCalled();
87+
});
88+
89+
describe('write output json', () => {
90+
const outputModulesPath = `${__dirname}/assets/output.json`;
91+
92+
const cleanUp = () => {
93+
if (existsSync(outputModulesPath)) {
94+
unlinkSync(outputModulesPath);
95+
rmdirSync(dirname(outputModulesPath));
96+
}
97+
};
98+
99+
beforeEach(cleanUp);
100+
afterEach(cleanUp);
101+
102+
test('should write output to file', () => {
103+
ModulesCollector.run({
104+
sourceMapPath: `${__dirname}/fixtures/mock.map`,
105+
outputModulesPath,
106+
modulesPaths: [
107+
`${__dirname}/fixtures/root-module/modules`,
108+
],
109+
});
110+
111+
expect(existsSync(outputModulesPath)).toEqual(true);
112+
expect(readFileSync(outputModulesPath, 'utf8')).toEqual('{}');
113+
});
114+
});
45115
});

test/tools/fixtures/mock.map

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"sources": []
3+
}

0 commit comments

Comments
 (0)