Skip to content

Commit e991722

Browse files
committed
fix: Replace existing debug ID comments
1 parent 9c56454 commit e991722

File tree

13 files changed

+210
-7
lines changed

13 files changed

+210
-7
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@ yarn-error.log
77
*.tgz
88

99
.nxcache
10+
packages/**/yarn.lock

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
"npm-run-all": "^4.1.5"
3636
},
3737
"volta": {
38-
"node": "14.21.2",
38+
"node": "20.19.1",
3939
"yarn": "1.22.19"
4040
}
4141
}

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

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -457,8 +457,11 @@ export function createSentryBuildPluginManager(
457457
const tmpUploadFolder = await startSpan(
458458
{ name: "mkdtemp", scope: sentryScope },
459459
async () => {
460-
return await fs.promises.mkdtemp(
461-
path.join(os.tmpdir(), "sentry-bundler-plugin-upload-")
460+
return (
461+
process.env?.["SENTRY_TEST_OVERRIDE_TEMP_DIR"] ||
462+
(await fs.promises.mkdtemp(
463+
path.join(os.tmpdir(), "sentry-bundler-plugin-upload-")
464+
))
462465
);
463466
}
464467
);
@@ -586,7 +589,7 @@ export function createSentryBuildPluginManager(
586589
sentryScope.captureException('Error in "debugIdUploadPlugin" writeBundle hook');
587590
handleRecoverableError(e, false);
588591
} finally {
589-
if (folderToCleanUp) {
592+
if (folderToCleanUp && !process.env?.["SENTRY_TEST_OVERRIDE_TEMP_DIR"]) {
590593
void startSpan({ name: "cleanup", scope: sentryScope }, async () => {
591594
if (folderToCleanUp) {
592595
await fs.promises.rm(folderToCleanUp, { recursive: true, force: true });

packages/bundler-plugin-core/src/debug-id-upload.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ export async function prepareBundleForDebugIdUpload(
5050

5151
const uniqueUploadName = `${debugId}-${chunkIndex}`;
5252

53-
bundleContent += `\n//# debugId=${debugId}`;
53+
bundleContent = addDebugIdToBundleSource(bundleContent, debugId);
5454
const writeSourceFilePromise = fs.promises.writeFile(
5555
path.join(uploadFolder, `${uniqueUploadName}.js`),
5656
bundleContent,
@@ -95,6 +95,20 @@ function determineDebugIdFromBundleSource(code: string): string | undefined {
9595
}
9696
}
9797

98+
const SPEC_LAST_DEBUG_ID_REGEX = /\/\/# debugId=([a-fA-F0-9-]+)(?![\s\S]*\/\/# debugId=)/m;
99+
100+
function hasSpecCompliantDebugId(bundleSource: string): boolean {
101+
return SPEC_LAST_DEBUG_ID_REGEX.test(bundleSource);
102+
}
103+
104+
function addDebugIdToBundleSource(bundleSource: string, debugId: string): string {
105+
if (hasSpecCompliantDebugId(bundleSource)) {
106+
return bundleSource.replace(SPEC_LAST_DEBUG_ID_REGEX, `//# debugId=${debugId}`);
107+
} else {
108+
return `${bundleSource}\n//# debugId=${debugId}`;
109+
}
110+
}
111+
98112
/**
99113
* Applies a set of heuristics to find the source map for a particular bundle.
100114
*
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
/* eslint-disable jest/no-standalone-expect */
2+
/* eslint-disable jest/expect-expect */
3+
import path from "path";
4+
import * as fs from "fs";
5+
import * as os from "os";
6+
import { describeNode18Plus } from "../../utils/testIf";
7+
import { execSync } from "child_process";
8+
9+
function createTempDir() {
10+
return fs.mkdtempSync(path.join(os.tmpdir(), "sentry-bundler-plugin-upload-"));
11+
}
12+
13+
const SPEC_DEBUG_ID_REGEX = /\/\/# debugId=([a-fA-F0-9-]+)/g;
14+
15+
function countDebugIdComments(source: string): number {
16+
const matches = source.match(SPEC_DEBUG_ID_REGEX);
17+
if (matches) {
18+
return matches.length;
19+
}
20+
return 0;
21+
}
22+
23+
function getSingleJavaScriptSourceFileFromDirectory(
24+
dir: string,
25+
fileExtension = ".js"
26+
): string | undefined {
27+
const files = fs.readdirSync(dir);
28+
const jsFiles = files.filter((file) => file.endsWith(fileExtension));
29+
if (jsFiles.length === 1) {
30+
return fs.readFileSync(path.join(dir, jsFiles[0] as string), "utf-8");
31+
}
32+
return undefined;
33+
}
34+
35+
describeNode18Plus("vite 6 bundle", () => {
36+
const viteRoot = path.join(__dirname, "input", "vite6");
37+
const tempDir = createTempDir();
38+
39+
beforeEach(() => {
40+
execSync("yarn install", { cwd: viteRoot, stdio: "inherit" });
41+
execSync("yarn vite build", {
42+
cwd: viteRoot,
43+
stdio: "inherit",
44+
env: { ...process.env, SENTRY_TEST_OVERRIDE_TEMP_DIR: tempDir },
45+
});
46+
});
47+
48+
test("check vite 6 bundle", () => {
49+
const source = getSingleJavaScriptSourceFileFromDirectory(tempDir);
50+
expect(source).toBeDefined();
51+
const debugIds = countDebugIdComments(source as string);
52+
expect(debugIds).toBe(1);
53+
});
54+
55+
afterEach(() => {
56+
fs.rmSync(tempDir, { recursive: true, force: true });
57+
});
58+
});
59+
60+
describeNode18Plus("webpack 5 bundle", () => {
61+
const viteRoot = path.join(__dirname, "input", "webpack5");
62+
const tempDir = createTempDir();
63+
64+
beforeEach(() => {
65+
execSync("yarn install", { cwd: viteRoot, stdio: "inherit" });
66+
execSync("yarn webpack build", {
67+
cwd: viteRoot,
68+
stdio: "inherit",
69+
env: { ...process.env, SENTRY_TEST_OVERRIDE_TEMP_DIR: tempDir },
70+
});
71+
});
72+
73+
test("check webpack 5 bundle", () => {
74+
const source = getSingleJavaScriptSourceFileFromDirectory(tempDir);
75+
expect(source).toBeDefined();
76+
const debugIds = countDebugIdComments(source as string);
77+
expect(debugIds).toBe(1);
78+
});
79+
80+
afterEach(() => {
81+
fs.rmSync(tempDir, { recursive: true, force: true });
82+
});
83+
});
84+
85+
describeNode18Plus("rollup bundle", () => {
86+
const viteRoot = path.join(__dirname, "input", "rollup4");
87+
const tempDir = createTempDir();
88+
89+
beforeEach(() => {
90+
execSync("yarn install", { cwd: viteRoot, stdio: "inherit" });
91+
execSync("yarn rollup --config rollup.config.js", {
92+
cwd: viteRoot,
93+
stdio: "inherit",
94+
env: { ...process.env, SENTRY_TEST_OVERRIDE_TEMP_DIR: tempDir },
95+
});
96+
});
97+
98+
test("check rollup bundle", () => {
99+
const source = getSingleJavaScriptSourceFileFromDirectory(tempDir);
100+
expect(source).toBeDefined();
101+
const debugIds = countDebugIdComments(source as string);
102+
expect(debugIds).toBe(1);
103+
});
104+
105+
afterEach(() => {
106+
fs.rmSync(tempDir, { recursive: true, force: true });
107+
});
108+
});
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
// eslint-disable-next-line no-console
2+
console.log("Hello world");
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"dependencies": {
3+
"rollup": "^4"
4+
}
5+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { defineConfig } from "rollup";
2+
import { sentryRollupPlugin } from "@sentry/rollup-plugin";
3+
import { join } from "path";
4+
5+
const __dirname = new URL(".", import.meta.url).pathname;
6+
7+
export default defineConfig({
8+
input: { index: join(__dirname, "..", "bundle.js") },
9+
output: {
10+
dir: join(__dirname, "..", "..", "out", "rollup4"),
11+
sourcemap: true,
12+
sourcemapDebugIds: true,
13+
},
14+
plugins: [sentryRollupPlugin({ telemetry: false })],
15+
});
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"dependencies": {
3+
"vite": "^6"
4+
}
5+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { defineConfig } from "vite";
2+
import { sentryVitePlugin } from "@sentry/vite-plugin";
3+
import { join } from "path";
4+
5+
export default defineConfig({
6+
clearScreen: false,
7+
mode: "production",
8+
build: {
9+
sourcemap: true,
10+
outDir: join(__dirname, "..", "..", "out", "vite6"),
11+
rollupOptions: {
12+
input: { index: join(__dirname, "..", "bundle.js") },
13+
output: {
14+
format: "cjs",
15+
entryFileNames: "[name].js",
16+
sourcemapDebugIds: true,
17+
},
18+
},
19+
},
20+
plugins: [sentryVitePlugin({ telemetry: false })],
21+
});
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"dependencies": {
3+
"webpack": "^5",
4+
"webpack-cli": "^6"
5+
}
6+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { sentryWebpackPlugin } from "@sentry/webpack-plugin";
2+
import { join } from "path";
3+
4+
const __dirname = new URL(".", import.meta.url).pathname;
5+
6+
export default {
7+
devtool: "source-map-debugids",
8+
cache: false,
9+
entry: { index: join(__dirname, "..", "bundle.js") },
10+
output: {
11+
path: join(__dirname, "..", "..", "out", "webpack5"),
12+
library: {
13+
type: "commonjs",
14+
},
15+
},
16+
mode: "production",
17+
plugins: [sentryWebpackPlugin({ telemetry: false })],
18+
};

packages/integration-tests/utils/testIf.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
const [NODE_MAJOR_VERSION] = process.version.replace("v", "").split(".").map(Number) as [number];
2+
13
// eslint-disable-next-line no-undef
24
export function testIf(condition: boolean): jest.It {
35
if (condition) {
@@ -15,7 +17,10 @@ export function testIf(condition: boolean): jest.It {
1517
*/
1618
// eslint-disable-next-line @typescript-eslint/no-explicit-any, no-undef, @typescript-eslint/no-unsafe-assignment
1719
export const testIfNodeMajorVersionIsLessThan18: jest.It = function () {
18-
const nodejsMajorversion = process.version.split(".")[0]?.slice(1);
19-
return testIf(!nodejsMajorversion || parseInt(nodejsMajorversion) < 18);
20+
return testIf(NODE_MAJOR_VERSION < 18);
2021
// eslint-disable-next-line @typescript-eslint/no-explicit-any
2122
} as any;
23+
24+
// eslint-disable-next-line no-undef
25+
export const describeNode18Plus: jest.Describe =
26+
NODE_MAJOR_VERSION >= 18 ? describe : describe.skip;

0 commit comments

Comments
 (0)