Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import * as fs from 'fs';
import * as path from 'path';
import {
assertSourceMapUpload,
findDebugIdsInFilesWithGlobCharacters,
findDebugIdsWithConflictingSourcemaps,
findFilesWithForeignSourcemaps,
findFilesWithMultipleDebugIds,
Expand Down Expand Up @@ -73,9 +72,6 @@ const outputDirsWithSourceMaps = [
const debugIdsWithoutSourceMap = new Set(
outputDirsWithSourceMaps.flatMap(dir => [...debugIdsOfChunksWithoutSourceMap(dir)]),
);
const debugIdsSkippedByUploader = isStaticBuild
? []
: findDebugIdsInFilesWithGlobCharacters({ outputDir: SERVER_OUTPUT });

const { requests, bundles, sourcemaps, uploadedDebugIds } = assertSourceMapUpload({
outputDirs: outputDirsWithSourceMaps,
Expand All @@ -86,7 +82,7 @@ const { requests, bundles, sourcemaps, uploadedDebugIds } = assertSourceMapUploa
// Nitro 3 deletes `sourcesContent` from the server maps unless `experimental.sourcemapMinify` is `false`. The module
// sets it to `false`, which is the only reason the server marker survives into `sourcesContent`.
markers: { 'client source (Vite plugin)': CLIENT_MARKER, 'server source (Rollup plugin)': SERVER_MARKER },
debugIdsWithoutSourceMap: [...debugIdsWithoutSourceMap, ...debugIdsSkippedByUploader],
debugIdsWithoutSourceMap: [...debugIdsWithoutSourceMap],
});
console.log(`Found ${bundles.length} artifact bundle(s)\n`);

Expand Down
3 changes: 2 additions & 1 deletion packages/bundler-plugins/src/core/build-plugin-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import * as dotenv from 'dotenv';
import * as fs from 'fs';
import * as os from 'os';
import * as path from 'path';
import { escape as escapeGlob } from 'glob';
import { SentryCliAdapter } from './cli';
import type { NormalizedOptions } from './options-mapping';
import { normalizeUserOptions, validateOptions } from './options-mapping';
Expand Down Expand Up @@ -708,7 +709,7 @@ export function createSentryBuildPluginManager(
logger.debug(
'No `sourcemaps.assets` option provided, falling back to uploading detected build artifacts.',
);
globAssets = buildArtifactPaths;
globAssets = buildArtifactPaths.map(asset => escapeGlob(asset.split(path.sep).join('/')));
}

const globResult = await startSpan({ name: 'glob', scope: sentryScope }, async () =>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import { existsSync, mkdtempSync, readFileSync, readdirSync, rmSync, writeFileSync } from 'node:fs';
import { tmpdir } from 'node:os';
import { join, sep } from 'node:path';
import { rollup } from 'rollup';
import { afterEach, beforeEach, expect, test, vi } from 'vitest';
import { sentryRollupPlugin } from '../../src/rollup';

const upload = vi.hoisted(() => vi.fn());
const fixtures: string[] = [];
vi.mock('sentry', () => ({
createSentrySDK: () => ({
sourcemap: { upload },
release: {},
}),
}));

beforeEach(() => {
upload.mockReset();
});

afterEach(() => {
for (const fixture of fixtures.splice(0)) {
rmSync(fixture, { recursive: true, force: true });
}
});

test.each([
{ name: 'ordinary filenames', file: 'sdk.mjs', explicitAssets: false, nativePath: false },
{ name: 'glob characters in detected paths', file: 'sdk+[...].mjs', explicitAssets: false, nativePath: false },
{ name: 'explicit asset globs', file: 'sdk+[...].mjs', explicitAssets: true, nativePath: false },
{ name: 'native path separators', file: 'sdk+[...].mjs', explicitAssets: false, nativePath: true },
{ name: 'ignored assets', file: 'sdk+[...].mjs', explicitAssets: false, nativePath: false, ignored: true },
])('handles $name when uploading Rollup artifacts', async ({ file, explicitAssets, nativePath, ignored }) => {
const fixture = mkdtempSync(join(tmpdir(), 'sentry-rollup-literal-paths-'));
fixtures.push(fixture);
const input = join(fixture, 'input.js');
const output = join(fixture, 'dist', '_libs', file);
writeFileSync(input, 'export function example() { throw new Error("original fixture"); }\n');
const uploadedFiles: string[] = [];
upload.mockImplementation(async (options: { directory: string }) => {
uploadedFiles.push(...readdirSync(options.directory));
});

const bundle = await rollup({
input,
plugins: sentryRollupPlugin({
authToken: 'local-fixture-only',
org: 'local-fixture',
project: 'local-fixture',
telemetry: false,
silent: true,
release: { create: false, finalize: false },
sourcemaps: {
assets: explicitAssets ? join(fixture, 'dist', '**', '*.mjs').split(sep).join('/') : undefined,
ignore: ignored ? join(fixture, 'dist', '**', 'sdk+*.mjs').split(sep).join('/') : undefined,
},
}),
});
try {
await bundle.write({ file: nativePath ? output : output.replace(/\\/g, '/'), format: 'es', sourcemap: true });
} finally {
await bundle.close();
}

expect(existsSync(output)).toBe(true);
expect(existsSync(`${output}.map`)).toBe(true);
expect(readFileSync(output, 'utf8')).toContain('sentry-dbid-');
expect(uploadedFiles.filter(name => name.endsWith('.js'))).toHaveLength(ignored ? 0 : 1);
expect(uploadedFiles.filter(name => name.endsWith('.js.map'))).toHaveLength(ignored ? 0 : 1);
});