Skip to content

Commit 1bafc55

Browse files
jpdefocodex
andauthored
fix(bundler-plugins): upload literal artifact paths
Refresh against develop and retain the current shared Nuxt source-map assertions while removing the glob-character upload exception. Co-authored-by: Codex <codex@openai.com>
1 parent 9310b4d commit 1bafc55

3 files changed

Lines changed: 73 additions & 6 deletions

File tree

‎dev-packages/e2e-tests/test-applications/nuxt-5-sourcemaps/assert-build.ts‎

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import * as fs from 'fs';
33
import * as path from 'path';
44
import {
55
assertSourceMapUpload,
6-
findDebugIdsInFilesWithGlobCharacters,
76
findDebugIdsWithConflictingSourcemaps,
87
findFilesWithForeignSourcemaps,
98
findFilesWithMultipleDebugIds,
@@ -73,9 +72,6 @@ const outputDirsWithSourceMaps = [
7372
const debugIdsWithoutSourceMap = new Set(
7473
outputDirsWithSourceMaps.flatMap(dir => [...debugIdsOfChunksWithoutSourceMap(dir)]),
7574
);
76-
const debugIdsSkippedByUploader = isStaticBuild
77-
? []
78-
: findDebugIdsInFilesWithGlobCharacters({ outputDir: SERVER_OUTPUT });
7975

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

‎packages/bundler-plugins/src/core/build-plugin-manager.ts‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import * as dotenv from 'dotenv';
44
import * as fs from 'fs';
55
import * as os from 'os';
66
import * as path from 'path';
7+
import { escape as escapeGlob } from 'glob';
78
import { SentryCliAdapter } from './cli';
89
import type { NormalizedOptions } from './options-mapping';
910
import { normalizeUserOptions, validateOptions } from './options-mapping';
@@ -708,7 +709,7 @@ export function createSentryBuildPluginManager(
708709
logger.debug(
709710
'No `sourcemaps.assets` option provided, falling back to uploading detected build artifacts.',
710711
);
711-
globAssets = buildArtifactPaths;
712+
globAssets = buildArtifactPaths.map(asset => escapeGlob(asset.split(path.sep).join('/')));
712713
}
713714

714715
const globResult = await startSpan({ name: 'glob', scope: sentryScope }, async () =>
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import { existsSync, mkdtempSync, readFileSync, readdirSync, rmSync, writeFileSync } from 'node:fs';
2+
import { tmpdir } from 'node:os';
3+
import { join, sep } from 'node:path';
4+
import { rollup } from 'rollup';
5+
import { afterEach, beforeEach, expect, test, vi } from 'vitest';
6+
import { sentryRollupPlugin } from '../../src/rollup';
7+
8+
const upload = vi.hoisted(() => vi.fn());
9+
const fixtures: string[] = [];
10+
vi.mock('sentry', () => ({
11+
createSentrySDK: () => ({
12+
sourcemap: { upload },
13+
release: {},
14+
}),
15+
}));
16+
17+
beforeEach(() => {
18+
upload.mockReset();
19+
});
20+
21+
afterEach(() => {
22+
for (const fixture of fixtures.splice(0)) {
23+
rmSync(fixture, { recursive: true, force: true });
24+
}
25+
});
26+
27+
test.each([
28+
{ name: 'ordinary filenames', file: 'sdk.mjs', explicitAssets: false, nativePath: false },
29+
{ name: 'glob characters in detected paths', file: 'sdk+[...].mjs', explicitAssets: false, nativePath: false },
30+
{ name: 'explicit asset globs', file: 'sdk+[...].mjs', explicitAssets: true, nativePath: false },
31+
{ name: 'native path separators', file: 'sdk+[...].mjs', explicitAssets: false, nativePath: true },
32+
{ name: 'ignored assets', file: 'sdk+[...].mjs', explicitAssets: false, nativePath: false, ignored: true },
33+
])('handles $name when uploading Rollup artifacts', async ({ file, explicitAssets, nativePath, ignored }) => {
34+
const fixture = mkdtempSync(join(tmpdir(), 'sentry-rollup-literal-paths-'));
35+
fixtures.push(fixture);
36+
const input = join(fixture, 'input.js');
37+
const output = join(fixture, 'dist', '_libs', file);
38+
writeFileSync(input, 'export function example() { throw new Error("original fixture"); }\n');
39+
const uploadedFiles: string[] = [];
40+
upload.mockImplementation(async (options: { directory: string }) => {
41+
uploadedFiles.push(...readdirSync(options.directory));
42+
});
43+
44+
const bundle = await rollup({
45+
input,
46+
plugins: sentryRollupPlugin({
47+
authToken: 'local-fixture-only',
48+
org: 'local-fixture',
49+
project: 'local-fixture',
50+
telemetry: false,
51+
silent: true,
52+
release: { create: false, finalize: false },
53+
sourcemaps: {
54+
assets: explicitAssets ? join(fixture, 'dist', '**', '*.mjs').split(sep).join('/') : undefined,
55+
ignore: ignored ? join(fixture, 'dist', '**', 'sdk+*.mjs').split(sep).join('/') : undefined,
56+
},
57+
}),
58+
});
59+
try {
60+
await bundle.write({ file: nativePath ? output : output.replace(/\\/g, '/'), format: 'es', sourcemap: true });
61+
} finally {
62+
await bundle.close();
63+
}
64+
65+
expect(existsSync(output)).toBe(true);
66+
expect(existsSync(`${output}.map`)).toBe(true);
67+
expect(readFileSync(output, 'utf8')).toContain('sentry-dbid-');
68+
expect(uploadedFiles.filter(name => name.endsWith('.js'))).toHaveLength(ignored ? 0 : 1);
69+
expect(uploadedFiles.filter(name => name.endsWith('.js.map'))).toHaveLength(ignored ? 0 : 1);
70+
});

0 commit comments

Comments
 (0)