@sentry/wizard 3.10.0 → 3.12.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 +54 -7
- package/dist/lib/Constants.d.ts +1 -0
- package/dist/lib/Constants.js +5 -0
- package/dist/lib/Constants.js.map +1 -1
- package/dist/lib/Steps/ChooseIntegration.js +8 -4
- package/dist/lib/Steps/ChooseIntegration.js.map +1 -1
- package/dist/lib/Steps/Integrations/Android.d.ts +9 -0
- package/dist/lib/Steps/Integrations/Android.js +86 -0
- package/dist/lib/Steps/Integrations/Android.js.map +1 -0
- package/dist/lib/Steps/Integrations/ReactNative.js +3 -3
- package/dist/lib/Steps/Integrations/ReactNative.js.map +1 -1
- package/dist/lib/Steps/PromptForParameters.js +36 -3
- package/dist/lib/Steps/PromptForParameters.js.map +1 -1
- package/dist/lib/Steps/SentryProjectSelector.js +1 -1
- package/dist/lib/Steps/SentryProjectSelector.js.map +1 -1
- package/dist/package.json +4 -3
- package/dist/src/android/android-wizard.d.ts +2 -0
- package/dist/src/android/android-wizard.js +225 -0
- package/dist/src/android/android-wizard.js.map +1 -0
- package/dist/src/android/code-tools.d.ts +47 -0
- package/dist/src/android/code-tools.js +173 -0
- package/dist/src/android/code-tools.js.map +1 -0
- package/dist/src/android/gradle.d.ts +62 -0
- package/dist/src/android/gradle.js +286 -0
- package/dist/src/android/gradle.js.map +1 -0
- package/dist/src/android/manifest.d.ts +57 -0
- package/dist/src/android/manifest.js +183 -0
- package/dist/src/android/manifest.js.map +1 -0
- package/dist/src/android/templates.d.ts +11 -0
- package/dist/src/android/templates.js +34 -0
- package/dist/src/android/templates.js.map +1 -0
- package/dist/src/apple/apple-wizard.js +123 -64
- package/dist/src/apple/apple-wizard.js.map +1 -1
- package/dist/src/apple/cocoapod.js +4 -3
- package/dist/src/apple/cocoapod.js.map +1 -1
- package/dist/src/apple/code-tools.d.ts +1 -1
- package/dist/src/apple/code-tools.js +43 -19
- package/dist/src/apple/code-tools.js.map +1 -1
- package/dist/src/apple/fastlane.d.ts +1 -1
- package/dist/src/apple/fastlane.js +12 -6
- package/dist/src/apple/fastlane.js.map +1 -1
- package/dist/src/apple/templates.d.ts +2 -2
- package/dist/src/apple/templates.js +4 -4
- package/dist/src/apple/templates.js.map +1 -1
- package/dist/src/apple/xcode-manager.d.ts +19 -3
- package/dist/src/apple/xcode-manager.js +126 -24
- package/dist/src/apple/xcode-manager.js.map +1 -1
- package/dist/src/nextjs/nextjs-wizard.js +49 -11
- package/dist/src/nextjs/nextjs-wizard.js.map +1 -1
- package/dist/src/nextjs/templates.d.ts +2 -0
- package/dist/src/nextjs/templates.js +6 -2
- package/dist/src/nextjs/templates.js.map +1 -1
- package/dist/src/remix/remix-wizard.js +10 -20
- package/dist/src/remix/remix-wizard.js.map +1 -1
- package/dist/src/sourcemaps/sourcemaps-wizard.js +26 -13
- package/dist/src/sourcemaps/sourcemaps-wizard.js.map +1 -1
- package/dist/src/sourcemaps/tools/nextjs.js +1 -1
- package/dist/src/sourcemaps/tools/nextjs.js.map +1 -1
- package/dist/src/sourcemaps/tools/sentry-cli.js +19 -16
- package/dist/src/sourcemaps/tools/sentry-cli.js.map +1 -1
- package/dist/src/sourcemaps/tools/vite.d.ts +2 -1
- package/dist/src/sourcemaps/tools/vite.js +123 -111
- package/dist/src/sourcemaps/tools/vite.js.map +1 -1
- package/dist/src/sourcemaps/tools/webpack.d.ts +6 -1
- package/dist/src/sourcemaps/tools/webpack.js +290 -25
- package/dist/src/sourcemaps/tools/webpack.js.map +1 -1
- package/dist/src/sourcemaps/utils/detect-tool.d.ts +1 -1
- package/dist/src/sourcemaps/utils/detect-tool.js.map +1 -1
- package/dist/src/sveltekit/sdk-setup.js +5 -5
- package/dist/src/sveltekit/sdk-setup.js.map +1 -1
- package/dist/src/sveltekit/sveltekit-wizard.js +34 -44
- package/dist/src/sveltekit/sveltekit-wizard.js.map +1 -1
- package/dist/src/telemetry.js +1 -0
- package/dist/src/telemetry.js.map +1 -1
- package/dist/src/utils/ast-utils.d.ts +9 -5
- package/dist/src/utils/ast-utils.js +26 -11
- package/dist/src/utils/ast-utils.js.map +1 -1
- package/dist/src/utils/clack-utils.d.ts +74 -28
- package/dist/src/utils/clack-utils.js +427 -264
- package/dist/src/utils/clack-utils.js.map +1 -1
- package/dist/src/utils/package-manager.d.ts +10 -0
- package/dist/{lib/Helper/PackageManager.js → src/utils/package-manager.js} +42 -74
- package/dist/src/utils/package-manager.js.map +1 -0
- package/dist/src/utils/release-registry.d.ts +1 -0
- package/dist/src/utils/release-registry.js +68 -0
- package/dist/src/utils/release-registry.js.map +1 -0
- package/dist/src/utils/sentrycli-utils.d.ts +4 -0
- package/dist/src/utils/sentrycli-utils.js +41 -0
- package/dist/src/utils/sentrycli-utils.js.map +1 -0
- package/dist/test/android/code-tools.test.d.ts +1 -0
- package/dist/test/android/code-tools.test.js +34 -0
- package/dist/test/android/code-tools.test.js.map +1 -0
- package/dist/test/sourcemaps/tools/vite.test.d.ts +1 -0
- package/dist/test/sourcemaps/tools/vite.test.js +132 -0
- package/dist/test/sourcemaps/tools/vite.test.js.map +1 -0
- package/dist/test/sourcemaps/tools/webpack.test.d.ts +1 -0
- package/dist/test/sourcemaps/tools/webpack.test.js +179 -0
- package/dist/test/sourcemaps/tools/webpack.test.js.map +1 -0
- package/dist/test/utils/ast-utils.test.js +42 -7
- package/dist/test/utils/ast-utils.test.js.map +1 -1
- package/dist/test/utils/clack-utils.test.d.ts +1 -0
- package/dist/test/utils/clack-utils.test.js +200 -0
- package/dist/test/utils/clack-utils.test.js.map +1 -0
- package/lib/Constants.ts +5 -0
- package/lib/Steps/ChooseIntegration.ts +7 -3
- package/lib/Steps/Integrations/Android.ts +23 -0
- package/lib/Steps/Integrations/ReactNative.ts +9 -3
- package/lib/Steps/PromptForParameters.ts +48 -3
- package/lib/Steps/SentryProjectSelector.ts +3 -1
- package/package.json +4 -3
- package/src/android/android-wizard.ts +204 -0
- package/src/android/code-tools.ts +170 -0
- package/src/android/gradle.ts +250 -0
- package/src/android/manifest.ts +180 -0
- package/src/android/templates.ts +88 -0
- package/src/apple/apple-wizard.ts +113 -35
- package/src/apple/cocoapod.ts +6 -3
- package/src/apple/code-tools.ts +46 -18
- package/src/apple/fastlane.ts +6 -12
- package/src/apple/templates.ts +2 -8
- package/src/apple/xcode-manager.ts +167 -25
- package/src/nextjs/nextjs-wizard.ts +72 -8
- package/src/nextjs/templates.ts +16 -2
- package/src/remix/remix-wizard.ts +10 -15
- package/src/sourcemaps/sourcemaps-wizard.ts +19 -5
- package/src/sourcemaps/tools/nextjs.ts +2 -2
- package/src/sourcemaps/tools/sentry-cli.ts +8 -7
- package/src/sourcemaps/tools/vite.ts +143 -79
- package/src/sourcemaps/tools/webpack.ts +369 -30
- package/src/sourcemaps/utils/detect-tool.ts +2 -1
- package/src/sveltekit/sdk-setup.ts +10 -6
- package/src/sveltekit/sveltekit-wizard.ts +5 -14
- package/src/telemetry.ts +2 -0
- package/src/utils/ast-utils.ts +29 -11
- package/src/utils/clack-utils.ts +485 -283
- package/src/utils/package-manager.ts +61 -0
- package/src/utils/release-registry.ts +19 -0
- package/src/utils/sentrycli-utils.ts +22 -0
- package/test/android/code-tools.test.ts +49 -0
- package/test/sourcemaps/tools/vite.test.ts +149 -0
- package/test/sourcemaps/tools/webpack.test.ts +303 -0
- package/test/utils/ast-utils.test.ts +28 -9
- package/test/utils/clack-utils.test.ts +142 -0
- package/dist/lib/Helper/PackageManager.d.ts +0 -22
- package/dist/lib/Helper/PackageManager.js.map +0 -1
- package/dist/src/utils/vendor/clack-custom-select.d.ts +0 -21
- package/dist/src/utils/vendor/clack-custom-select.js +0 -137
- package/dist/src/utils/vendor/clack-custom-select.js.map +0 -1
- package/lib/Helper/PackageManager.ts +0 -59
- package/src/utils/vendor/clack-custom-select.ts +0 -160
|
@@ -7,9 +7,10 @@
|
|
|
7
7
|
import clack from '@clack/prompts';
|
|
8
8
|
import * as fs from 'fs';
|
|
9
9
|
import * as path from 'path';
|
|
10
|
-
import
|
|
10
|
+
import { XcodeProject } from './xcode-manager';
|
|
11
11
|
import * as codeTools from './code-tools';
|
|
12
12
|
import * as bash from '../utils/bash';
|
|
13
|
+
import * as SentryUtils from '../utils/sentrycli-utils';
|
|
13
14
|
import { SentryProjectData, WizardOptions } from '../utils/types';
|
|
14
15
|
import * as Sentry from '@sentry/node';
|
|
15
16
|
import { traceStep, withTelemetry } from '../telemetry';
|
|
@@ -20,13 +21,12 @@ const xcode = require('xcode');
|
|
|
20
21
|
/* eslint-enable @typescript-eslint/no-unused-vars */
|
|
21
22
|
|
|
22
23
|
import {
|
|
23
|
-
askForProjectSelection,
|
|
24
|
-
askForSelfHosted,
|
|
25
|
-
askForWizardLogin,
|
|
26
24
|
askToInstallSentryCLI,
|
|
27
25
|
printWelcome,
|
|
28
26
|
abort,
|
|
29
27
|
askForItemSelection,
|
|
28
|
+
confirmContinueEvenThoughNoGitRepo,
|
|
29
|
+
getOrAskForProjectData,
|
|
30
30
|
} from '../utils/clack-utils';
|
|
31
31
|
|
|
32
32
|
export async function runAppleWizard(options: WizardOptions): Promise<void> {
|
|
@@ -47,6 +47,8 @@ async function runAppleWizardWithTelementry(
|
|
|
47
47
|
promoCode: options.promoCode,
|
|
48
48
|
});
|
|
49
49
|
|
|
50
|
+
await confirmContinueEvenThoughNoGitRepo();
|
|
51
|
+
|
|
50
52
|
const hasCli = bash.hasSentryCLI();
|
|
51
53
|
Sentry.setTag('has-cli', hasCli);
|
|
52
54
|
if (!hasCli) {
|
|
@@ -64,7 +66,7 @@ async function runAppleWizardWithTelementry(
|
|
|
64
66
|
}
|
|
65
67
|
|
|
66
68
|
const projectDir = process.cwd();
|
|
67
|
-
const xcodeProjFiles =
|
|
69
|
+
const xcodeProjFiles = searchXcodeProject(projectDir);
|
|
68
70
|
|
|
69
71
|
if (!xcodeProjFiles || xcodeProjFiles.length === 0) {
|
|
70
72
|
clack.log.error(
|
|
@@ -92,42 +94,79 @@ async function runAppleWizardWithTelementry(
|
|
|
92
94
|
}
|
|
93
95
|
|
|
94
96
|
const pbxproj = path.join(projectDir, xcodeProjFile, 'project.pbxproj');
|
|
97
|
+
|
|
95
98
|
if (!fs.existsSync(pbxproj)) {
|
|
96
|
-
clack.log.error(`No pbxproj found at ${
|
|
99
|
+
clack.log.error(`No pbxproj found at ${xcodeProjFile}`);
|
|
100
|
+
await abort();
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const { project, apiKey } = await getSentryProjectAndApiKey(options);
|
|
105
|
+
|
|
106
|
+
const xcProject = new XcodeProject(pbxproj);
|
|
107
|
+
|
|
108
|
+
const availableTargets = xcProject.getAllTargets();
|
|
109
|
+
|
|
110
|
+
if (availableTargets.length == 0) {
|
|
111
|
+
clack.log.error(`No suttable target found in ${xcodeProjFile}`);
|
|
97
112
|
await abort();
|
|
98
113
|
return;
|
|
99
114
|
}
|
|
100
115
|
|
|
101
|
-
const
|
|
102
|
-
|
|
103
|
-
|
|
116
|
+
const target =
|
|
117
|
+
availableTargets.length == 1
|
|
118
|
+
? availableTargets[0]
|
|
119
|
+
: (
|
|
120
|
+
await traceStep('Choose target', () =>
|
|
121
|
+
askForItemSelection(
|
|
122
|
+
availableTargets,
|
|
123
|
+
'Which target do you want to add Sentry to?',
|
|
124
|
+
),
|
|
125
|
+
)
|
|
126
|
+
).value;
|
|
127
|
+
|
|
128
|
+
SentryUtils.createSentryCLIRC(projectDir, { auth_token: apiKey.token });
|
|
129
|
+
clack.log.info(
|
|
130
|
+
'We created a ".sentryclirc" file in your project directory in order to provide an auth token for Sentry CLI.\nIt was also added to your ".gitignore" file.\nAt your CI enviroment, you can set the SENTRY_AUTH_TOKEN environment variable instead. See https://docs.sentry.io/cli/configuration/#auth-token for more information.',
|
|
104
131
|
);
|
|
105
132
|
|
|
106
|
-
|
|
133
|
+
let hasCocoa = cocoapod.usesCocoaPod(projectDir);
|
|
107
134
|
|
|
108
135
|
if (hasCocoa) {
|
|
109
|
-
const
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
136
|
+
const pm = (
|
|
137
|
+
await traceStep('Choose a package manager', () =>
|
|
138
|
+
askForItemSelection(
|
|
139
|
+
['Swift Package Manager', 'CocoaPods'],
|
|
140
|
+
'Which package manager would you like to use to add Sentry?',
|
|
141
|
+
),
|
|
142
|
+
)
|
|
143
|
+
).value;
|
|
144
|
+
|
|
145
|
+
hasCocoa = pm === 'CocoaPods';
|
|
146
|
+
if (hasCocoa) {
|
|
147
|
+
const podAdded = await traceStep('Add CocoaPods reference', () =>
|
|
148
|
+
cocoapod.addCocoaPods(projectDir),
|
|
115
149
|
);
|
|
150
|
+
if (!podAdded) {
|
|
151
|
+
clack.log.warn(
|
|
152
|
+
"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",
|
|
153
|
+
);
|
|
154
|
+
}
|
|
116
155
|
}
|
|
117
156
|
}
|
|
118
157
|
|
|
119
158
|
traceStep('Update Xcode project', () => {
|
|
120
|
-
|
|
159
|
+
xcProject.updateXcodeProject(project, target, apiKey, !hasCocoa, true);
|
|
121
160
|
});
|
|
122
161
|
|
|
123
162
|
Sentry.setTag('package-manager', hasCocoa ? 'cocoapods' : 'SPM');
|
|
124
|
-
const projSource = path.join(
|
|
125
|
-
projectDir,
|
|
126
|
-
xcodeProjFile.replace('.xcodeproj', ''),
|
|
127
|
-
);
|
|
128
163
|
const codeAdded = traceStep('Add code snippet', () => {
|
|
164
|
+
const files = xcProject.filesForTarget(target);
|
|
165
|
+
if (files === undefined || files.length == 0) return false;
|
|
166
|
+
|
|
129
167
|
return codeTools.addCodeSnippetToProject(
|
|
130
|
-
|
|
168
|
+
projectDir,
|
|
169
|
+
files,
|
|
131
170
|
project.keys[0].dsn.public,
|
|
132
171
|
);
|
|
133
172
|
});
|
|
@@ -144,35 +183,74 @@ async function runAppleWizardWithTelementry(
|
|
|
144
183
|
'Found a Fastfile in your project. Do you want to configure a lane to upload debug symbols to Sentry?',
|
|
145
184
|
});
|
|
146
185
|
if (addLane) {
|
|
147
|
-
await traceStep('Configure fastlane', () =>
|
|
186
|
+
const added = await traceStep('Configure fastlane', () =>
|
|
148
187
|
fastlane.addSentryToFastlane(
|
|
149
188
|
projectDir,
|
|
150
189
|
project.organization.slug,
|
|
151
190
|
project.slug,
|
|
152
|
-
apiKey.token,
|
|
153
191
|
),
|
|
154
192
|
);
|
|
193
|
+
if (added) {
|
|
194
|
+
clack.log.step(
|
|
195
|
+
'A new step was added to your fastlane file. Now and you build your project with fastlane, debug symbols and source context will be uploaded to Sentry.',
|
|
196
|
+
);
|
|
197
|
+
} else {
|
|
198
|
+
clack.log.warn(
|
|
199
|
+
'Could not edit your fastlane file to upload debug symbols to Sentry. Please follow the instructions at https://docs.sentry.io/platforms/apple/guides/ios/dsym/#fastlane',
|
|
200
|
+
);
|
|
201
|
+
}
|
|
155
202
|
}
|
|
156
203
|
}
|
|
157
204
|
|
|
158
|
-
clack.log.success(
|
|
205
|
+
clack.log.success(
|
|
206
|
+
'Sentry was successfully added to your project! Run your project to send your first event to Sentry. Go to Sentry.io to see whether everything is working fine.',
|
|
207
|
+
);
|
|
159
208
|
}
|
|
160
209
|
|
|
161
210
|
//Prompt for Sentry project and API key
|
|
162
211
|
async function getSentryProjectAndApiKey(
|
|
163
|
-
|
|
164
|
-
url?: string,
|
|
212
|
+
options: WizardOptions,
|
|
165
213
|
): Promise<{ project: SentryProjectData; apiKey: { token: string } }> {
|
|
166
|
-
const {
|
|
214
|
+
const { selectedProject, authToken } = await getOrAskForProjectData(options);
|
|
215
|
+
return { project: selectedProject, apiKey: { token: authToken } };
|
|
216
|
+
}
|
|
167
217
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
}
|
|
218
|
+
function searchXcodeProject(at: string): string[] {
|
|
219
|
+
const projs = findFilesWithExtension(at, '.xcodeproj');
|
|
220
|
+
if (projs.length > 0) {
|
|
221
|
+
return projs;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
const workspace = findFilesWithExtension(at, '.xcworkspace');
|
|
225
|
+
if (workspace.length == 0) {
|
|
226
|
+
return [];
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
const xsworkspacedata = path.join(
|
|
230
|
+
at,
|
|
231
|
+
workspace[0],
|
|
232
|
+
'contents.xcworkspacedata',
|
|
233
|
+
);
|
|
234
|
+
if (!fs.existsSync(xsworkspacedata)) {
|
|
235
|
+
return [];
|
|
236
|
+
}
|
|
237
|
+
const groupRegex = /location *= *"group:([^"]+)"/gim;
|
|
238
|
+
const content = fs.readFileSync(xsworkspacedata, 'utf8');
|
|
239
|
+
let matches = groupRegex.exec(content);
|
|
173
240
|
|
|
174
|
-
|
|
175
|
-
|
|
241
|
+
while (matches) {
|
|
242
|
+
const group = matches[1];
|
|
243
|
+
const groupPath = path.join(at, group);
|
|
244
|
+
if (
|
|
245
|
+
!group.endsWith('Pods.xcodeproj') &&
|
|
246
|
+
group.endsWith('.xcodeproj') &&
|
|
247
|
+
fs.existsSync(groupPath)
|
|
248
|
+
) {
|
|
249
|
+
projs.push(group);
|
|
250
|
+
}
|
|
251
|
+
matches = groupRegex.exec(content);
|
|
252
|
+
}
|
|
253
|
+
return projs;
|
|
176
254
|
}
|
|
177
255
|
|
|
178
256
|
//find files with the given extension
|
package/src/apple/cocoapod.ts
CHANGED
|
@@ -42,14 +42,17 @@ export async function addCocoaPods(projPath: string): Promise<boolean> {
|
|
|
42
42
|
|
|
43
43
|
const loginSpinner = clack.spinner();
|
|
44
44
|
|
|
45
|
+
clack.log.step('Sentry pod added to the project podFile.');
|
|
45
46
|
loginSpinner.start("Running 'pod install'. This may take a few minutes...");
|
|
46
47
|
|
|
47
48
|
try {
|
|
48
49
|
await bash.execute('pod install --silent');
|
|
49
|
-
loginSpinner.stop('
|
|
50
|
+
loginSpinner.stop('Running "pod install"');
|
|
50
51
|
} catch (e) {
|
|
51
|
-
|
|
52
|
-
|
|
52
|
+
loginSpinner.stop('Running "pod install"');
|
|
53
|
+
clack.log.error(
|
|
54
|
+
'Failed to run "pod install". You can run it manually for more details.',
|
|
55
|
+
);
|
|
53
56
|
Sentry.captureException('Sentry pod install failed.');
|
|
54
57
|
}
|
|
55
58
|
|
package/src/apple/code-tools.ts
CHANGED
|
@@ -2,12 +2,14 @@ import * as fs from 'fs';
|
|
|
2
2
|
import * as path from 'path';
|
|
3
3
|
import * as templates from './templates';
|
|
4
4
|
import * as Sentry from '@sentry/node';
|
|
5
|
+
// @ts-ignore - clack is ESM and TS complains about that. It works though
|
|
6
|
+
import clack from '@clack/prompts';
|
|
5
7
|
|
|
6
8
|
const swiftAppLaunchRegex =
|
|
7
|
-
/(func\s+application\s*\(_\sapplication:[^,]+,\s*didFinishLaunchingWithOptions[^,]+:[^)]+\)\s+->\s+Bool\s+{)|(
|
|
9
|
+
/(func\s+application\s*\(_\sapplication:[^,]+,\s*didFinishLaunchingWithOptions[^,]+:[^)]+\)\s+->\s+Bool\s+{)|func\s+applicationDidFinishLaunching\(_\s+aNotification:\s+Notification\)\s+{/im;
|
|
8
10
|
const objcAppLaunchRegex =
|
|
9
11
|
/-\s*\(BOOL\)\s*application:\s*\(UIApplication\s*\*\)\s*application\s+didFinishLaunchingWithOptions:\s*\(NSDictionary\s*\*\)\s*launchOptions\s*{/im;
|
|
10
|
-
const swiftUIRegex =
|
|
12
|
+
const swiftUIRegex = /@main\s+struct[^:]+:\s*App\s*{/im;
|
|
11
13
|
|
|
12
14
|
function isAppDelegateFile(filePath: string): boolean {
|
|
13
15
|
const appLaunchRegex = filePath.toLowerCase().endsWith('.swift')
|
|
@@ -18,34 +20,41 @@ function isAppDelegateFile(filePath: string): boolean {
|
|
|
18
20
|
return appLaunchRegex.test(fileContent) || swiftUIRegex.test(fileContent);
|
|
19
21
|
}
|
|
20
22
|
|
|
21
|
-
function findAppDidFinishLaunchingWithOptions(
|
|
22
|
-
|
|
23
|
+
function findAppDidFinishLaunchingWithOptions(
|
|
24
|
+
dir: string,
|
|
25
|
+
files: string[] | undefined = undefined,
|
|
26
|
+
): string | null {
|
|
27
|
+
if (!files) {
|
|
28
|
+
files = fs.readdirSync(dir);
|
|
29
|
+
files = files.map((f) => path.join(dir, f));
|
|
30
|
+
}
|
|
31
|
+
|
|
23
32
|
//iterate over subdirectories later,
|
|
24
33
|
//the appdelegate usually is in the top level
|
|
25
34
|
const dirs: string[] = [];
|
|
26
35
|
|
|
27
|
-
for (const
|
|
28
|
-
const filePath = path.join(dir, file);
|
|
36
|
+
for (const filePath of files) {
|
|
29
37
|
if (
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
38
|
+
filePath.endsWith('.swift') ||
|
|
39
|
+
filePath.endsWith('.m') ||
|
|
40
|
+
filePath.endsWith('.mm')
|
|
33
41
|
) {
|
|
34
|
-
if (isAppDelegateFile(filePath)) {
|
|
42
|
+
if (fs.existsSync(filePath) && isAppDelegateFile(filePath)) {
|
|
35
43
|
return filePath;
|
|
36
44
|
}
|
|
37
45
|
} else if (
|
|
38
|
-
!
|
|
39
|
-
!
|
|
40
|
-
!
|
|
46
|
+
!filePath.startsWith('.') &&
|
|
47
|
+
!filePath.endsWith('.xcodeproj') &&
|
|
48
|
+
!filePath.endsWith('.xcassets') &&
|
|
49
|
+
fs.existsSync(filePath) &&
|
|
41
50
|
fs.lstatSync(filePath).isDirectory()
|
|
42
51
|
) {
|
|
43
|
-
dirs.push(
|
|
52
|
+
dirs.push(filePath);
|
|
44
53
|
}
|
|
45
54
|
}
|
|
46
55
|
|
|
47
56
|
for (const dr of dirs) {
|
|
48
|
-
const result = findAppDidFinishLaunchingWithOptions(
|
|
57
|
+
const result = findAppDidFinishLaunchingWithOptions(dr);
|
|
49
58
|
if (result) return result;
|
|
50
59
|
}
|
|
51
60
|
return null;
|
|
@@ -53,9 +62,10 @@ function findAppDidFinishLaunchingWithOptions(dir: string): string | null {
|
|
|
53
62
|
|
|
54
63
|
export function addCodeSnippetToProject(
|
|
55
64
|
projPath: string,
|
|
65
|
+
files: string[],
|
|
56
66
|
dsn: string,
|
|
57
67
|
): boolean {
|
|
58
|
-
const appDelegate = findAppDidFinishLaunchingWithOptions(projPath);
|
|
68
|
+
const appDelegate = findAppDidFinishLaunchingWithOptions(projPath, files);
|
|
59
69
|
if (!appDelegate) {
|
|
60
70
|
return false;
|
|
61
71
|
}
|
|
@@ -77,6 +87,9 @@ export function addCodeSnippetToProject(
|
|
|
77
87
|
|
|
78
88
|
if (fileContent.includes(checkForSentryInit)) {
|
|
79
89
|
//already initialized
|
|
90
|
+
clack.log.info(
|
|
91
|
+
'Sentry is already initialized in your AppDelegate. Skipping adding the code snippet.',
|
|
92
|
+
);
|
|
80
93
|
return true;
|
|
81
94
|
}
|
|
82
95
|
|
|
@@ -92,13 +105,28 @@ export function addCodeSnippetToProject(
|
|
|
92
105
|
}
|
|
93
106
|
|
|
94
107
|
const insertIndex = match.index + match[0].length;
|
|
95
|
-
|
|
96
|
-
(fileContent.indexOf(importStatement) >= 0 ? '' : importStatement) +
|
|
108
|
+
let newFileContent =
|
|
97
109
|
fileContent.slice(0, insertIndex) +
|
|
98
110
|
'\n' +
|
|
99
111
|
codeSnippet +
|
|
100
112
|
fileContent.slice(insertIndex);
|
|
113
|
+
|
|
114
|
+
if (newFileContent.indexOf(importStatement) < 0) {
|
|
115
|
+
const firstImport = /^[ \t]*import +\w+.*$/m.exec(newFileContent);
|
|
116
|
+
if (firstImport) {
|
|
117
|
+
const importIndex = firstImport.index + firstImport[0].length;
|
|
118
|
+
newFileContent =
|
|
119
|
+
newFileContent.slice(0, importIndex) +
|
|
120
|
+
'\n' +
|
|
121
|
+
importStatement +
|
|
122
|
+
newFileContent.slice(importIndex);
|
|
123
|
+
} else {
|
|
124
|
+
newFileContent = importStatement + newFileContent;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
101
128
|
fs.writeFileSync(appDelegate, newFileContent, 'utf8');
|
|
102
129
|
|
|
130
|
+
clack.log.step('Added Sentry initialization code snippet to ' + appDelegate);
|
|
103
131
|
return true;
|
|
104
132
|
}
|
package/src/apple/fastlane.ts
CHANGED
|
@@ -2,6 +2,8 @@ import * as fs from 'fs';
|
|
|
2
2
|
import * as path from 'path';
|
|
3
3
|
import * as templates from './templates';
|
|
4
4
|
import { askForItemSelection } from '../utils/clack-utils';
|
|
5
|
+
// @ts-ignore - clack is ESM and TS complains about that. It works though
|
|
6
|
+
import clack from '@clack/prompts';
|
|
5
7
|
|
|
6
8
|
export function fastFile(projectPath: string): string | null {
|
|
7
9
|
const fastlanePath = path.join(projectPath, 'fastlane', 'Fastfile');
|
|
@@ -75,7 +77,6 @@ function addSentryToLane(
|
|
|
75
77
|
lane: { index: number; length: number; name: string },
|
|
76
78
|
org: string,
|
|
77
79
|
project: string,
|
|
78
|
-
token: string,
|
|
79
80
|
): string {
|
|
80
81
|
const laneContent = content.slice(lane.index, lane.index + lane.length);
|
|
81
82
|
const sentryCLIMatch = /sentry_cli\s*\([^)]+\)/gim.exec(laneContent);
|
|
@@ -83,7 +84,7 @@ function addSentryToLane(
|
|
|
83
84
|
// Sentry already added to lane. Update it.
|
|
84
85
|
return (
|
|
85
86
|
content.slice(0, sentryCLIMatch.index + lane.index) +
|
|
86
|
-
templates.getFastlaneSnippet(org, project
|
|
87
|
+
templates.getFastlaneSnippet(org, project).trim() +
|
|
87
88
|
content.slice(
|
|
88
89
|
sentryCLIMatch.index + sentryCLIMatch[0].length + lane.index,
|
|
89
90
|
)
|
|
@@ -94,7 +95,7 @@ function addSentryToLane(
|
|
|
94
95
|
return (
|
|
95
96
|
content.slice(0, lane.index + lane.length) +
|
|
96
97
|
'\n' +
|
|
97
|
-
templates.getFastlaneSnippet(org, project
|
|
98
|
+
templates.getFastlaneSnippet(org, project) +
|
|
98
99
|
'\n' +
|
|
99
100
|
content.slice(lane.index + lane.length)
|
|
100
101
|
);
|
|
@@ -104,7 +105,6 @@ export async function addSentryToFastlane(
|
|
|
104
105
|
projectPath: string,
|
|
105
106
|
org: string,
|
|
106
107
|
project: string,
|
|
107
|
-
token: string,
|
|
108
108
|
): Promise<boolean> {
|
|
109
109
|
const fastFilePath = fastFile(projectPath);
|
|
110
110
|
if (!fastFilePath) {
|
|
@@ -125,18 +125,13 @@ export async function addSentryToFastlane(
|
|
|
125
125
|
lanes?.forEach((l) => (l.index += platform.index));
|
|
126
126
|
|
|
127
127
|
if (!lanes || lanes.length === 0) {
|
|
128
|
+
clack.log.warn('No suitable lanes in your Fastfile.');
|
|
128
129
|
return false;
|
|
129
130
|
}
|
|
130
131
|
|
|
131
132
|
let newFileContent: string | undefined;
|
|
132
133
|
if (lanes.length === 1) {
|
|
133
|
-
newFileContent = addSentryToLane(
|
|
134
|
-
fileContent,
|
|
135
|
-
lanes[0],
|
|
136
|
-
org,
|
|
137
|
-
project,
|
|
138
|
-
token,
|
|
139
|
-
);
|
|
134
|
+
newFileContent = addSentryToLane(fileContent, lanes[0], org, project);
|
|
140
135
|
} else {
|
|
141
136
|
const laneNames = lanes.map((l) => l.name);
|
|
142
137
|
const selectedLane = await askForItemSelection(
|
|
@@ -151,7 +146,6 @@ export async function addSentryToFastlane(
|
|
|
151
146
|
lanes[selectedLane.index],
|
|
152
147
|
org,
|
|
153
148
|
project,
|
|
154
|
-
token,
|
|
155
149
|
);
|
|
156
150
|
}
|
|
157
151
|
|
package/src/apple/templates.ts
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
export function getRunScriptTemplate(
|
|
2
2
|
orgSlug: string,
|
|
3
3
|
projectSlug: string,
|
|
4
|
-
apiKey: string,
|
|
5
4
|
uploadSource = true,
|
|
6
5
|
): string {
|
|
7
6
|
// 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}\\
|
|
7
|
+
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}\\nERROR=$(sentry-cli debug-files upload ${
|
|
9
8
|
uploadSource ? '--include-sources ' : ''
|
|
10
9
|
}"$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`;
|
|
11
10
|
}
|
|
@@ -41,13 +40,8 @@ export function getObjcSnippet(dsn: string): string {
|
|
|
41
40
|
[SentrySDK captureMessage:@"This app uses Sentry!"];\n`;
|
|
42
41
|
}
|
|
43
42
|
|
|
44
|
-
export function getFastlaneSnippet(
|
|
45
|
-
org: string,
|
|
46
|
-
project: string,
|
|
47
|
-
token: string,
|
|
48
|
-
): string {
|
|
43
|
+
export function getFastlaneSnippet(org: string, project: string): string {
|
|
49
44
|
return ` sentry_cli(
|
|
50
|
-
auth_token: '${token}',
|
|
51
45
|
org_slug: '${org}',
|
|
52
46
|
project_slug: '${project}',
|
|
53
47
|
include_sources: true
|