@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.
Files changed (83) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/dist/lib/Helper/__tests__/MergeConfig.js.map +1 -1
  3. package/dist/lib/Steps/ChooseIntegration.js +12 -26
  4. package/dist/lib/Steps/ChooseIntegration.js.map +1 -1
  5. package/dist/lib/Steps/Integrations/Cordova.js.map +1 -1
  6. package/dist/lib/Steps/Integrations/Electron.js.map +1 -1
  7. package/dist/lib/Steps/Integrations/MobileProject.js.map +1 -1
  8. package/dist/lib/Steps/Integrations/ReactNative.js +2 -2
  9. package/dist/lib/Steps/Integrations/ReactNative.js.map +1 -1
  10. package/dist/lib/Steps/Integrations/__tests__/ReactNative.js +5 -6
  11. package/dist/lib/Steps/Integrations/__tests__/ReactNative.js.map +1 -1
  12. package/dist/package.json +3 -3
  13. package/dist/src/apple/apple-wizard.js +31 -2
  14. package/dist/src/apple/apple-wizard.js.map +1 -1
  15. package/dist/src/apple/cocoapod.d.ts +2 -0
  16. package/dist/src/apple/cocoapod.js +122 -0
  17. package/dist/src/apple/cocoapod.js.map +1 -0
  18. package/dist/src/apple/code-tools.js +22 -12
  19. package/dist/src/apple/code-tools.js.map +1 -1
  20. package/dist/src/apple/fastlane.d.ts +2 -0
  21. package/dist/src/apple/fastlane.js +179 -0
  22. package/dist/src/apple/fastlane.js.map +1 -0
  23. package/dist/src/apple/templates.d.ts +1 -0
  24. package/dist/src/apple/templates.js +7 -3
  25. package/dist/src/apple/templates.js.map +1 -1
  26. package/dist/src/apple/xcode-manager.d.ts +1 -1
  27. package/dist/src/apple/xcode-manager.js +35 -28
  28. package/dist/src/apple/xcode-manager.js.map +1 -1
  29. package/dist/src/nextjs/nextjs-wizard.js +71 -81
  30. package/dist/src/nextjs/nextjs-wizard.js.map +1 -1
  31. package/dist/src/sourcemaps/sourcemaps-wizard.js +61 -46
  32. package/dist/src/sourcemaps/sourcemaps-wizard.js.map +1 -1
  33. package/dist/src/sourcemaps/tools/nextjs.d.ts +3 -0
  34. package/dist/src/sourcemaps/tools/nextjs.js +135 -0
  35. package/dist/src/sourcemaps/tools/nextjs.js.map +1 -0
  36. package/dist/src/sourcemaps/tools/sentry-cli.js +120 -16
  37. package/dist/src/sourcemaps/tools/sentry-cli.js.map +1 -1
  38. package/dist/src/sourcemaps/utils/detect-tool.d.ts +1 -1
  39. package/dist/src/sourcemaps/utils/detect-tool.js +1 -0
  40. package/dist/src/sourcemaps/utils/detect-tool.js.map +1 -1
  41. package/dist/src/sourcemaps/utils/other-wizards.js +35 -12
  42. package/dist/src/sourcemaps/utils/other-wizards.js.map +1 -1
  43. package/dist/src/sveltekit/sentry-cli-setup.d.ts +1 -1
  44. package/dist/src/sveltekit/sentry-cli-setup.js.map +1 -1
  45. package/dist/src/sveltekit/sveltekit-wizard.js +14 -8
  46. package/dist/src/sveltekit/sveltekit-wizard.js.map +1 -1
  47. package/dist/src/utils/bash.d.ts +2 -1
  48. package/dist/src/utils/bash.js +14 -2
  49. package/dist/src/utils/bash.js.map +1 -1
  50. package/dist/src/utils/clack-utils.d.ts +7 -14
  51. package/dist/src/utils/clack-utils.js +46 -2
  52. package/dist/src/utils/clack-utils.js.map +1 -1
  53. package/dist/src/utils/package-json.d.ts +1 -1
  54. package/dist/src/utils/package-json.js.map +1 -1
  55. package/dist/src/utils/types.d.ts +24 -0
  56. package/dist/src/utils/types.js.map +1 -1
  57. package/lib/Helper/__tests__/MergeConfig.ts +9 -4
  58. package/lib/Steps/ChooseIntegration.ts +13 -3
  59. package/lib/Steps/Integrations/Cordova.ts +3 -3
  60. package/lib/Steps/Integrations/Electron.ts +1 -2
  61. package/lib/Steps/Integrations/MobileProject.ts +1 -1
  62. package/lib/Steps/Integrations/ReactNative.ts +16 -14
  63. package/lib/Steps/Integrations/__tests__/ReactNative.ts +24 -15
  64. package/package-lock.json +2 -2
  65. package/package.json +3 -3
  66. package/src/apple/apple-wizard.ts +35 -3
  67. package/src/apple/cocoapod.ts +57 -0
  68. package/src/apple/code-tools.ts +80 -57
  69. package/src/apple/fastlane.ts +160 -0
  70. package/src/apple/templates.ts +26 -10
  71. package/src/apple/xcode-manager.ts +137 -120
  72. package/src/nextjs/nextjs-wizard.ts +4 -13
  73. package/src/sourcemaps/sourcemaps-wizard.ts +40 -28
  74. package/src/sourcemaps/tools/nextjs.ts +114 -0
  75. package/src/sourcemaps/tools/sentry-cli.ts +134 -8
  76. package/src/sourcemaps/utils/detect-tool.ts +3 -1
  77. package/src/sourcemaps/utils/other-wizards.ts +32 -13
  78. package/src/sveltekit/sentry-cli-setup.ts +1 -1
  79. package/src/sveltekit/sveltekit-wizard.ts +3 -0
  80. package/src/utils/bash.ts +43 -30
  81. package/src/utils/clack-utils.ts +42 -14
  82. package/src/utils/package-json.ts +1 -1
  83. 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, true, true);
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
+ }
@@ -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 = /(func\s+application\s*\(_\sapplication:[^,]+,\s*didFinishLaunchingWithOptions[^,]+:[^)]+\)\s+->\s+Bool\s+{)|(init\s*\([^)]*\)\s*{)/im;
7
- const objcAppLaunchRegex = /-\s*\(BOOL\)\s*application:\s*\(UIApplication\s*\*\)\s*application\s+didFinishLaunchingWithOptions:\s*\(NSDictionary\s*\*\)\s*launchOptions\s*{/im;
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
- const appLaunchRegex = filePath.toLowerCase().endsWith(".swift") ? swiftAppLaunchRegex : objcAppLaunchRegex;
13
+ const appLaunchRegex = filePath.toLowerCase().endsWith('.swift')
14
+ ? swiftAppLaunchRegex
15
+ : objcAppLaunchRegex;
12
16
 
13
- const fileContent = fs.readFileSync(filePath, 'utf8');
14
- return appLaunchRegex.test(fileContent) || swiftUIRegex.test(fileContent);
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
- const files = fs.readdirSync(dir);
19
- //iterate over subdirectories later,
20
- //the appdelegate usually is in the top level
21
- const dirs: string[] = [];
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
- for (const file of files) {
24
- const filePath = path.join(dir, file);
25
- if (file.endsWith(".swift") || file.endsWith(".m") || file.endsWith(".mm")) {
26
- if (isAppDelegateFile(filePath)) {
27
- return filePath;
28
- }
29
- } else if (!file.startsWith(".") && !file.endsWith(".xcodeproj") && !file.endsWith(".xcassets") && fs.lstatSync(filePath).isDirectory()) {
30
- dirs.push(file);
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
- for (const dr of dirs) {
35
- const result = findAppDidFinishLaunchingWithOptions(path.join(dir, dr));
36
- if (result) return result;
37
- }
38
- return null;
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(projPath: string, dsn: string): boolean {
42
- const appDelegate = findAppDidFinishLaunchingWithOptions(projPath);
43
- if (!appDelegate) {
44
- return false;
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
- const fileContent = fs.readFileSync(appDelegate, 'utf8');
48
- const isSwift = appDelegate.toLowerCase().endsWith(".swift");
49
- const appLaunchRegex = isSwift ? swiftAppLaunchRegex : objcAppLaunchRegex;
50
- const importStatement = isSwift ? "import Sentry\n" : "@import Sentry;\n";
51
- const checkForSentryInit = isSwift ? "SentrySDK.start" : "[SentrySDK start";
52
- let codeSnippet = isSwift ? templates.getSwiftSnippet(dsn) : templates.getObjcSnippet(dsn);
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
- Sentry.setTag("code-language", isSwift ? "swift" : "objc");
55
- Sentry.setTag("ui-engine", swiftUIRegex.test(fileContent) ? "swiftui" : "uikit");
72
+ Sentry.setTag('code-language', isSwift ? 'swift' : 'objc');
73
+ Sentry.setTag(
74
+ 'ui-engine',
75
+ swiftUIRegex.test(fileContent) ? 'swiftui' : 'uikit',
76
+ );
56
77
 
57
- if (fileContent.includes(checkForSentryInit)) {
58
- //already initialized
59
- return true;
60
- }
78
+ if (fileContent.includes(checkForSentryInit)) {
79
+ //already initialized
80
+ return true;
81
+ }
61
82
 
62
- let match = appLaunchRegex.exec(fileContent);
63
- if (!match) {
64
- const swiftUIMatch = swiftUIRegex.exec(fileContent)
65
- if (!swiftUIMatch) {
66
- return false;
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
- const insertIndex = match.index + match[0].length;
74
- const newFileContent = (fileContent.indexOf(importStatement) >= 0 ? "" : importStatement) +
75
- fileContent.slice(0, insertIndex) + "\n" +
76
- codeSnippet +
77
- fileContent.slice(insertIndex);
78
- fs.writeFileSync(appDelegate, newFileContent, 'utf8');
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
- return true;
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
+ }
@@ -1,17 +1,20 @@
1
1
  export function getRunScriptTemplate(
2
- orgSlug: string,
3
- projectSlug: string,
4
- apiKey: string,
5
- uploadSource = true,
2
+ orgSlug: string,
3
+ projectSlug: string,
4
+ apiKey: string,
5
+ uploadSource = true,
6
6
  ): string {
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 ${uploadSource ? "--include-sources " : ""}\"$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`;
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 = "\"${DWARF_DSYM_FOLDER_PATH}/${DWARF_DSYM_FILE_NAME}/Contents/Resources/DWARF/${TARGET_NAME}\"";
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
- return ` SentrySDK.start { options in
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
- return ` [SentrySDK startWithConfigureOptions:^(SentryOptions * options) {
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
+ }