Skip to content

Commit 770cbe1

Browse files
committed
use plugins only for release
1 parent 52c164e commit 770cbe1

File tree

8 files changed

+626
-164
lines changed

8 files changed

+626
-164
lines changed

packages/nuxt/src/module.ts

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import { consoleSandbox } from '@sentry/core';
1010
import * as path from 'path';
1111
import type { SentryNuxtModuleOptions } from './common/types';
1212
import { addDynamicImportEntryFileWrapper, addSentryTopImport, addServerConfigToBuild } from './vite/addServerConfig';
13-
import { handleBuildDoneHook } from './vite/buildEndUpload';
1413
import { addDatabaseInstrumentation } from './vite/databaseConfig';
1514
import { addMiddlewareImports, addMiddlewareInstrumentation } from './vite/middlewareConfig';
1615
import { setupSourceMaps } from './vite/sourceMaps';
@@ -214,12 +213,5 @@ export default defineNuxtModule<ModuleOptions>({
214213
}
215214
}
216215
});
217-
218-
// This ensures debug IDs are injected and source maps uploaded only once
219-
nuxt.hook('close', async () => {
220-
if (!nuxt.options.dev && (clientConfigFile || serverConfigFile)) {
221-
await handleBuildDoneHook(moduleOptions, nuxt);
222-
}
223-
});
224216
},
225217
});

packages/nuxt/src/vite/buildEndUpload.ts

