Skip to content

feat(nitro): Handle sourcemap preparation and upload#19304

Open
logaretm wants to merge 6 commits intoawad/js-1128-nitro-use-tracing-channels-for-srvx-and-h3from
awad/js-1076-nitro-upload-sourcemaps
Open

feat(nitro): Handle sourcemap preparation and upload#19304
logaretm wants to merge 6 commits intoawad/js-1128-nitro-use-tracing-channels-for-srvx-and-h3from
awad/js-1076-nitro-upload-sourcemaps

Conversation

@logaretm
Copy link
Copy Markdown
Member

@logaretm logaretm commented Feb 12, 2026

Adds automatic sourcemap handling to the Nitro SDK, using @sentry/bundler-plugin-core for builder-agnostic post-build upload.

Nitro uses rollup or rolldown, so it made sense to make it as agnostic as possible.

Closes #17992


This PR is part of a stack:

@linear
Copy link
Copy Markdown

linear bot commented Feb 12, 2026

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Feb 12, 2026

Codecov Results 📊


Generated by Codecov Action

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Feb 12, 2026

size-limit report 📦

Path Size % Change Change
@sentry/browser 25.78 kB added added
@sentry/browser - with treeshaking flags 24.27 kB added added
@sentry/browser (incl. Tracing) 42.77 kB added added
@sentry/browser (incl. Tracing, Profiling) 47.4 kB added added
@sentry/browser (incl. Tracing, Replay) 81.69 kB added added
@sentry/browser (incl. Tracing, Replay) - with treeshaking flags 71.22 kB added added
@sentry/browser (incl. Tracing, Replay with Canvas) 86.39 kB added added
@sentry/browser (incl. Tracing, Replay, Feedback) 98.6 kB added added
@sentry/browser (incl. Feedback) 42.59 kB added added
@sentry/browser (incl. sendFeedback) 30.45 kB added added
@sentry/browser (incl. FeedbackAsync) 35.45 kB added added
@sentry/browser (incl. Metrics) 27.07 kB added added
@sentry/browser (incl. Logs) 27.2 kB added added
@sentry/browser (incl. Metrics & Logs) 27.89 kB added added
@sentry/react 27.53 kB added added
@sentry/react (incl. Tracing) 45.09 kB added added
@sentry/vue 30.61 kB added added
@sentry/vue (incl. Tracing) 44.63 kB added added
@sentry/svelte 25.8 kB added added
CDN Bundle 28.46 kB added added
CDN Bundle (incl. Tracing) 43.82 kB added added
CDN Bundle (incl. Logs, Metrics) 29.83 kB added added
CDN Bundle (incl. Tracing, Logs, Metrics) 44.89 kB added added
CDN Bundle (incl. Replay, Logs, Metrics) 68.73 kB added added
CDN Bundle (incl. Tracing, Replay) 80.78 kB added added
CDN Bundle (incl. Tracing, Replay, Logs, Metrics) 81.83 kB added added
CDN Bundle (incl. Tracing, Replay, Feedback) 86.31 kB added added
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics) 87.34 kB added added
CDN Bundle - uncompressed 83.12 kB added added
CDN Bundle (incl. Tracing) - uncompressed 129.95 kB added added
CDN Bundle (incl. Logs, Metrics) - uncompressed 87.27 kB added added
CDN Bundle (incl. Tracing, Logs, Metrics) - uncompressed 133.36 kB added added
CDN Bundle (incl. Replay, Logs, Metrics) - uncompressed 210.63 kB added added
CDN Bundle (incl. Tracing, Replay) - uncompressed 247.21 kB added added
CDN Bundle (incl. Tracing, Replay, Logs, Metrics) - uncompressed 250.6 kB added added
CDN Bundle (incl. Tracing, Replay, Feedback) - uncompressed 260.12 kB added added
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics) - uncompressed 263.51 kB added added
@sentry/nextjs (client) 47.52 kB added added
@sentry/sveltekit (client) 43.24 kB added added
@sentry/node-core 57.94 kB added added
@sentry/node 174.76 kB added added
@sentry/node - without tracing 97.8 kB added added
@sentry/aws-serverless 115.06 kB added added

