Skip to content

Commit 11ee820

Browse files
authored
Merge branch 'develop' into anthropic-integration
2 parents d40558f + 08fb932 commit 11ee820

File tree

7 files changed

+385
-142
lines changed

7 files changed

+385
-142
lines changed

packages/react-router/src/vite/buildEnd/handleOnBuildEnd.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,10 @@ export const sentryOnBuildEnd: BuildEndHook = async ({ reactRouterConfig, viteCo
5959
if (sourceMapsUploadOptions?.enabled ?? (true && viteConfig.build.sourcemap !== false)) {
6060
// inject debugIds
6161
try {
62-
await cliInstance.execute(['sourcemaps', 'inject', reactRouterConfig.buildDirectory], debug);
62+
await cliInstance.execute(
63+
['sourcemaps', 'inject', reactRouterConfig.buildDirectory],
64+
debug ? 'rejectOnError' : false,
65+
);
6366
} catch (error) {
6467
// eslint-disable-next-line no-console
6568
console.error('[Sentry] Could not inject debug ids', error);
@@ -73,6 +76,7 @@ export const sentryOnBuildEnd: BuildEndHook = async ({ reactRouterConfig, viteCo
7376
paths: [reactRouterConfig.buildDirectory],
7477
},
7578
],
79+
live: 'rejectOnError',
7680
});
7781
} catch (error) {
7882
// eslint-disable-next-line no-console

packages/react-router/test/vite/buildEnd/handleOnBuildEnd.test.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,8 +147,10 @@ describe('sentryOnBuildEnd', () => {
147147

148148
await sentryOnBuildEnd(config);
149149

150+
expect(mockSentryCliInstance.releases.uploadSourceMaps).toHaveBeenCalledTimes(1);
150151
expect(mockSentryCliInstance.releases.uploadSourceMaps).toHaveBeenCalledWith('undefined', {
151152
include: [{ paths: ['/build'] }],
153+
live: 'rejectOnError',
152154
});
153155
});
154156

@@ -249,6 +251,8 @@ describe('sentryOnBuildEnd', () => {
249251
mockSentryCliInstance.execute.mockRejectedValueOnce(new Error('Injection failed'));
250252

251253
await sentryOnBuildEnd(defaultConfig);
254+
expect(mockSentryCliInstance.execute).toHaveBeenCalledTimes(1);
255+
expect(mockSentryCliInstance.execute).toHaveBeenCalledWith(['sourcemaps', 'inject', '/build'], false);
252256

253257
expect(consoleSpy).toHaveBeenCalledWith('[Sentry] Could not inject debug ids', expect.any(Error));
254258
consoleSpy.mockRestore();
@@ -282,6 +286,9 @@ describe('sentryOnBuildEnd', () => {
282286

283287
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining('[Sentry] Automatically setting'));
284288
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining('Deleting asset after upload:'));
289+
// rejectOnError is used in debug mode to pipe debug id injection output from the CLI to this process's stdout
290+
expect(mockSentryCliInstance.execute).toHaveBeenCalledWith(['sourcemaps', 'inject', '/build'], 'rejectOnError');
291+
285292
consoleSpy.mockRestore();
286293
});
287294

packages/sveltekit/src/vite/sourceMaps.ts

Lines changed: 82 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/* eslint-disable max-lines */
2-
import { consoleSandbox, escapeStringForRegex, uuid4 } from '@sentry/core';
2+
import { escapeStringForRegex, uuid4 } from '@sentry/core';
33
import { getSentryRelease } from '@sentry/node';
44
import type { SentryVitePluginOptions } from '@sentry/vite-plugin';
55
import { sentryVitePlugin } from '@sentry/vite-plugin';
@@ -27,6 +27,8 @@ type Sorcery = {
2727
// and we only want to generate a uuid once in case we have to fall back to it.
2828
const releaseName = detectSentryRelease();
2929

30+
type FilesToDeleteAfterUpload = string | string[] | undefined;
31+
3032
/**
3133
* Creates a new Vite plugin that uses the unplugin-based Sentry Vite plugin to create
3234
* releases and upload source maps to Sentry.
@@ -60,8 +62,12 @@ export async function makeCustomSentryVitePlugins(options?: CustomSentryVitePlug
6062
},
6163
};
6264

63-
const { promise: filesToDeleteAfterUpload, resolve: resolveFilesToDeleteAfterUpload } =
64-
createFilesToDeleteAfterUploadPromise();
65+
let _resolveFilesToDeleteAfterUpload:
66+
| undefined
67+
| ((value: FilesToDeleteAfterUpload | Promise<FilesToDeleteAfterUpload>) => void);
68+
const filesToDeleteAfterUploadPromise = new Promise<FilesToDeleteAfterUpload>(resolve => {
69+
_resolveFilesToDeleteAfterUpload = resolve;
70+
});
6571

6672
const mergedOptions = {
6773
...defaultPluginOptions,
@@ -72,7 +78,7 @@ export async function makeCustomSentryVitePlugins(options?: CustomSentryVitePlug
7278
},
7379
sourcemaps: {
7480
...options?.sourcemaps,
75-
filesToDeleteAfterUpload,
81+
filesToDeleteAfterUpload: filesToDeleteAfterUploadPromise,
7682
},
7783
};
7884

@@ -100,7 +106,7 @@ export async function makeCustomSentryVitePlugins(options?: CustomSentryVitePlug
100106
);
101107

102108
// resolving filesToDeleteAfterUpload here, because we return the original deletion plugin which awaits the promise
103-
resolveFilesToDeleteAfterUpload(undefined);
109+
_resolveFilesToDeleteAfterUpload?.(undefined);
104110

105111
return sentryPlugins;
106112
}
@@ -113,7 +119,7 @@ export async function makeCustomSentryVitePlugins(options?: CustomSentryVitePlug
113119
);
114120

115121
// resolving filesToDeleteAfterUpload here, because we return the original deletion plugin which awaits the promise
116-
resolveFilesToDeleteAfterUpload(undefined);
122+
_resolveFilesToDeleteAfterUpload?.(undefined);
117123

118124
return sentryPlugins;
119125
}
@@ -126,7 +132,7 @@ export async function makeCustomSentryVitePlugins(options?: CustomSentryVitePlug
126132
);
127133

128134
// resolving filesToDeleteAfterUpload here, because we return the original deletion plugin which awaits the promise
129-
resolveFilesToDeleteAfterUpload(undefined);
135+
_resolveFilesToDeleteAfterUpload?.(undefined);
130136

131137
return sentryPlugins;
132138
}
@@ -153,64 +159,40 @@ export async function makeCustomSentryVitePlugins(options?: CustomSentryVitePlug
153159
name: 'sentry-sveltekit-update-source-map-setting-plugin',
154160
apply: 'build', // only apply this plugin at build time
155161
config: async (config: UserConfig) => {
156-
const settingKey = 'build.sourcemap';
157-
158-
const { updatedSourceMapSetting, previousSourceMapSetting } = getUpdatedSourceMapSetting(config);
159-
160-
const userProvidedFilesToDeleteAfterUpload = await options?.sourcemaps?.filesToDeleteAfterUpload;
161-
162-
if (previousSourceMapSetting === 'unset') {
163-
consoleSandbox(() => {
164-
// eslint-disable-next-line no-console
165-
console.log(`[Sentry] Enabled source map generation in the build options with \`${settingKey}: "hidden"\`.`);
166-
});
167-
168-
if (userProvidedFilesToDeleteAfterUpload) {
169-
resolveFilesToDeleteAfterUpload(userProvidedFilesToDeleteAfterUpload);
170-
} else {
171-
// Including all hidden (`.*`) directories by default so that folders like .vercel,
172-
// .netlify, etc are also cleaned up. Additionally, we include the adapter output
173-
// dir which could be a non-hidden directory, like `build` for the Node adapter.
174-
const defaultFileDeletionGlob = ['./.*/**/*.map', `./${adapterOutputDir}/**/*.map`];
175-
176-
consoleSandbox(() => {
177-
// eslint-disable-next-line no-console
178-
console.warn(
179-
`[Sentry] Automatically setting \`sourceMapsUploadOptions.sourcemaps.filesToDeleteAfterUpload: [${defaultFileDeletionGlob
180-
.map(file => `"${file}"`)
181-
.join(', ')}]\` to delete generated source maps after they were uploaded to Sentry.`,
182-
);
183-
});
162+
return {
163+
...config,
164+
build: {
165+
...config.build,
166+
sourcemap: _getUpdatedSourceMapSettings(config, options),
167+
},
168+
};
169+
},
170+
};
184171

185-
// In case we enabled source maps and users didn't specify a glob patter to delete, we set a default pattern:
186-
resolveFilesToDeleteAfterUpload(defaultFileDeletionGlob);
187-
}
172+
const filesToDeleteAfterUploadConfigPlugin: Plugin = {
173+
name: 'sentry-sveltekit-files-to-delete-after-upload-setting-plugin',
174+
apply: 'build', // only apply this plugin at build time
175+
config: (config: UserConfig) => {
176+
const originalFilesToDeleteAfterUpload = options?.sourcemaps?.filesToDeleteAfterUpload;
188177

189-
return {
190-
...config,
191-
build: { ...config.build, sourcemap: updatedSourceMapSetting },
192-
};
193-
}
178+
if (typeof originalFilesToDeleteAfterUpload === 'undefined' && typeof config.build?.sourcemap === 'undefined') {
179+
// Including all hidden (`.*`) directories by default so that folders like .vercel,
180+
// .netlify, etc are also cleaned up. Additionally, we include the adapter output
181+
// dir which could be a non-hidden directory, like `build` for the Node adapter.
182+
const defaultFileDeletionGlob = ['./.*/**/*.map', `./${adapterOutputDir}/**/*.map`];
194183

195-
if (previousSourceMapSetting === 'disabled') {
196-
consoleSandbox(() => {
197-
// eslint-disable-next-line no-console
198-
console.warn(
199-
`[Sentry] Parts of source map generation are currently disabled in your Vite configuration (\`${settingKey}: false\`). This setting is either a default setting or was explicitly set in your configuration. Sentry won't override this setting. Without source maps, code snippets on the Sentry Issues page will remain minified. To show unminified code, enable source maps in \`${settingKey}\` (e.g. by setting them to \`hidden\`).`,
184+
debug &&
185+
// eslint-disable-next-line no-console
186+
console.info(
187+
`[Sentry] Automatically setting \`sourceMapsUploadOptions.sourcemaps.filesToDeleteAfterUpload: [${defaultFileDeletionGlob
188+
.map(file => `"${file}"`)
189+
.join(', ')}]\` to delete generated source maps after they were uploaded to Sentry.`,
200190
);
201-
});
202-
} else if (previousSourceMapSetting === 'enabled') {
203-
if (mergedOptions?.debug) {
204-
consoleSandbox(() => {
205-
// eslint-disable-next-line no-console
206-
console.log(
207-
`[Sentry] We discovered you enabled source map generation in your Vite configuration (\`${settingKey}\`). Sentry will keep this source map setting. This will un-minify the code snippet on the Sentry Issue page.`,
208-
);
209-
});
210-
}
211-
}
212191

213-
resolveFilesToDeleteAfterUpload(userProvidedFilesToDeleteAfterUpload);
192+
_resolveFilesToDeleteAfterUpload?.(defaultFileDeletionGlob);
193+
} else {
194+
_resolveFilesToDeleteAfterUpload?.(originalFilesToDeleteAfterUpload);
195+
}
214196

215197
return config;
216198
},
@@ -390,18 +372,14 @@ export async function makeCustomSentryVitePlugins(options?: CustomSentryVitePlug
390372
return [
391373
...unchangedSentryVitePlugins,
392374
sourceMapSettingsPlugin,
375+
filesToDeleteAfterUploadConfigPlugin,
393376
customReleaseManagementPlugin,
394377
customDebugIdUploadPlugin,
395378
customFileDeletionPlugin,
396379
];
397380
}
398381

399-
/**
400-
* Whether the user enabled (true, 'hidden', 'inline') or disabled (false) source maps
401-
*/
402-
type UserSourceMapSetting = 'enabled' | 'disabled' | 'unset' | undefined;
403-
404-
/** There are 3 ways to set up source map generation (https://github.com/getsentry/sentry-javascript/issues/13993)
382+
/** There are 3 ways to set up source map generation (https://github.com/getsentry/sentry-j avascript/issues/13993)
405383
*
406384
* 1. User explicitly disabled source maps
407385
* - keep this setting (emit a warning that errors won't be unminified in Sentry)
@@ -416,30 +394,50 @@ type UserSourceMapSetting = 'enabled' | 'disabled' | 'unset' | undefined;
416394
*
417395
* --> only exported for testing
418396
*/
419-
export function getUpdatedSourceMapSetting(viteConfig: {
420-
build?: {
421-
sourcemap?: boolean | 'inline' | 'hidden';
422-
};
423-
}): { updatedSourceMapSetting: boolean | 'inline' | 'hidden'; previousSourceMapSetting: UserSourceMapSetting } {
397+
export function _getUpdatedSourceMapSettings(
398+
viteConfig: UserConfig,
399+
sentryPluginOptions?: CustomSentryVitePluginOptions,
400+
): boolean | 'inline' | 'hidden' {
424401
viteConfig.build = viteConfig.build || {};
425402

426-
const originalSourcemapSetting = viteConfig.build.sourcemap;
403+
const viteSourceMap = viteConfig?.build?.sourcemap;
404+
let updatedSourceMapSetting = viteSourceMap;
427405

428-
if (originalSourcemapSetting === false) {
429-
return {
430-
previousSourceMapSetting: 'disabled',
431-
updatedSourceMapSetting: originalSourcemapSetting,
432-
};
433-
}
406+
const settingKey = 'build.sourcemap';
407+
const debug = sentryPluginOptions?.debug;
408+
409+
if (viteSourceMap === false) {
410+
updatedSourceMapSetting = viteSourceMap;
411+
412+
if (debug) {
413+
// Longer debug message with more details
414+
// eslint-disable-next-line no-console
415+
console.warn(
416+
`[Sentry] Source map generation is currently disabled in your Vite configuration (\`${settingKey}: false \`). This setting is either a default setting or was explicitly set in your configuration. Sentry won't override this setting. Without source maps, code snippets on the Sentry Issues page will remain minified. To show unminified code, enable source maps in \`${settingKey}\` (e.g. by setting them to \`hidden\`).`,
417+
);
418+
} else {
419+
// eslint-disable-next-line no-console
420+
console.warn('[Sentry] Source map generation is disabled in your Vite configuration.');
421+
}
422+
} else if (viteSourceMap && ['hidden', 'inline', true].includes(viteSourceMap)) {
423+
updatedSourceMapSetting = viteSourceMap;
424+
425+
debug &&
426+
// eslint-disable-next-line no-console
427+
console.log(
428+
`[Sentry] We discovered \`${settingKey}\` is set to \`${viteSourceMap.toString()}\`. Sentry will keep this source map setting. This will un-minify the code snippet on the Sentry Issue page.`,
429+
);
430+
} else {
431+
updatedSourceMapSetting = 'hidden';
434432

435-
if (originalSourcemapSetting && ['hidden', 'inline', true].includes(originalSourcemapSetting)) {
436-
return { previousSourceMapSetting: 'enabled', updatedSourceMapSetting: originalSourcemapSetting };
433+
debug &&
434+
// eslint-disable-next-line no-console
435+
console.log(
436+
`[Sentry] Enabled source map generation in the build options with \`${settingKey}: 'hidden'\`. The source maps will be deleted after they were uploaded to Sentry.`,
437+
);
437438
}
438439

439-
return {
440-
previousSourceMapSetting: 'unset',
441-
updatedSourceMapSetting: 'hidden',
442-
};
440+
return updatedSourceMapSetting;
443441
}
444442

445443
function getFiles(dir: string): string[] {
@@ -475,22 +473,3 @@ function detectSentryRelease(): string {
475473

476474
return release;
477475
}
478-
479-
/**
480-
* Creates a deferred promise that can be resolved/rejected by calling the
481-
* `resolve` or `reject` function.
482-
* Inspired by: https://stackoverflow.com/a/69027809
483-
*/
484-
function createFilesToDeleteAfterUploadPromise(): {
485-
promise: Promise<string | string[] | undefined>;
486-
resolve: (value: string | string[] | undefined) => void;
487-
reject: (reason?: unknown) => void;
488-
} {
489-
let resolve!: (value: string | string[] | undefined) => void;
490-
let reject!: (reason?: unknown) => void;
491-
const promise = new Promise<string | string[] | undefined>((res, rej) => {
492-
resolve = res;
493-
reject = rej;
494-
});
495-
return { resolve, reject, promise };
496-
}

packages/sveltekit/test/vite/sentrySvelteKitPlugins.test.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ describe('sentrySvelteKit()', () => {
4242

4343
expect(plugins).toBeInstanceOf(Array);
4444
// 1 auto instrument plugin + 5 source maps plugins
45-
expect(plugins).toHaveLength(8);
45+
expect(plugins).toHaveLength(9);
4646
});
4747

4848
it('returns the custom sentry source maps upload plugin, unmodified sourcemaps plugins and the auto-instrument plugin by default', async () => {
@@ -56,6 +56,7 @@ describe('sentrySvelteKit()', () => {
5656
'sentry-vite-release-injection-plugin',
5757
'sentry-vite-debug-id-injection-plugin',
5858
'sentry-sveltekit-update-source-map-setting-plugin',
59+
'sentry-sveltekit-files-to-delete-after-upload-setting-plugin',
5960
// custom release plugin:
6061
'sentry-sveltekit-release-management-plugin',
6162
// custom source maps plugin:
@@ -86,7 +87,7 @@ describe('sentrySvelteKit()', () => {
8687
it("doesn't return the auto instrument plugin if autoInstrument is `false`", async () => {
8788
const plugins = await getSentrySvelteKitPlugins({ autoInstrument: false });
8889
const pluginNames = plugins.map(plugin => plugin.name);
89-
expect(plugins).toHaveLength(7);
90+
expect(plugins).toHaveLength(8);
9091
expect(pluginNames).not.toContain('sentry-upload-source-maps');
9192
});
9293

@@ -184,7 +185,7 @@ describe('sentrySvelteKit()', () => {
184185
// just to ignore the source maps plugin:
185186
autoUploadSourceMaps: false,
186187
});
187-
const plugin = plugins[0];
188+
const plugin = plugins[0]!;
188189

189190
expect(plugin.name).toEqual('sentry-auto-instrumentation');
190191
expect(makePluginSpy).toHaveBeenCalledWith({

0 commit comments

Comments
 (0)