Lines changed: 0 additions & 108 deletions
This file was deleted.
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
import { existsSync } from 'node:fs';
2+
import type { Nuxt } from '@nuxt/schema';
3+
import type { createSentryBuildPluginManager as createSentryBuildPluginManagerType } from '@sentry/bundler-plugin-core';
4+
import * as path from 'path';
5+
import type { SentryNuxtModuleOptions } from '../common/types';
6+
import { getPluginOptions } from './sourceMaps';
7+
8+
/**
9+
* A build-end hook that handles Sentry release creation and source map uploads.
10+
* It creates a new Sentry release if configured, uploads source maps to Sentry,
11+
* and optionally deletes the source map files after upload.
12+
*
13+
* This runs after both Vite (Nuxt) and Rollup (Nitro) builds complete, ensuring
14+
* debug IDs are injected and source maps uploaded only once.
15+
*/
16+
// eslint-disable-next-line complexity
17+
export async function handleBuildDoneHook(
18+
sentryModuleOptions: SentryNuxtModuleOptions,
19+
nuxt: Nuxt,
20+
shouldDeleteFilesFallback?: { client: boolean; server: boolean },
21+
): Promise<void> {
22+
const debug = sentryModuleOptions.debug ?? false;
23+
if (debug) {
24+
// eslint-disable-next-line no-console
25+
console.log('[Sentry] Nuxt build ended. Starting to upload build-time info to Sentry (release, source maps)...');
26+
}
27+
28+
let createSentryBuildPluginManager: typeof createSentryBuildPluginManagerType | undefined;
29+
try {
30+
const bundlerPluginCore = await import('@sentry/bundler-plugin-core');
31+
createSentryBuildPluginManager = bundlerPluginCore.createSentryBuildPluginManager;
32+
} catch (error) {
33+
debug &&
34+
// eslint-disable-next-line no-console
35+
console.warn('[Sentry] Could not load build manager package. Will not upload build-time info to Sentry.', error);
36+
return;
37+
}
38+
39+
if (!createSentryBuildPluginManager) {
40+
// eslint-disable-next-line no-console
41+
debug && console.warn('[Sentry] Could not find createSentryBuildPluginManager in bundler plugin core.');
42+
return;
43+
}
44+
45+
const outputDir = nuxt.options.nitro?.output?.dir || path.join(nuxt.options.rootDir, '.output');
46+
47+
if (!existsSync(outputDir)) {
48+
// eslint-disable-next-line no-console
49+
debug && console.warn(`[Sentry] Output directory does not exist yet: ${outputDir}. Skipping source map upload.`);
50+
return;
51+
}
52+
53+
const options = getPluginOptions(sentryModuleOptions, shouldDeleteFilesFallback, 'full');
54+
55+
// eslint-disable-next-line deprecation/deprecation
56+
const sourceMapsUploadOptions = sentryModuleOptions.sourceMapsUploadOptions || {};
57+
const sourceMapsEnabled =
58+
sentryModuleOptions.sourcemaps?.disable === true
59+
? false
60+
: sentryModuleOptions.sourcemaps?.disable === false
61+
? true
62+
: // eslint-disable-next-line deprecation/deprecation
63+
(sourceMapsUploadOptions.enabled ?? true);
64+
65+
if (sourceMapsEnabled) {
66+
const existingIgnore = options.sourcemaps?.ignore || [];
67+
const ignorePatterns = Array.isArray(existingIgnore) ? existingIgnore : [existingIgnore];
68+
69+
// node_modules source maps are ignored
70+
const nodeModulesPatterns = ['**/node_modules/**', '**/node_modules/**/*.map'];
71+
const hasNodeModulesIgnore = ignorePatterns.some(
72+
pattern => typeof pattern === 'string' && pattern.includes('node_modules'),
73+
);
74+
75+
if (!hasNodeModulesIgnore) {
76+
ignorePatterns.push(...nodeModulesPatterns);
77+
}
78+
79+
options.sourcemaps = {
80+
...options.sourcemaps,
81+
ignore: ignorePatterns.length > 0 ? ignorePatterns : undefined,
82+
};
83+
84+
if (debug && ignorePatterns.length > 0) {
85+
// eslint-disable-next-line no-console
86+
console.log(`[Sentry] Excluding patterns from source map upload: ${ignorePatterns.join(', ')}`);
87+
}
88+
}
89+
90+
try {
91+
const sentryBuildPluginManager = createSentryBuildPluginManager(options, {
92+
buildTool: 'nuxt',
93+
loggerPrefix: '[Sentry Nuxt Module]',
94+
});
95+
96+
await sentryBuildPluginManager.telemetry.emitBundlerPluginExecutionSignal();
97+
await sentryBuildPluginManager.createRelease();
98+
99+
// eslint-disable-next-line no-console
100+
debug && console.log('[Sentry] Successfully uploaded release information.');
101+
102+
if (!sourceMapsEnabled) {
103+
debug &&
104+
// eslint-disable-next-line no-console
105+
console.log('[Sentry] Source map upload is disabled. Skipping debugID injection and source map upload steps.');
106+
} else {
107+
await sentryBuildPluginManager.injectDebugIds([outputDir]);
108+
// eslint-disable-next-line no-console
109+
debug && console.log('[Sentry] Successfully injected Debug IDs.');
110+
111+
// todo: rewriteSources seems to not be applied
112+
await sentryBuildPluginManager.uploadSourcemaps([outputDir], {
113+
// We don't want to prepare the artifacts because we injected Debug IDs manually before
114+
prepareArtifacts: false,
115+
});
116+
// eslint-disable-next-line no-console
117+
debug && console.log('[Sentry] Successfully uploaded source maps.');
118+
119+
await sentryBuildPluginManager.deleteArtifacts();
120+
debug &&
121+
// eslint-disable-next-line no-console
122+
console.log(
123+
`[Sentry] Successfully deleted specified source map artifacts (${sentryModuleOptions.sourcemaps?.filesToDeleteAfterUpload ? '' : "based on Sentry's default "}\`filesToDeleteAfterUpload: [${options.sourcemaps?.filesToDeleteAfterUpload}\`]).`,
124+
);
125+
}
126+
} catch (error) {
127+
// eslint-disable-next-line no-console
128+
console.error("[Sentry] Error during Sentry's build-end hook: ", error);
129+
}
130+
}

0 commit comments

Comments
 (0)