@logaretm logaretm force-pushed the awad/js-1128-nitro-use-tracing-channels-for-srvx-and-h3 branch from 1923dda to be2f037 Compare February 23, 2026 14:50
@logaretm logaretm force-pushed the awad/js-1076-nitro-upload-sourcemaps branch from 0d86a79 to 9f6254a Compare February 23, 2026 14:50
@logaretm logaretm force-pushed the awad/js-1128-nitro-use-tracing-channels-for-srvx-and-h3 branch from be2f037 to 3b30e36 Compare February 23, 2026 14:52
@logaretm logaretm force-pushed the awad/js-1076-nitro-upload-sourcemaps branch from 9f6254a to 63a2175 Compare February 23, 2026 14:52
@logaretm logaretm force-pushed the awad/js-1128-nitro-use-tracing-channels-for-srvx-and-h3 branch from 3b30e36 to 36c96b6 Compare February 23, 2026 16:17
@logaretm logaretm force-pushed the awad/js-1076-nitro-upload-sourcemaps branch 2 times, most recently from d3e3ae1 to a24cad5 Compare February 23, 2026 16:23
@github-actions
Copy link
Copy Markdown
Contributor

This pull request has gone three weeks without activity. In another week, I will close it.

But! If you comment or otherwise update it, I will reset the clock, and if you apply the label PR: no-auto-close I will leave it alone ... forever!

@logaretm logaretm force-pushed the awad/js-1128-nitro-use-tracing-channels-for-srvx-and-h3 branch 2 times, most recently from 3cf1515 to 342ea3b Compare April 15, 2026 13:54
@logaretm logaretm force-pushed the awad/js-1076-nitro-upload-sourcemaps branch from a24cad5 to 1583866 Compare April 15, 2026 14:44
@logaretm logaretm force-pushed the awad/js-1128-nitro-use-tracing-channels-for-srvx-and-h3 branch from 342ea3b to 8d44437 Compare April 15, 2026 14:55
@logaretm logaretm force-pushed the awad/js-1076-nitro-upload-sourcemaps branch from 1583866 to 07659b6 Compare April 15, 2026 14:57
@logaretm logaretm force-pushed the awad/js-1076-nitro-upload-sourcemaps branch from a967e7a to 00bd835 Compare April 15, 2026 14:59
@logaretm logaretm marked this pull request as ready for review April 15, 2026 18:13
Comment on lines +42 to +48
if (options?.sourcemaps?.disable !== 'disable-upload') {
await sentryBuildPluginManager.injectDebugIds([outputDir]);
await sentryBuildPluginManager.uploadSourcemaps([outputDir], {
// We don't prepare the artifacts because we injected debug IDs manually before
prepareArtifacts: false,
});
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: When sourcemaps.disable is set to 'disable-upload', the code incorrectly skips injecting debug IDs, not just the source map upload, breaking manual upload workflows.
Severity: HIGH

Suggested Fix

Move the injectDebugIds() call out of the conditional block that checks options?.sourcemaps?.disable !== 'disable-upload'. This check should only wrap the uploadSourcemaps() call, ensuring debug IDs are injected even when automatic uploads are disabled.

Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent.
Verify if this is a real issue. If it is, propose a fix; if not, explain why it's not
valid.

Location: packages/nitro/src/sourceMaps.ts#L42-L48

Potential issue: The logic in `handleSourceMapUpload` incorrectly skips debug ID
injection when source map uploads are disabled. The condition `if
(options?.sourcemaps?.disable !== 'disable-upload')` wraps both the `injectDebugIds()`
and `uploadSourcemaps()` calls. According to documentation, when
`options.sourcemaps.disable` is set to `'disable-upload'`, the plugin should still
inject debug IDs to support manual uploads, but skip the automatic upload step. The
current implementation skips both actions, which means build artifacts will lack the
necessary debug IDs for users relying on a manual upload workflow.

Did we get this right? 👍 / 👎 to inform future reviews.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds build-time sourcemap generation + post-build sourcemap (and debug ID) handling to the @sentry/nitro SDK by wiring Nitro’s compiled hook to @sentry/bundler-plugin-core.

Changes:

  • Introduces packages/nitro/src/sourceMaps.ts to configure Nitro sourcemap settings and to run a post-build upload flow via createSentryBuildPluginManager.
  • Threads SentryNitroOptions through module setup so sourcemap behavior can be configured from withSentryConfig/setupSentryNitroModule.
  • Adds Vitest coverage for option-shaping and basic hook registration behavior.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
packages/nitro/src/sourceMaps.ts New sourcemap config + post-build hook which injects debug IDs and uploads sourcemaps via bundler-plugin-core
packages/nitro/test/sourceMaps.test.ts New unit tests for plugin option building, config mutation, and hook registration
packages/nitro/src/module.ts Passes Sentry options into module setup to enable sourcemap handling
packages/nitro/src/config.ts Defines SentryNitroOptions from bundler-plugin-core options and enables sourcemap config during module setup
packages/nitro/rollup.npm.config.mjs Marks @sentry/bundler-plugin-core as external in the package build
packages/nitro/package.json Adds @sentry/bundler-plugin-core dependency

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +42 to +48
if (options?.sourcemaps?.disable !== 'disable-upload') {
await sentryBuildPluginManager.injectDebugIds([outputDir]);
await sentryBuildPluginManager.uploadSourcemaps([outputDir], {
// We don't prepare the artifacts because we injected debug IDs manually before
prepareArtifacts: false,
});
}
Comment on lines +48 to +50
}

