@sentry/wizard 3.7.1 → 3.8.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 +11 -0
- package/dist/lib/Helper/__tests__/MergeConfig.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 +2 -2
- 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 +3 -3
- 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/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/sentry-cli-setup.d.ts +1 -1
- package/dist/src/sveltekit/sentry-cli-setup.js.map +1 -1
- package/dist/src/sveltekit/sveltekit-wizard.js +14 -8
- package/dist/src/sveltekit/sveltekit-wizard.js.map +1 -1
- 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/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/lib/Helper/__tests__/MergeConfig.ts +9 -4
- 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 +16 -14
- package/lib/Steps/Integrations/__tests__/ReactNative.ts +24 -15
- package/package-lock.json +2 -2
- package/package.json +3 -3
- 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/utils/detect-tool.ts +3 -1
- package/src/sourcemaps/utils/other-wizards.ts +32 -13
- package/src/sveltekit/sentry-cli-setup.ts +1 -1
- package/src/sveltekit/sveltekit-wizard.ts +3 -0
- package/src/utils/bash.ts +43 -30
- package/src/utils/clack-utils.ts +42 -14
- package/src/utils/package-json.ts +1 -1
- package/src/utils/types.ts +22 -0
|
@@ -10,9 +10,11 @@ import * as path from 'path';
|
|
|
10
10
|
import * as xcManager from './xcode-manager';
|
|
11
11
|
import * as codeTools from './code-tools';
|
|
12
12
|
import * as bash from '../utils/bash';
|
|
13
|
-
import { WizardOptions } from '../utils/types';
|
|
13
|
+
import { SentryProjectData, WizardOptions } from '../utils/types';
|
|
14
14
|
import * as Sentry from '@sentry/node';
|
|
15
15
|
import { traceStep, withTelemetry } from '../telemetry';
|
|
16
|
+
import * as cocoapod from './cocoapod';
|
|
17
|
+
import * as fastlane from './fastlane';
|
|
16
18
|
|
|
17
19
|
const xcode = require('xcode');
|
|
18
20
|
/* eslint-enable @typescript-eslint/no-unused-vars */
|
|
@@ -22,7 +24,6 @@ import {
|
|
|
22
24
|
askForSelfHosted,
|
|
23
25
|
askForWizardLogin,
|
|
24
26
|
askToInstallSentryCLI,
|
|
25
|
-
SentryProjectData,
|
|
26
27
|
printWelcome,
|
|
27
28
|
abort,
|
|
28
29
|
askForItemSelection,
|
|
@@ -102,10 +103,24 @@ async function runAppleWizardWithTelementry(
|
|
|
102
103
|
options.url,
|
|
103
104
|
);
|
|
104
105
|
|
|
106
|
+
const hasCocoa = cocoapod.usesCocoaPod(projectDir);
|
|
107
|
+
|
|
108
|
+
if (hasCocoa) {
|
|
109
|
+
const podAdded = await traceStep('Add CocoaPods reference', () =>
|
|
110
|
+
cocoapod.addCocoaPods(projectDir),
|
|
111
|
+
);
|
|
112
|
+
if (!podAdded) {
|
|
113
|
+
clack.log.warn(
|
|
114
|
+
"Could not add Sentry pod to your Podfile. You'll have to add it manually.\nPlease follow the instructions at https://docs.sentry.io/platforms/apple/guides/ios/#install",
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
105
119
|
traceStep('Update Xcode project', () => {
|
|
106
|
-
xcManager.updateXcodeProject(pbxproj, project, apiKey,
|
|
120
|
+
xcManager.updateXcodeProject(pbxproj, project, apiKey, !hasCocoa, true);
|
|
107
121
|
});
|
|
108
122
|
|
|
123
|
+
Sentry.setTag('package-manager', hasCocoa ? 'cocoapods' : 'SPM');
|
|
109
124
|
const projSource = path.join(
|
|
110
125
|
projectDir,
|
|
111
126
|
xcodeProjFile.replace('.xcodeproj', ''),
|
|
@@ -123,6 +138,23 @@ async function runAppleWizardWithTelementry(
|
|
|
123
138
|
return;
|
|
124
139
|
}
|
|
125
140
|
|
|
141
|
+
if (fastlane.fastFile(projectDir)) {
|
|
142
|
+
const addLane = await clack.confirm({
|
|
143
|
+
message:
|
|
144
|
+
'Found a Fastfile in your project. Do you want to configure a lane to upload debug symbols to Sentry?',
|
|
145
|
+
});
|
|
146
|
+
if (addLane) {
|
|
147
|
+
await traceStep('Configure fastlane', () =>
|
|
148
|
+
fastlane.addSentryToFastlane(
|
|
149
|
+
projectDir,
|
|
150
|
+
project.organization.slug,
|
|
151
|
+
project.slug,
|
|
152
|
+
apiKey.token,
|
|
153
|
+
),
|
|
154
|
+
);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
126
158
|
clack.log.success('Sentry was successfully added to your project!');
|
|
127
159
|
}
|
|
128
160
|
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import * as fs from 'fs';
|
|
2
|
+
import * as path from 'path';
|
|
3
|
+
import * as bash from '../utils/bash';
|
|
4
|
+
import * as Sentry from '@sentry/node';
|
|
5
|
+
// @ts-ignore - clack is ESM and TS complains about that. It works though
|
|
6
|
+
import * as clack from '@clack/prompts';
|
|
7
|
+
|
|
8
|
+
export function usesCocoaPod(projPath: string): boolean {
|
|
9
|
+
return fs.existsSync(path.join(projPath, 'Podfile'));
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export async function addCocoaPods(projPath: string): Promise<boolean> {
|
|
13
|
+
const podfile = path.join(projPath, 'Podfile');
|
|
14
|
+
|
|
15
|
+
const podContent = fs.readFileSync(podfile, 'utf8');
|
|
16
|
+
|
|
17
|
+
if (
|
|
18
|
+
/^\s*pod\s+(['"]Sentry['"]|['"]SentrySwiftUI['"])\s*$/im.test(podContent)
|
|
19
|
+
) {
|
|
20
|
+
// Already have Sentry pod
|
|
21
|
+
return true;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
let podMatch = /^( *)pod\s+['"](\w+)['"] *$/im.exec(podContent);
|
|
25
|
+
if (!podMatch) {
|
|
26
|
+
// No Podfile is empty, will try to add Sentry pod after "use_frameworks!"
|
|
27
|
+
const frameworkMatch = /^( *)use_frameworks![^\n]* *$/im.exec(podContent);
|
|
28
|
+
if (!frameworkMatch) {
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
podMatch = frameworkMatch;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const insertIndex = podMatch.index + podMatch[0].length;
|
|
35
|
+
const newFileContent =
|
|
36
|
+
podContent.slice(0, insertIndex) +
|
|
37
|
+
'\n' +
|
|
38
|
+
podMatch[1] +
|
|
39
|
+
"pod 'Sentry'\n" +
|
|
40
|
+
podContent.slice(insertIndex);
|
|
41
|
+
fs.writeFileSync(podfile, newFileContent, 'utf8');
|
|
42
|
+
|
|
43
|
+
const loginSpinner = clack.spinner();
|
|
44
|
+
|
|
45
|
+
loginSpinner.start("Running 'pod install'. This may take a few minutes...");
|
|
46
|
+
|
|
47
|
+
try {
|
|
48
|
+
await bash.execute('pod install --silent');
|
|
49
|
+
loginSpinner.stop('Sentry pod added to the project.');
|
|
50
|
+
} catch (e) {
|
|
51
|
+
clack.log.error("'pod install' failed. You will need to run it manually.");
|
|
52
|
+
loginSpinner.stop();
|
|
53
|
+
Sentry.captureException('Sentry pod install failed.');
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return true;
|
|
57
|
+
}
|
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
|
+
}
|