@sentry/wizard 3.7.1 → 3.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +21 -0
- package/bin.ts +14 -0
- package/dist/bin.js +9 -0
- package/dist/bin.js.map +1 -1
- package/dist/lib/Helper/Logging.d.ts +1 -0
- package/dist/lib/Helper/Logging.js +2 -1
- package/dist/lib/Helper/Logging.js.map +1 -1
- package/dist/lib/Helper/__tests__/MergeConfig.js.map +1 -1
- package/dist/lib/Setup.js +4 -0
- package/dist/lib/Setup.js.map +1 -1
- package/dist/lib/Steps/ChooseIntegration.js +12 -26
- package/dist/lib/Steps/ChooseIntegration.js.map +1 -1
- package/dist/lib/Steps/Integrations/Cordova.js.map +1 -1
- package/dist/lib/Steps/Integrations/Electron.js.map +1 -1
- package/dist/lib/Steps/Integrations/MobileProject.js.map +1 -1
- package/dist/lib/Steps/Integrations/ReactNative.js +5 -5
- package/dist/lib/Steps/Integrations/ReactNative.js.map +1 -1
- package/dist/lib/Steps/Integrations/__tests__/ReactNative.js +5 -6
- package/dist/lib/Steps/Integrations/__tests__/ReactNative.js.map +1 -1
- package/dist/package.json +11 -7
- package/dist/src/apple/apple-wizard.js +31 -2
- package/dist/src/apple/apple-wizard.js.map +1 -1
- package/dist/src/apple/cocoapod.d.ts +2 -0
- package/dist/src/apple/cocoapod.js +122 -0
- package/dist/src/apple/cocoapod.js.map +1 -0
- package/dist/src/apple/code-tools.js +22 -12
- package/dist/src/apple/code-tools.js.map +1 -1
- package/dist/src/apple/fastlane.d.ts +2 -0
- package/dist/src/apple/fastlane.js +179 -0
- package/dist/src/apple/fastlane.js.map +1 -0
- package/dist/src/apple/templates.d.ts +1 -0
- package/dist/src/apple/templates.js +7 -3
- package/dist/src/apple/templates.js.map +1 -1
- package/dist/src/apple/xcode-manager.d.ts +1 -1
- package/dist/src/apple/xcode-manager.js +35 -28
- package/dist/src/apple/xcode-manager.js.map +1 -1
- package/dist/src/nextjs/nextjs-wizard.js +71 -81
- package/dist/src/nextjs/nextjs-wizard.js.map +1 -1
- package/dist/src/sourcemaps/sourcemaps-wizard.js +61 -46
- package/dist/src/sourcemaps/sourcemaps-wizard.js.map +1 -1
- package/dist/src/sourcemaps/tools/nextjs.d.ts +3 -0
- package/dist/src/sourcemaps/tools/nextjs.js +135 -0
- package/dist/src/sourcemaps/tools/nextjs.js.map +1 -0
- package/dist/src/sourcemaps/tools/sentry-cli.js +120 -16
- package/dist/src/sourcemaps/tools/sentry-cli.js.map +1 -1
- package/dist/src/sourcemaps/tools/vite.js +102 -12
- package/dist/src/sourcemaps/tools/vite.js.map +1 -1
- package/dist/src/sourcemaps/utils/detect-tool.d.ts +1 -1
- package/dist/src/sourcemaps/utils/detect-tool.js +1 -0
- package/dist/src/sourcemaps/utils/detect-tool.js.map +1 -1
- package/dist/src/sourcemaps/utils/other-wizards.js +35 -12
- package/dist/src/sourcemaps/utils/other-wizards.js.map +1 -1
- package/dist/src/sveltekit/sdk-setup.d.ts +9 -1
- package/dist/src/sveltekit/sdk-setup.js +73 -29
- package/dist/src/sveltekit/sdk-setup.js.map +1 -1
- package/dist/src/sveltekit/sveltekit-wizard.js +23 -13
- package/dist/src/sveltekit/sveltekit-wizard.js.map +1 -1
- package/dist/src/utils/ast-utils.d.ts +8 -0
- package/dist/src/utils/ast-utils.js +45 -0
- package/dist/src/utils/ast-utils.js.map +1 -0
- package/dist/src/utils/bash.d.ts +2 -1
- package/dist/src/utils/bash.js +14 -2
- package/dist/src/utils/bash.js.map +1 -1
- package/dist/src/utils/clack-utils.d.ts +7 -14
- package/dist/src/utils/clack-utils.js +46 -2
- package/dist/src/utils/clack-utils.js.map +1 -1
- package/dist/src/utils/debug.d.ts +2 -0
- package/dist/src/utils/debug.js +51 -0
- package/dist/src/utils/debug.js.map +1 -0
- package/dist/src/utils/package-json.d.ts +1 -1
- package/dist/src/utils/package-json.js.map +1 -1
- package/dist/src/utils/types.d.ts +24 -0
- package/dist/src/utils/types.js.map +1 -1
- package/dist/test/utils/ast-utils.test.d.ts +1 -0
- package/dist/test/utils/ast-utils.test.js +21 -0
- package/dist/test/utils/ast-utils.test.js.map +1 -0
- package/lib/Helper/Logging.ts +1 -1
- package/lib/Helper/__tests__/MergeConfig.ts +9 -4
- package/lib/Setup.ts +5 -0
- package/lib/Steps/ChooseIntegration.ts +13 -3
- package/lib/Steps/Integrations/Cordova.ts +3 -3
- package/lib/Steps/Integrations/Electron.ts +1 -2
- package/lib/Steps/Integrations/MobileProject.ts +1 -1
- package/lib/Steps/Integrations/ReactNative.ts +23 -17
- package/lib/Steps/Integrations/__tests__/ReactNative.ts +24 -15
- package/package.json +11 -7
- package/src/apple/apple-wizard.ts +35 -3
- package/src/apple/cocoapod.ts +57 -0
- package/src/apple/code-tools.ts +80 -57
- package/src/apple/fastlane.ts +160 -0
- package/src/apple/templates.ts +26 -10
- package/src/apple/xcode-manager.ts +137 -120
- package/src/nextjs/nextjs-wizard.ts +4 -13
- package/src/sourcemaps/sourcemaps-wizard.ts +40 -28
- package/src/sourcemaps/tools/nextjs.ts +114 -0
- package/src/sourcemaps/tools/sentry-cli.ts +134 -8
- package/src/sourcemaps/tools/vite.ts +101 -12
- package/src/sourcemaps/utils/detect-tool.ts +3 -1
- package/src/sourcemaps/utils/other-wizards.ts +32 -13
- package/src/sveltekit/sdk-setup.ts +122 -43
- package/src/sveltekit/sveltekit-wizard.ts +15 -6
- package/src/utils/ast-utils.ts +20 -0
- package/src/utils/bash.ts +43 -30
- package/src/utils/clack-utils.ts +42 -14
- package/src/utils/debug.ts +20 -0
- package/src/utils/package-json.ts +1 -1
- package/src/utils/types.ts +22 -0
- package/test/utils/ast-utils.test.ts +44 -0
- package/dist/src/sveltekit/sentry-cli-setup.d.ts +0 -2
- package/dist/src/sveltekit/sentry-cli-setup.js +0 -71
- package/dist/src/sveltekit/sentry-cli-setup.js.map +0 -1
- package/package-lock.json +0 -8910
- package/src/sveltekit/sentry-cli-setup.ts +0 -27
package/src/apple/code-tools.ts
CHANGED
|
@@ -3,79 +3,102 @@ import * as path from 'path';
|
|
|
3
3
|
import * as templates from './templates';
|
|
4
4
|
import * as Sentry from '@sentry/node';
|
|
5
5
|
|
|
6
|
-
const swiftAppLaunchRegex =
|
|
7
|
-
|
|
6
|
+
const swiftAppLaunchRegex =
|
|
7
|
+
/(func\s+application\s*\(_\sapplication:[^,]+,\s*didFinishLaunchingWithOptions[^,]+:[^)]+\)\s+->\s+Bool\s+{)|(init\s*\([^)]*\)\s*{)/im;
|
|
8
|
+
const objcAppLaunchRegex =
|
|
9
|
+
/-\s*\(BOOL\)\s*application:\s*\(UIApplication\s*\*\)\s*application\s+didFinishLaunchingWithOptions:\s*\(NSDictionary\s*\*\)\s*launchOptions\s*{/im;
|
|
8
10
|
const swiftUIRegex = /struct[^:]+:\s*App\s*{/im;
|
|
9
11
|
|
|
10
12
|
function isAppDelegateFile(filePath: string): boolean {
|
|
11
|
-
|
|
13
|
+
const appLaunchRegex = filePath.toLowerCase().endsWith('.swift')
|
|
14
|
+
? swiftAppLaunchRegex
|
|
15
|
+
: objcAppLaunchRegex;
|
|
12
16
|
|
|
13
|
-
|
|
14
|
-
|
|
17
|
+
const fileContent = fs.readFileSync(filePath, 'utf8');
|
|
18
|
+
return appLaunchRegex.test(fileContent) || swiftUIRegex.test(fileContent);
|
|
15
19
|
}
|
|
16
20
|
|
|
17
21
|
function findAppDidFinishLaunchingWithOptions(dir: string): string | null {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
+
const files = fs.readdirSync(dir);
|
|
23
|
+
//iterate over subdirectories later,
|
|
24
|
+
//the appdelegate usually is in the top level
|
|
25
|
+
const dirs: string[] = [];
|
|
22
26
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
27
|
+
for (const file of files) {
|
|
28
|
+
const filePath = path.join(dir, file);
|
|
29
|
+
if (
|
|
30
|
+
file.endsWith('.swift') ||
|
|
31
|
+
file.endsWith('.m') ||
|
|
32
|
+
file.endsWith('.mm')
|
|
33
|
+
) {
|
|
34
|
+
if (isAppDelegateFile(filePath)) {
|
|
35
|
+
return filePath;
|
|
36
|
+
}
|
|
37
|
+
} else if (
|
|
38
|
+
!file.startsWith('.') &&
|
|
39
|
+
!file.endsWith('.xcodeproj') &&
|
|
40
|
+
!file.endsWith('.xcassets') &&
|
|
41
|
+
fs.lstatSync(filePath).isDirectory()
|
|
42
|
+
) {
|
|
43
|
+
dirs.push(file);
|
|
32
44
|
}
|
|
45
|
+
}
|
|
33
46
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
47
|
+
for (const dr of dirs) {
|
|
48
|
+
const result = findAppDidFinishLaunchingWithOptions(path.join(dir, dr));
|
|
49
|
+
if (result) return result;
|
|
50
|
+
}
|
|
51
|
+
return null;
|
|
39
52
|
}
|
|
40
53
|
|
|
41
|
-
export function addCodeSnippetToProject(
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
54
|
+
export function addCodeSnippetToProject(
|
|
55
|
+
projPath: string,
|
|
56
|
+
dsn: string,
|
|
57
|
+
): boolean {
|
|
58
|
+
const appDelegate = findAppDidFinishLaunchingWithOptions(projPath);
|
|
59
|
+
if (!appDelegate) {
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
46
62
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
63
|
+
const fileContent = fs.readFileSync(appDelegate, 'utf8');
|
|
64
|
+
const isSwift = appDelegate.toLowerCase().endsWith('.swift');
|
|
65
|
+
const appLaunchRegex = isSwift ? swiftAppLaunchRegex : objcAppLaunchRegex;
|
|
66
|
+
const importStatement = isSwift ? 'import Sentry\n' : '@import Sentry;\n';
|
|
67
|
+
const checkForSentryInit = isSwift ? 'SentrySDK.start' : '[SentrySDK start';
|
|
68
|
+
let codeSnippet = isSwift
|
|
69
|
+
? templates.getSwiftSnippet(dsn)
|
|
70
|
+
: templates.getObjcSnippet(dsn);
|
|
53
71
|
|
|
54
|
-
|
|
55
|
-
|
|
72
|
+
Sentry.setTag('code-language', isSwift ? 'swift' : 'objc');
|
|
73
|
+
Sentry.setTag(
|
|
74
|
+
'ui-engine',
|
|
75
|
+
swiftUIRegex.test(fileContent) ? 'swiftui' : 'uikit',
|
|
76
|
+
);
|
|
56
77
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
78
|
+
if (fileContent.includes(checkForSentryInit)) {
|
|
79
|
+
//already initialized
|
|
80
|
+
return true;
|
|
81
|
+
}
|
|
61
82
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
}
|
|
68
|
-
//Is SwiftUI with no init
|
|
69
|
-
match = swiftUIMatch;
|
|
70
|
-
codeSnippet = ` init() {\n${codeSnippet} }`;
|
|
83
|
+
let match = appLaunchRegex.exec(fileContent);
|
|
84
|
+
if (!match) {
|
|
85
|
+
const swiftUIMatch = swiftUIRegex.exec(fileContent);
|
|
86
|
+
if (!swiftUIMatch) {
|
|
87
|
+
return false;
|
|
71
88
|
}
|
|
89
|
+
//Is SwiftUI with no init
|
|
90
|
+
match = swiftUIMatch;
|
|
91
|
+
codeSnippet = ` init() {\n${codeSnippet} }`;
|
|
92
|
+
}
|
|
72
93
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
94
|
+
const insertIndex = match.index + match[0].length;
|
|
95
|
+
const newFileContent =
|
|
96
|
+
(fileContent.indexOf(importStatement) >= 0 ? '' : importStatement) +
|
|
97
|
+
fileContent.slice(0, insertIndex) +
|
|
98
|
+
'\n' +
|
|
99
|
+
codeSnippet +
|
|
100
|
+
fileContent.slice(insertIndex);
|
|
101
|
+
fs.writeFileSync(appDelegate, newFileContent, 'utf8');
|
|
79
102
|
|
|
80
|
-
|
|
81
|
-
}
|
|
103
|
+
return true;
|
|
104
|
+
}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import * as fs from 'fs';
|
|
2
|
+
import * as path from 'path';
|
|
3
|
+
import * as templates from './templates';
|
|
4
|
+
import { askForItemSelection } from '../utils/clack-utils';
|
|
5
|
+
|
|
6
|
+
export function fastFile(projectPath: string): string | null {
|
|
7
|
+
const fastlanePath = path.join(projectPath, 'fastlane', 'Fastfile');
|
|
8
|
+
return fs.existsSync(fastlanePath) ? fastlanePath : null;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function findIOSPlatform(
|
|
12
|
+
content: string,
|
|
13
|
+
): { index: number; length: number } | null {
|
|
14
|
+
const platformRegex = /^ *platform\s+:([^ ]+)[^\n]*\n/gim;
|
|
15
|
+
let match = platformRegex.exec(content);
|
|
16
|
+
if (!match) {
|
|
17
|
+
// No platform found, treat whole file as one platform.
|
|
18
|
+
return { index: 0, length: content.length };
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
let index = -1;
|
|
22
|
+
while (match) {
|
|
23
|
+
if (match[1] === 'ios') {
|
|
24
|
+
index = match.index + match[0].length;
|
|
25
|
+
break;
|
|
26
|
+
}
|
|
27
|
+
match = platformRegex.exec(content);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (index === -1) {
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
//After finding the platform, we need to find the end of the platform block.
|
|
35
|
+
//This solution has the assumption that the file is well formed,
|
|
36
|
+
//which is not a perfect solution, but it's good enough assumption.
|
|
37
|
+
const platformEndRegex = /^end[^\n]*/gim;
|
|
38
|
+
match = platformEndRegex.exec(content.slice(index));
|
|
39
|
+
if (!match) {
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return { index, length: match.index };
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function findLanes(
|
|
47
|
+
content: string,
|
|
48
|
+
): { index: number; length: number; name: string }[] | null {
|
|
49
|
+
const laneRegex = /^ {2}lane\s+:([^ ]+)[^\n]*\n/gim;
|
|
50
|
+
let match = laneRegex.exec(content);
|
|
51
|
+
if (!match) {
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const lanes: { index: number; length: number; name: string }[] = [];
|
|
56
|
+
while (match) {
|
|
57
|
+
const laneEnd = /^ {2}end/m.exec(
|
|
58
|
+
content.slice(match.index + match[0].length),
|
|
59
|
+
);
|
|
60
|
+
if (laneEnd === null) {
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
lanes.push({
|
|
64
|
+
index: match.index + match[0].length,
|
|
65
|
+
length: laneEnd.index,
|
|
66
|
+
name: match[1],
|
|
67
|
+
});
|
|
68
|
+
match = laneRegex.exec(content);
|
|
69
|
+
}
|
|
70
|
+
return lanes;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function addSentryToLane(
|
|
74
|
+
content: string,
|
|
75
|
+
lane: { index: number; length: number; name: string },
|
|
76
|
+
org: string,
|
|
77
|
+
project: string,
|
|
78
|
+
token: string,
|
|
79
|
+
): string {
|
|
80
|
+
const laneContent = content.slice(lane.index, lane.index + lane.length);
|
|
81
|
+
const sentryCLIMatch = /sentry_cli\s*\([^)]+\)/gim.exec(laneContent);
|
|
82
|
+
if (sentryCLIMatch) {
|
|
83
|
+
// Sentry already added to lane. Update it.
|
|
84
|
+
return (
|
|
85
|
+
content.slice(0, sentryCLIMatch.index + lane.index) +
|
|
86
|
+
templates.getFastlaneSnippet(org, project, token).trim() +
|
|
87
|
+
content.slice(
|
|
88
|
+
sentryCLIMatch.index + sentryCLIMatch[0].length + lane.index,
|
|
89
|
+
)
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Sentry not added to lane. Add it.
|
|
94
|
+
return (
|
|
95
|
+
content.slice(0, lane.index + lane.length) +
|
|
96
|
+
'\n' +
|
|
97
|
+
templates.getFastlaneSnippet(org, project, token) +
|
|
98
|
+
'\n' +
|
|
99
|
+
content.slice(lane.index + lane.length)
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export async function addSentryToFastlane(
|
|
104
|
+
projectPath: string,
|
|
105
|
+
org: string,
|
|
106
|
+
project: string,
|
|
107
|
+
token: string,
|
|
108
|
+
): Promise<boolean> {
|
|
109
|
+
const fastFilePath = fastFile(projectPath);
|
|
110
|
+
if (!fastFilePath) {
|
|
111
|
+
return false;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const fileContent = fs.readFileSync(fastFilePath, 'utf8');
|
|
115
|
+
const platform = findIOSPlatform(fileContent);
|
|
116
|
+
if (!platform) {
|
|
117
|
+
return false;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const platformContent = fileContent.slice(
|
|
121
|
+
platform.index,
|
|
122
|
+
platform.index + platform.length,
|
|
123
|
+
);
|
|
124
|
+
const lanes = findLanes(platformContent);
|
|
125
|
+
lanes?.forEach((l) => (l.index += platform.index));
|
|
126
|
+
|
|
127
|
+
if (!lanes || lanes.length === 0) {
|
|
128
|
+
return false;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
let newFileContent: string | undefined;
|
|
132
|
+
if (lanes.length === 1) {
|
|
133
|
+
newFileContent = addSentryToLane(
|
|
134
|
+
fileContent,
|
|
135
|
+
lanes[0],
|
|
136
|
+
org,
|
|
137
|
+
project,
|
|
138
|
+
token,
|
|
139
|
+
);
|
|
140
|
+
} else {
|
|
141
|
+
const laneNames = lanes.map((l) => l.name);
|
|
142
|
+
const selectedLane = await askForItemSelection(
|
|
143
|
+
laneNames,
|
|
144
|
+
'Select lane to add Sentry to:',
|
|
145
|
+
);
|
|
146
|
+
if (selectedLane === undefined) {
|
|
147
|
+
return false;
|
|
148
|
+
}
|
|
149
|
+
newFileContent = addSentryToLane(
|
|
150
|
+
fileContent,
|
|
151
|
+
lanes[selectedLane.index],
|
|
152
|
+
org,
|
|
153
|
+
project,
|
|
154
|
+
token,
|
|
155
|
+
);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
fs.writeFileSync(fastFilePath, newFileContent, 'utf8');
|
|
159
|
+
return true;
|
|
160
|
+
}
|
package/src/apple/templates.ts
CHANGED
|
@@ -1,17 +1,20 @@
|
|
|
1
1
|
export function getRunScriptTemplate(
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
orgSlug: string,
|
|
3
|
+
projectSlug: string,
|
|
4
|
+
apiKey: string,
|
|
5
|
+
uploadSource = true,
|
|
6
6
|
): string {
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
// eslint-disable-next-line no-useless-escape
|
|
8
|
+
return `# This script is responsable to upload debug symbols and source context for Sentry.\\nif which sentry-cli >/dev/null; then\\nexport SENTRY_ORG=${orgSlug}\\nexport SENTRY_PROJECT=${projectSlug}\\nexport SENTRY_AUTH_TOKEN=${apiKey}\\nERROR=$(sentry-cli debug-files upload ${
|
|
9
|
+
uploadSource ? '--include-sources ' : ''
|
|
10
|
+
}"$DWARF_DSYM_FOLDER_PATH" 2>&1 >/dev/null)\\nif [ ! $? -eq 0 ]; then\\necho "warning: sentry-cli - $ERROR"\\nfi\\nelse\\necho "warning: sentry-cli not installed, download from https://github.com/getsentry/sentry-cli/releases"\\nfi\\n`;
|
|
9
11
|
}
|
|
10
12
|
|
|
11
|
-
export const scriptInputPath =
|
|
13
|
+
export const scriptInputPath =
|
|
14
|
+
'"${DWARF_DSYM_FOLDER_PATH}/${DWARF_DSYM_FILE_NAME}/Contents/Resources/DWARF/${TARGET_NAME}"';
|
|
12
15
|
|
|
13
16
|
export function getSwiftSnippet(dsn: string): string {
|
|
14
|
-
|
|
17
|
+
return ` SentrySDK.start { options in
|
|
15
18
|
options.dsn = "${dsn}"
|
|
16
19
|
options.debug = true // Enabled debug when first installing is always helpful
|
|
17
20
|
options.enableTracing = true
|
|
@@ -25,7 +28,7 @@ export function getSwiftSnippet(dsn: string): string {
|
|
|
25
28
|
}
|
|
26
29
|
|
|
27
30
|
export function getObjcSnippet(dsn: string): string {
|
|
28
|
-
|
|
31
|
+
return ` [SentrySDK startWithConfigureOptions:^(SentryOptions * options) {
|
|
29
32
|
options.dsn = @"${dsn}";
|
|
30
33
|
options.debug = YES; // Enabled debug when first installing is always helpful
|
|
31
34
|
options.enableTracing = YES;
|
|
@@ -36,4 +39,17 @@ export function getObjcSnippet(dsn: string): string {
|
|
|
36
39
|
}];
|
|
37
40
|
//Remove the next line after confirming that your Sentry integration is working.
|
|
38
41
|
[SentrySDK captureMessage:@"This app uses Sentry!"];\n`;
|
|
39
|
-
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function getFastlaneSnippet(
|
|
45
|
+
org: string,
|
|
46
|
+
project: string,
|
|
47
|
+
token: string,
|
|
48
|
+
): string {
|
|
49
|
+
return ` sentry_cli(
|
|
50
|
+
auth_token: '${token}',
|
|
51
|
+
org_slug: '${org}',
|
|
52
|
+
project_slug: '${project}',
|
|
53
|
+
include_sources: true
|
|
54
|
+
)`;
|
|
55
|
+
}
|
|
@@ -3,145 +3,162 @@
|
|
|
3
3
|
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
|
4
4
|
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
|
5
5
|
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
6
|
-
import { SentryCli } from '../../lib/Helper/SentryCli';
|
|
7
|
-
// @ts-ignore - clack is ESM and TS complains about that. It works though
|
|
8
|
-
import clack from '@clack/prompts';
|
|
9
|
-
import chalk from 'chalk';
|
|
10
6
|
import * as fs from 'fs';
|
|
11
|
-
import
|
|
7
|
+
import { SentryProjectData } from '../utils/types';
|
|
12
8
|
import * as templates from './templates';
|
|
13
9
|
const xcode = require('xcode');
|
|
14
10
|
|
|
15
|
-
import { SentryProjectData } from '../utils/clack-utils';
|
|
16
11
|
/* eslint-enable @typescript-eslint/no-unused-vars */
|
|
17
12
|
|
|
18
13
|
function setDebugInformationFormat(proj: any): void {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
14
|
+
const xcObjects = proj.hash.project.objects;
|
|
15
|
+
const target = proj.getFirstTarget().firstTarget;
|
|
16
|
+
|
|
17
|
+
xcObjects.XCConfigurationList[
|
|
18
|
+
target.buildConfigurationList
|
|
19
|
+
].buildConfigurations.forEach((buildConfig: { value: string }) => {
|
|
20
|
+
xcObjects.XCBuildConfiguration[
|
|
21
|
+
buildConfig.value
|
|
22
|
+
].buildSettings.DEBUG_INFORMATION_FORMAT = '"dwarf-with-dsym"';
|
|
23
|
+
});
|
|
25
24
|
}
|
|
26
25
|
|
|
27
26
|
function addSentrySPM(proj: any): void {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
const sentryFrameworkUUID = proj.generateUuid() as string;
|
|
31
|
-
const sentrySPMUUID = proj.generateUuid() as string;
|
|
32
|
-
|
|
33
|
-
//Check whether xcObjects already have sentry framework
|
|
34
|
-
if (xcObjects.PBXFrameworksBuildPhase) {
|
|
35
|
-
for (const key in xcObjects.PBXFrameworksBuildPhase || {}) {
|
|
36
|
-
if (!key.endsWith("_comment")) {
|
|
37
|
-
const frameworks = xcObjects.PBXFrameworksBuildPhase[key].files;
|
|
38
|
-
for (const framework of frameworks) {
|
|
39
|
-
if (framework.comment === "Sentry in Frameworks") {
|
|
40
|
-
return;
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
}
|
|
27
|
+
const xcObjects = proj.hash.project.objects;
|
|
46
28
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
productRef: sentrySPMUUID,
|
|
50
|
-
productRef_comment: "Sentry",
|
|
51
|
-
};
|
|
52
|
-
xcObjects.PBXBuildFile[sentryFrameworkUUID + "_comment"] = "Sentry in Frameworks";
|
|
29
|
+
const sentryFrameworkUUID = proj.generateUuid() as string;
|
|
30
|
+
const sentrySPMUUID = proj.generateUuid() as string;
|
|
53
31
|
|
|
32
|
+
//Check whether xcObjects already have sentry framework
|
|
33
|
+
if (xcObjects.PBXFrameworksBuildPhase) {
|
|
54
34
|
for (const key in xcObjects.PBXFrameworksBuildPhase || {}) {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
35
|
+
if (!key.endsWith('_comment')) {
|
|
36
|
+
const frameworks = xcObjects.PBXFrameworksBuildPhase[key].files;
|
|
37
|
+
for (const framework of frameworks) {
|
|
38
|
+
if (framework.comment === 'Sentry in Frameworks') {
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
61
41
|
}
|
|
42
|
+
}
|
|
62
43
|
}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
xcObjects.PBXBuildFile[sentryFrameworkUUID] = {
|
|
47
|
+
isa: 'PBXBuildFile',
|
|
48
|
+
productRef: sentrySPMUUID,
|
|
49
|
+
productRef_comment: 'Sentry',
|
|
50
|
+
};
|
|
51
|
+
xcObjects.PBXBuildFile[sentryFrameworkUUID + '_comment'] =
|
|
52
|
+
'Sentry in Frameworks';
|
|
53
|
+
|
|
54
|
+
for (const key in xcObjects.PBXFrameworksBuildPhase || {}) {
|
|
55
|
+
if (!key.endsWith('_comment')) {
|
|
56
|
+
const frameworks = xcObjects.PBXFrameworksBuildPhase[key].files;
|
|
57
|
+
frameworks.push({
|
|
58
|
+
value: sentryFrameworkUUID,
|
|
59
|
+
comment: 'Sentry in Frameworks',
|
|
60
|
+
});
|
|
67
61
|
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const target = proj.getFirstTarget().firstTarget;
|
|
65
|
+
if (!target.packageProductDependencies) {
|
|
66
|
+
target.packageProductDependencies = [];
|
|
67
|
+
}
|
|
68
|
+
target.packageProductDependencies.push({
|
|
69
|
+
value: sentrySPMUUID,
|
|
70
|
+
comment: 'Sentry',
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
const sentrySwiftPackageUUID = proj.generateUuid() as string;
|
|
74
|
+
const xcProject = proj.getFirstProject().firstProject;
|
|
75
|
+
if (!xcProject.packageReferences) {
|
|
76
|
+
xcProject.packageReferences = [];
|
|
77
|
+
}
|
|
78
|
+
xcProject.packageReferences.push({
|
|
79
|
+
value: sentrySwiftPackageUUID,
|
|
80
|
+
comment: 'XCRemoteSwiftPackageReference "sentry-cocoa"',
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
xcObjects.XCRemoteSwiftPackageReference = {};
|
|
84
|
+
xcObjects.XCRemoteSwiftPackageReference[sentrySwiftPackageUUID] = {
|
|
85
|
+
isa: 'XCRemoteSwiftPackageReference',
|
|
86
|
+
repositoryURL: '"https://github.com/getsentry/sentry-cocoa/"',
|
|
87
|
+
requirement: {
|
|
88
|
+
kind: 'upToNextMajorVersion',
|
|
89
|
+
minimumVersion: '8.0.0',
|
|
90
|
+
},
|
|
91
|
+
};
|
|
92
|
+
xcObjects.XCRemoteSwiftPackageReference[sentrySwiftPackageUUID + '_comment'] =
|
|
93
|
+
'XCRemoteSwiftPackageReference "sentry-cocoa"';
|
|
94
|
+
|
|
95
|
+
xcObjects.XCSwiftPackageProductDependency = {};
|
|
96
|
+
xcObjects.XCSwiftPackageProductDependency[sentrySPMUUID] = {
|
|
97
|
+
isa: 'XCSwiftPackageProductDependency',
|
|
98
|
+
package: sentrySwiftPackageUUID,
|
|
99
|
+
package_comment: 'XCRemoteSwiftPackageReference "sentry-cocoa"',
|
|
100
|
+
productName: 'Sentry',
|
|
101
|
+
};
|
|
102
|
+
xcObjects.XCSwiftPackageProductDependency[sentrySPMUUID + '_comment'] =
|
|
103
|
+
'Sentry';
|
|
103
104
|
}
|
|
104
105
|
|
|
105
|
-
function addUploadSymbolsScript(
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
106
|
+
function addUploadSymbolsScript(
|
|
107
|
+
xcodeProject: any,
|
|
108
|
+
sentryProject: SentryProjectData,
|
|
109
|
+
apiKeys: { token: string },
|
|
110
|
+
uploadSource = true,
|
|
111
|
+
): void {
|
|
112
|
+
const xcObjects = xcodeProject.hash.project.objects;
|
|
113
|
+
|
|
114
|
+
for (const scriptKey in xcObjects.PBXShellScriptBuildPhase || {}) {
|
|
115
|
+
if (!scriptKey.endsWith('_comment')) {
|
|
116
|
+
const script = xcObjects.PBXShellScriptBuildPhase[scriptKey].shellScript;
|
|
117
|
+
//Sentry script already exists, update it
|
|
118
|
+
if (script.includes('sentry-cli')) {
|
|
119
|
+
delete xcObjects.PBXShellScriptBuildPhase[scriptKey];
|
|
120
|
+
delete xcObjects.PBXShellScriptBuildPhase[scriptKey + '_comment'];
|
|
121
|
+
break;
|
|
122
|
+
}
|
|
118
123
|
}
|
|
124
|
+
}
|
|
119
125
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
126
|
+
xcodeProject.addBuildPhase(
|
|
127
|
+
[],
|
|
128
|
+
'PBXShellScriptBuildPhase',
|
|
129
|
+
'Upload Debug Symbols to Sentry',
|
|
130
|
+
null,
|
|
131
|
+
{
|
|
132
|
+
inputFileListPaths: [],
|
|
133
|
+
outputFileListPaths: [],
|
|
134
|
+
inputPaths: [templates.scriptInputPath],
|
|
135
|
+
shellPath: '/bin/sh',
|
|
136
|
+
shellScript: templates.getRunScriptTemplate(
|
|
137
|
+
sentryProject.organization.slug,
|
|
138
|
+
sentryProject.slug,
|
|
139
|
+
apiKeys.token,
|
|
140
|
+
uploadSource,
|
|
141
|
+
),
|
|
142
|
+
},
|
|
143
|
+
);
|
|
133
144
|
}
|
|
134
145
|
|
|
135
|
-
export function updateXcodeProject(
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
}
|
|
146
|
+
export function updateXcodeProject(
|
|
147
|
+
projectPath: string,
|
|
148
|
+
sentryProject: SentryProjectData,
|
|
149
|
+
apiKeys: { token: string },
|
|
150
|
+
addSPMReference: boolean,
|
|
151
|
+
uploadSource = true,
|
|
152
|
+
): void {
|
|
153
|
+
const proj = xcode.project(projectPath);
|
|
154
|
+
proj.parseSync();
|
|
155
|
+
addUploadSymbolsScript(proj, sentryProject, apiKeys, uploadSource);
|
|
156
|
+
if (uploadSource) {
|
|
157
|
+
setDebugInformationFormat(proj);
|
|
158
|
+
}
|
|
159
|
+
if (addSPMReference) {
|
|
160
|
+
addSentrySPM(proj);
|
|
161
|
+
}
|
|
162
|
+
const newContent = proj.writeSync();
|
|
163
|
+
fs.writeFileSync(projectPath, newContent);
|
|
164
|
+
}
|