await sentryBuildPluginManager.deleteArtifacts();
Comment on lines +86 to +89
telemetry: {
metaFramework: 'nitro',
},
...options?._metaOptions,
Comment on lines +1 to +5
import type { Options } from '@sentry/bundler-plugin-core';
import { createSentryBuildPluginManager } from '@sentry/bundler-plugin-core';
import { debug } from '@sentry/core';
import type { Nitro, NitroConfig } from 'nitro/types';
import type { SentryNitroOptions } from './config';
Comment on lines +113 to +114
// This makes sourcemaps unusable for Sentry.
// FIXME: Not sure about this one, it works either way?
Comment on lines +218 to +277
describe('setupSourceMaps', () => {
it('does not register hook in dev mode', () => {
const hookFn = vi.fn();
const nitro = {
options: { dev: true, output: { serverDir: '/output/server' } },
hooks: { hook: hookFn },
} as any;

setupSourceMaps(nitro);

expect(hookFn).not.toHaveBeenCalled();
});

it('does not register hook when sourcemaps.disable is true', () => {
const hookFn = vi.fn();
const nitro = {
options: { dev: false, output: { serverDir: '/output/server' } },
hooks: { hook: hookFn },
} as any;

setupSourceMaps(nitro, { sourcemaps: { disable: true } });

expect(hookFn).not.toHaveBeenCalled();
});

it('does not register hook when disable is true', () => {
const hookFn = vi.fn();
const nitro = {
options: { dev: false, output: { serverDir: '/output/server' } },
hooks: { hook: hookFn },
} as any;

setupSourceMaps(nitro, { disable: true });

expect(hookFn).not.toHaveBeenCalled();
});

it('registers compiled hook in production mode', () => {
const hookFn = vi.fn();
const nitro = {
options: { dev: false, output: { serverDir: '/output/server' } },
hooks: { hook: hookFn },
} as any;

setupSourceMaps(nitro);

expect(hookFn).toHaveBeenCalledWith('compiled', expect.any(Function));
});

it('registers compiled hook with custom options', () => {
const hookFn = vi.fn();
const nitro = {
options: { dev: false, output: { serverDir: '/output/server' } },
hooks: { hook: hookFn },
} as any;

setupSourceMaps(nitro, { org: 'my-org', project: 'my-project' });

expect(hookFn).toHaveBeenCalledWith('compiled', expect.any(Function));
});
Copy link
Copy Markdown

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 3 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 973bf37. Configure here.

// We don't prepare the artifacts because we injected debug IDs manually before
prepareArtifacts: false,
});
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

disable-upload incorrectly skips debug ID injection

High Severity

When sourcemaps.disable is 'disable-upload', the condition options?.sourcemaps?.disable !== 'disable-upload' causes both injectDebugIds and uploadSourcemaps to be skipped. According to the @sentry/bundler-plugin-core documentation, disable-upload means "will not upload source maps but will inject debug IDs." The injectDebugIds call needs to happen outside this conditional so it still runs in disable-upload mode. The Next.js SDK handles this correctly by separating the two operations.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 973bf37. Configure here.

metaFramework: 'nitro',
},
...options?._metaOptions,
},
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_metaOptions spread can override metaFramework: 'nitro'

Low Severity

The spread ...options?._metaOptions comes after the telemetry property, so any user-provided _metaOptions with a telemetry key will completely overwrite metaFramework: 'nitro'. The corresponding test asserts this value is "always" set to 'nitro', but the implementation doesn't guarantee it. The spread and default should be ordered to preserve the metaFramework value.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 973bf37. Configure here.

assets: options?.sourcemaps?.assets,
ignore: options?.sourcemaps?.ignore,
filesToDeleteAfterUpload: options?.sourcemaps?.filesToDeleteAfterUpload ?? ['**/*.map'],
rewriteSources: (source: string) => normalizePath(source),
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

User-provided rewriteSources option silently ignored

Medium Severity

The rewriteSources property in getPluginOptions is hardcoded to normalizePath and ignores any user-provided options?.sourcemaps?.rewriteSources. Since SentryNitroOptions picks the full sourcemaps type (which includes rewriteSources), users can set this option but it's silently dropped. The Nuxt SDK handles this correctly with sourcemapsOptions.rewriteSources ?? normalizePath, falling back to the default only when the user doesn't provide one.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 973bf37. Configure here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants