Skip to content

Commit add97e6

Browse files
authored
feat(core): Add flag for disabling sourcemaps upload (#785)
1 parent c1441e8 commit add97e6

File tree

4 files changed

+209
-21
lines changed

4 files changed

+209
-21
lines changed

packages/bundler-plugin-core/src/index.ts

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -123,25 +123,27 @@ export function sentryUnpluginFactory({
123123
},
124124
});
125125

126-
if (!options.sourcemaps?.disable) {
126+
if (options.sourcemaps?.disable !== true) {
127127
plugins.push(debugIdInjectionPlugin(logger));
128128

129-
// This option is only strongly typed for the webpack plugin, where it is used. It has no effect on other plugins
130-
const webpack_forceExitOnBuildComplete =
131-
typeof options._experiments["forceExitOnBuildCompletion"] === "boolean"
132-
? options._experiments["forceExitOnBuildCompletion"]
133-
: undefined;
134-
135-
plugins.push(
136-
debugIdUploadPlugin(
137-
createDebugIdUploadFunction({
138-
sentryBuildPluginManager,
139-
}),
140-
logger,
141-
sentryBuildPluginManager.createDependencyOnBuildArtifacts,
142-
webpack_forceExitOnBuildComplete
143-
)
144-
);
129+
if (options.sourcemaps?.disable !== "disable-upload") {
130+
// This option is only strongly typed for the webpack plugin, where it is used. It has no effect on other plugins
131+
const webpack_forceExitOnBuildComplete =
132+
typeof options._experiments["forceExitOnBuildCompletion"] === "boolean"
133+
? options._experiments["forceExitOnBuildCompletion"]
134+
: undefined;
135+
136+
plugins.push(
137+
debugIdUploadPlugin(
138+
createDebugIdUploadFunction({
139+
sentryBuildPluginManager,
140+
}),
141+
logger,
142+
sentryBuildPluginManager.createDependencyOnBuildArtifacts,
143+
webpack_forceExitOnBuildComplete
144+
)
145+
);
146+
}
145147
}
146148

147149
if (options.reactComponentAnnotation) {

packages/bundler-plugin-core/src/options-mapping.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ export type NormalizedOptions = {
2323
disable: boolean;
2424
sourcemaps:
2525
| {
26-
disable?: boolean;
26+
disable?: boolean | "disable-upload";
2727
assets?: string | string[];
2828
ignore?: string | string[];
2929
rewriteSources?: RewriteSourcesHook;

packages/bundler-plugin-core/src/types.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,11 +95,14 @@ export interface Options {
9595
*/
9696
sourcemaps?: {
9797
/**
98-
* If this flag is `true`, any functionality related to source maps will be disabled.
98+
* Disables all functionality related to sourcemaps if set to `true`.
99+
*
100+
* If set to `"disable-upload"`, the plugin will not upload sourcemaps to Sentry, but will inject debug IDs into the build artifacts.
101+
* This is useful if you want to manually upload sourcemaps to Sentry at a later point in time.
99102
*
100103
* @default false
101104
*/
102-
disable?: boolean;
105+
disable?: boolean | "disable-upload";
103106

104107
/**
105108
* A glob or an array of globs that specify the build artifacts and source maps that will be uploaded to Sentry.

packages/bundler-plugin-core/test/index.test.ts

Lines changed: 184 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import { getDebugIdSnippet } from "../src";
1+
import { Compiler } from "webpack";
2+
import { getDebugIdSnippet, sentryUnpluginFactory } from "../src";
23

34
describe("getDebugIdSnippet", () => {
45
it("returns the debugId injection snippet for a passed debugId", () => {
@@ -8,3 +9,185 @@ describe("getDebugIdSnippet", () => {
89
);
910
});
1011
});
12+
13+
describe("sentryUnpluginFactory sourcemaps.disable behavior", () => {
14+
const mockReleaseInjectionPlugin = jest.fn((_injectionCode: string) => ({
15+
name: "mock-release-injection-plugin",
16+
}));
17+
18+
const mockComponentNameAnnotatePlugin = jest.fn(() => ({
19+
name: "mock-component-name-annotate-plugin",
20+
}));
21+
22+
const mockModuleMetadataInjectionPlugin = jest.fn((_injectionCode: string) => ({
23+
name: "mock-module-metadata-injection-plugin",
24+
}));
25+
26+
const mockDebugIdInjectionPlugin = jest.fn(() => ({
27+
name: "mock-debug-id-injection-plugin",
28+
}));
29+
30+
const mockDebugIdUploadPlugin = jest.fn(() => ({
31+
name: "mock-debug-id-upload-plugin",
32+
}));
33+
34+
const mockBundleSizeOptimizationsPlugin = jest.fn(() => ({
35+
name: "mock-bundle-size-optimizations-plugin",
36+
}));
37+
38+
const createUnpluginInstance = (): ReturnType<typeof sentryUnpluginFactory> => {
39+
return sentryUnpluginFactory({
40+
releaseInjectionPlugin: mockReleaseInjectionPlugin,
41+
componentNameAnnotatePlugin: mockComponentNameAnnotatePlugin,
42+
moduleMetadataInjectionPlugin: mockModuleMetadataInjectionPlugin,
43+
debugIdInjectionPlugin: mockDebugIdInjectionPlugin,
44+
debugIdUploadPlugin: mockDebugIdUploadPlugin,
45+
bundleSizeOptimizationsPlugin: mockBundleSizeOptimizationsPlugin,
46+
});
47+
};
48+
49+
beforeEach(() => {
50+
jest.clearAllMocks();
51+
});
52+
53+
describe("when sourcemaps.disable is true", () => {
54+
it("should not include debug ID injection or upload plugins", () => {
55+
const unpluginInstance = createUnpluginInstance();
56+
57+
const plugins = unpluginInstance.raw(
58+
{
59+
authToken: "test-token",
60+
org: "test-org",
61+
project: "test-project",
62+
sourcemaps: {
63+
disable: true,
64+
},
65+
},
66+
{ framework: "webpack", webpack: { compiler: {} as Compiler } }
67+
);
68+
69+
const pluginNames = plugins.map((plugin) => plugin.name);
70+
71+
// Should not include debug ID related plugins
72+
expect(pluginNames).not.toContain("mock-debug-id-injection-plugin");
73+
expect(pluginNames).not.toContain("mock-debug-id-upload-plugin");
74+
75+
// Should still include other core plugins
76+
expect(pluginNames).toContain("sentry-telemetry-plugin");
77+
expect(pluginNames).toContain("sentry-release-management-plugin");
78+
expect(pluginNames).toContain("sentry-file-deletion-plugin");
79+
});
80+
});
81+
82+
describe('when sourcemaps.disable is "disable-upload"', () => {
83+
it("should include debug ID injection plugin but not upload plugin", () => {
84+
const unpluginInstance = createUnpluginInstance();
85+
86+
const plugins = unpluginInstance.raw(
87+
{
88+
authToken: "test-token",
89+
org: "test-org",
90+
project: "test-project",
91+
sourcemaps: {
92+
disable: "disable-upload",
93+
},
94+
},
95+
{ framework: "webpack", webpack: { compiler: {} as Compiler } }
96+
);
97+
98+
const pluginNames = plugins.map((plugin) => plugin.name);
99+
100+
// Should include debug ID injection but not upload
101+
expect(pluginNames).toContain("mock-debug-id-injection-plugin");
102+
expect(pluginNames).not.toContain("mock-debug-id-upload-plugin");
103+
104+
// Should still include other core plugins
105+
expect(pluginNames).toContain("sentry-telemetry-plugin");
106+
expect(pluginNames).toContain("sentry-release-management-plugin");
107+
expect(pluginNames).toContain("sentry-file-deletion-plugin");
108+
});
109+
});
110+
111+
describe("when sourcemaps.disable is false", () => {
112+
it("should include both debug ID injection and upload plugins", () => {
113+
const unpluginInstance = createUnpluginInstance();
114+
115+
const plugins = unpluginInstance.raw(
116+
{
117+
authToken: "test-token",
118+
org: "test-org",
119+
project: "test-project",
120+
sourcemaps: {
121+
disable: false,
122+
},
123+
},
124+
{ framework: "webpack", webpack: { compiler: {} as Compiler } }
125+
);
126+
127+
const pluginNames = plugins.map((plugin) => plugin.name);
128+
129+
// Should include both debug ID related plugins
130+
expect(pluginNames).toContain("mock-debug-id-injection-plugin");
131+
expect(pluginNames).toContain("mock-debug-id-upload-plugin");
132+
133+
// Should include other core plugins
134+
expect(pluginNames).toContain("sentry-telemetry-plugin");
135+
expect(pluginNames).toContain("sentry-release-management-plugin");
136+
expect(pluginNames).toContain("sentry-file-deletion-plugin");
137+
});
138+
});
139+
140+
describe("when sourcemaps.disable is undefined (default)", () => {
141+
it("should include both debug ID injection and upload plugins", () => {
142+
const unpluginInstance = createUnpluginInstance();
143+
144+
const plugins = unpluginInstance.raw(
145+
{
146+
authToken: "test-token",
147+
org: "test-org",
148+
project: "test-project",
149+
// sourcemaps.disable not specified (undefined)
150+
},
151+
{ framework: "webpack", webpack: { compiler: {} as Compiler } }
152+
);
153+
154+
const pluginNames = plugins.map((plugin) => plugin.name);
155+
156+
// Should include both debug ID related plugins by default
157+
expect(pluginNames).toContain("mock-debug-id-injection-plugin");
158+
expect(pluginNames).toContain("mock-debug-id-upload-plugin");
159+
160+
// Should include other core plugins
161+
expect(pluginNames).toContain("sentry-telemetry-plugin");
162+
expect(pluginNames).toContain("sentry-release-management-plugin");
163+
expect(pluginNames).toContain("sentry-file-deletion-plugin");
164+
});
165+
});
166+
167+
describe("when entire sourcemaps option is undefined", () => {
168+
it("should include both debug ID injection and upload plugins", () => {
169+
const unpluginInstance = createUnpluginInstance();
170+
171+
const plugins = unpluginInstance.raw(
172+
{
173+
authToken: "test-token",
174+
org: "test-org",
175+
project: "test-project",
176+
// sourcemaps option not specified at all
177+
},
178+
{ framework: "webpack", webpack: { compiler: {} as Compiler } }
179+
);
180+
181+
const pluginNames = plugins.map((plugin) => plugin.name);
182+
183+
// Should include both debug ID related plugins by default
184+
expect(pluginNames).toContain("mock-debug-id-injection-plugin");
185+
expect(pluginNames).toContain("mock-debug-id-upload-plugin");
186+
187+
// Should include other core plugins
188+
expect(pluginNames).toContain("sentry-telemetry-plugin");
189+
expect(pluginNames).toContain("sentry-release-management-plugin");
190+
expect(pluginNames).toContain("sentry-file-deletion-plugin");
191+
});
192+
});
193+
});

0 commit comments

Comments
 (0)