From d09fe3621a0ef3da8067119cfab948de6fa1a5a6 Mon Sep 17 00:00:00 2001 From: Luca Forstner Date: Tue, 23 May 2023 10:59:35 +0200 Subject: [PATCH 1/3] feat: Auto detect build artifacts --- .../src/{plugins => }/debug-id-upload.ts | 106 +++++++++--------- packages/bundler-plugin-core/src/index.ts | 79 ++++++++----- packages/bundler-plugin-core/src/types.ts | 4 +- .../src/generate-documentation-table.ts | 2 +- packages/esbuild-plugin/README_TEMPLATE.md | 21 ---- packages/esbuild-plugin/src/index.ts | 18 +++ packages/playground/build-esbuild.js | 5 +- packages/playground/build-webpack4.js | 5 +- packages/playground/build-webpack5.js | 5 +- packages/playground/rollup.config.mjs | 5 +- packages/playground/vite.config.js | 5 +- packages/rollup-plugin/README_TEMPLATE.md | 27 +---- packages/rollup-plugin/src/index.ts | 11 ++ packages/vite-plugin/README_TEMPLATE.md | 21 ---- packages/vite-plugin/src/index.ts | 11 ++ packages/webpack-plugin/README_TEMPLATE.md | 21 ---- packages/webpack-plugin/src/index.ts | 32 ++++-- 17 files changed, 182 insertions(+), 196 deletions(-) rename packages/bundler-plugin-core/src/{plugins => }/debug-id-upload.ts (76%) diff --git a/packages/bundler-plugin-core/src/plugins/debug-id-upload.ts b/packages/bundler-plugin-core/src/debug-id-upload.ts similarity index 76% rename from packages/bundler-plugin-core/src/plugins/debug-id-upload.ts rename to packages/bundler-plugin-core/src/debug-id-upload.ts index 356309ff..84727e9b 100644 --- a/packages/bundler-plugin-core/src/plugins/debug-id-upload.ts +++ b/packages/bundler-plugin-core/src/debug-id-upload.ts @@ -3,8 +3,7 @@ import { glob } from "glob"; import os from "os"; import path from "path"; import * as util from "util"; -import { UnpluginOptions } from "unplugin"; -import { Logger } from "../sentry/logger"; +import { Logger } from "./sentry/logger"; import { promisify } from "util"; import { Hub, NodeClient } from "@sentry/node"; import SentryCli from "@sentry/cli"; @@ -15,7 +14,7 @@ interface RewriteSourcesHook { interface DebugIdUploadPluginOptions { logger: Logger; - assets: string | string[]; + assets?: string | string[]; ignore?: string | string[]; releaseName?: string; dist?: string; @@ -35,7 +34,7 @@ interface DebugIdUploadPluginOptions { }; } -export function debugIdUploadPlugin({ +export function createDebugIdUploadFunction({ assets, ignore, logger, @@ -47,34 +46,41 @@ export function debugIdUploadPlugin({ sentryCliOptions, rewriteSourcesHook, deleteFilesAfterUpload, -}: DebugIdUploadPluginOptions): UnpluginOptions { - return { - name: "sentry-debug-id-upload-plugin", - async writeBundle() { - let folderToCleanUp: string | undefined; +}: DebugIdUploadPluginOptions) { + return async (buildArtifactPaths: string[]) => { + let folderToCleanUp: string | undefined; - const cliInstance = new SentryCli(null, sentryCliOptions); + const cliInstance = new SentryCli(null, sentryCliOptions); - try { - const tmpUploadFolder = await fs.promises.mkdtemp( - path.join(os.tmpdir(), "sentry-bundler-plugin-upload-") - ); + try { + const tmpUploadFolder = await fs.promises.mkdtemp( + path.join(os.tmpdir(), "sentry-bundler-plugin-upload-") + ); - folderToCleanUp = tmpUploadFolder; + folderToCleanUp = tmpUploadFolder; - const debugIdChunkFilePaths = ( - await glob(assets, { - absolute: true, - nodir: true, - ignore: ignore, - }) - ).filter( - (debugIdChunkFilePath) => - debugIdChunkFilePath.endsWith(".js") || - debugIdChunkFilePath.endsWith(".mjs") || - debugIdChunkFilePath.endsWith(".cjs") - ); + const debugIdChunkFilePaths = ( + await glob(assets ?? buildArtifactPaths, { + absolute: true, + nodir: true, + ignore: ignore, + }) + ).filter( + (debugIdChunkFilePath) => + debugIdChunkFilePath.endsWith(".js") || + debugIdChunkFilePath.endsWith(".mjs") || + debugIdChunkFilePath.endsWith(".cjs") + ); + if (Array.isArray(assets) && assets.length === 0) { + logger.debug( + "Empty `sourcemaps.assets` option provided. Will not upload sourcemaps with debug ID." + ); + } else if (debugIdChunkFilePaths.length === 0) { + logger.warn( + "Didn't find any matching sources for debug ID upload. Please check the `sourcemaps.assets` option." + ); + } else { await Promise.all( debugIdChunkFilePaths.map(async (chunkFilePath, chunkIndex): Promise => { await prepareBundleForDebugIdUpload( @@ -100,33 +106,33 @@ export function debugIdUploadPlugin({ useArtifactBundle: true, } ); + } - if (deleteFilesAfterUpload) { - const filePathsToDelete = await glob(deleteFilesAfterUpload, { - absolute: true, - nodir: true, - }); + if (deleteFilesAfterUpload) { + const filePathsToDelete = await glob(deleteFilesAfterUpload, { + absolute: true, + nodir: true, + }); - filePathsToDelete.forEach((filePathToDelete) => { - logger.debug(`Deleting asset after upload: ${filePathToDelete}`); - }); + filePathsToDelete.forEach((filePathToDelete) => { + logger.debug(`Deleting asset after upload: ${filePathToDelete}`); + }); - await Promise.all( - filePathsToDelete.map((filePathToDelete) => - fs.promises.rm(filePathToDelete, { force: true }) - ) - ); - } - } catch (e) { - sentryHub.captureException('Error in "debugIdUploadPlugin" writeBundle hook'); - await sentryClient.flush(); - handleRecoverableError(e); - } finally { - if (folderToCleanUp) { - void fs.promises.rm(folderToCleanUp, { recursive: true, force: true }); - } + await Promise.all( + filePathsToDelete.map((filePathToDelete) => + fs.promises.rm(filePathToDelete, { force: true }) + ) + ); + } + } catch (e) { + sentryHub.captureException('Error in "debugIdUploadPlugin" writeBundle hook'); + await sentryClient.flush(); + handleRecoverableError(e); + } finally { + if (folderToCleanUp) { + void fs.promises.rm(folderToCleanUp, { recursive: true, force: true }); } - }, + } }; } diff --git a/packages/bundler-plugin-core/src/index.ts b/packages/bundler-plugin-core/src/index.ts index 78a9febe..4e4019c9 100644 --- a/packages/bundler-plugin-core/src/index.ts +++ b/packages/bundler-plugin-core/src/index.ts @@ -1,9 +1,10 @@ import SentryCli from "@sentry/cli"; -import fs from "fs"; +import * as fs from "fs"; +import * as path from "path"; import MagicString from "magic-string"; import { createUnplugin, UnpluginOptions } from "unplugin"; import { normalizeUserOptions, validateOptions } from "./options-mapping"; -import { debugIdUploadPlugin } from "./plugins/debug-id-upload"; +import { createDebugIdUploadFunction } from "./debug-id-upload"; import { releaseManagementPlugin } from "./plugins/release-management"; import { telemetryPlugin } from "./plugins/telemetry"; import { createLogger } from "./sentry/logger"; @@ -21,6 +22,7 @@ import { interface SentryUnpluginFactoryOptions { releaseInjectionPlugin: (injectionCode: string) => UnpluginOptions; debugIdInjectionPlugin: () => UnpluginOptions; + debugIdUploadPlugin: (upload: (buildArtifacts: string[]) => Promise) => UnpluginOptions; } /** @@ -53,6 +55,7 @@ interface SentryUnpluginFactoryOptions { export function sentryUnpluginFactory({ releaseInjectionPlugin, debugIdInjectionPlugin, + debugIdUploadPlugin, }: SentryUnpluginFactoryOptions) { return createUnplugin((userOptions, unpluginMetaContext) => { const options = normalizeUserOptions(userOptions); @@ -180,35 +183,31 @@ export function sentryUnpluginFactory({ ); } - if (options.sourcemaps) { - if (!options.authToken) { - logger.warn( - "No auth token provided. Will not upload source maps. Please set the `authToken` option. You can find information on how to generate a Sentry auth token here: https://docs.sentry.io/api/auth/" - ); - } else if (!options.org) { - logger.warn( - "No org provided. Will not upload source maps. Please set the `org` option to your Sentry organization slug." - ); - } else if (!options.project) { - logger.warn( - "No project provided. Will not upload source maps. Please set the `project` option to your Sentry project slug." - ); - } else if (!options.sourcemaps.assets) { - logger.warn( - "No assets defined. Will not upload source maps. Please provide set the `assets` option to your build-output folder." - ); - } else { - plugins.push(debugIdInjectionPlugin()); - plugins.push( - debugIdUploadPlugin({ - assets: options.sourcemaps.assets, - ignore: options.sourcemaps.ignore, - deleteFilesAfterUpload: options.sourcemaps.deleteFilesAfterUpload, + if (!options.authToken) { + logger.warn( + "No auth token provided. Will not upload source maps. Please set the `authToken` option. You can find information on how to generate a Sentry auth token here: https://docs.sentry.io/api/auth/" + ); + } else if (!options.org) { + logger.warn( + "No org provided. Will not upload source maps. Please set the `org` option to your Sentry organization slug." + ); + } else if (!options.project) { + logger.warn( + "No project provided. Will not upload source maps. Please set the `project` option to your Sentry project slug." + ); + } else { + plugins.push(debugIdInjectionPlugin()); + plugins.push( + debugIdUploadPlugin( + createDebugIdUploadFunction({ + assets: options.sourcemaps?.assets, + ignore: options.sourcemaps?.ignore, + deleteFilesAfterUpload: options.sourcemaps?.deleteFilesAfterUpload, dist: options.release.dist, releaseName: options.release.name, logger: logger, handleRecoverableError: handleRecoverableError, - rewriteSourcesHook: options.sourcemaps.rewriteSources, + rewriteSourcesHook: options.sourcemaps?.rewriteSources, sentryHub, sentryClient, sentryCliOptions: { @@ -221,8 +220,8 @@ export function sentryUnpluginFactory({ headers: options.headers, }, }) - ); - } + ) + ); } return plugins; @@ -341,6 +340,28 @@ export function createRollupDebugIdInjectionHooks() { }; } +export function createRollupDebugIdUploadHooks( + upload: (buildArtifacts: string[]) => Promise +) { + return { + async writeBundle( + outputOptions: { dir?: string; file?: string }, + bundle: { [fileName: string]: unknown } + ) { + if (outputOptions.dir) { + const outputDir = outputOptions.dir; + const buildArtifacts = Object.keys(bundle).map((asset) => path.join(outputDir, asset)); + await upload(buildArtifacts); + } else if (outputOptions.file) { + await upload([outputOptions.file]); + } else { + const buildArtifacts = Object.keys(bundle).map((asset) => path.join(path.resolve(), asset)); + await upload(buildArtifacts); + } + }, + }; +} + export function getDebugIdSnippet(debugId: string): string { return `;!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{},n=(new Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="${debugId}",e._sentryDebugIdIdentifier="sentry-dbid-${debugId}")}catch(e){}}();`; } diff --git a/packages/bundler-plugin-core/src/types.ts b/packages/bundler-plugin-core/src/types.ts index abb6d0f0..e33c91cb 100644 --- a/packages/bundler-plugin-core/src/types.ts +++ b/packages/bundler-plugin-core/src/types.ts @@ -93,11 +93,13 @@ export interface Options { /** * A glob or an array of globs that specifies the build artifacts that should be uploaded to Sentry. * + * If this option is not specified, the plugin will try to upload all JavaScript files and source map files that are created during build. + * * The globbing patterns follow the implementation of the `glob` package. (https://www.npmjs.com/package/glob) * * Use the `debug` option to print information about which files end up being uploaded. */ - assets: string | string[]; + assets?: string | string[]; /** * A glob or an array of globs that specifies which build artifacts should not be uploaded to Sentry. diff --git a/packages/dev-utils/src/generate-documentation-table.ts b/packages/dev-utils/src/generate-documentation-table.ts index ed5175ee..e7f36c26 100644 --- a/packages/dev-utils/src/generate-documentation-table.ts +++ b/packages/dev-utils/src/generate-documentation-table.ts @@ -79,7 +79,7 @@ errorHandler: (err) => { name: "assets", type: "string | string[]", fullDescription: - "A glob or an array of globs that specifies the build artifacts that should be uploaded to Sentry.\n\nThe globbing patterns follow the implementation of the `glob` package. (https://www.npmjs.com/package/glob)\n\nUse the `debug` option to print information about which files end up being uploaded.", + "A glob or an array of globs that specifies the build artifacts that should be uploaded to Sentry.\n\nIf this option is not specified, the plugin will try to upload all JavaScript files and source map files that are created during build.\n\nThe globbing patterns follow the implementation of the `glob` package. (https://www.npmjs.com/package/glob)\n\nUse the `debug` option to print information about which files end up being uploaded.", }, { name: "ignore", diff --git a/packages/esbuild-plugin/README_TEMPLATE.md b/packages/esbuild-plugin/README_TEMPLATE.md index 0bec8eb3..04108466 100644 --- a/packages/esbuild-plugin/README_TEMPLATE.md +++ b/packages/esbuild-plugin/README_TEMPLATE.md @@ -49,27 +49,6 @@ require("esbuild").build({ // Auth tokens can be obtained from https://sentry.io/settings/account/api/auth-tokens/ // and need `project:releases` and `org:read` scopes authToken: process.env.SENTRY_AUTH_TOKEN, - - sourcemaps: { - // Specify the directory containing build artifacts - assets: "./**", - // Don't upload the source maps of dependencies - ignore: ["./node_modules/**"], - }, - - // Helps troubleshooting - set to false to make plugin less noisy - debug: true, - - // Use the following option if you're on an SDK version lower than 7.47.0: - // release: { - // uploadLegacySourcemaps: { - // include: ".", - // ignore: ["node_modules"], - // }, - // }, - - // Optionally uncomment the line below to override automatic release name detection - // release: process.env.RELEASE, }), ], }); diff --git a/packages/esbuild-plugin/src/index.ts b/packages/esbuild-plugin/src/index.ts index 7ecb0f33..269687ad 100644 --- a/packages/esbuild-plugin/src/index.ts +++ b/packages/esbuild-plugin/src/index.ts @@ -63,9 +63,27 @@ function esbuildDebugIdInjectionPlugin(): UnpluginOptions { }; } +function esbuildDebugIdUploadPlugin( + upload: (buildArtifacts: string[]) => Promise +): UnpluginOptions { + return { + name: "sentry-esbuild-debug-id-upload-plugin", + esbuild: { + setup({ initialOptions, onEnd }) { + initialOptions.metafile = true; + onEnd(async (result) => { + const buildArtifacts = result.metafile ? Object.keys(result.metafile.outputs) : []; + await upload(buildArtifacts); + }); + }, + }, + }; +} + const sentryUnplugin = sentryUnpluginFactory({ releaseInjectionPlugin: esbuildReleaseInjectionPlugin, debugIdInjectionPlugin: esbuildDebugIdInjectionPlugin, + debugIdUploadPlugin: esbuildDebugIdUploadPlugin, }); // eslint-disable-next-line @typescript-eslint/no-explicit-any diff --git a/packages/playground/build-esbuild.js b/packages/playground/build-esbuild.js index 9ab3d5fa..dabb9fea 100644 --- a/packages/playground/build-esbuild.js +++ b/packages/playground/build-esbuild.js @@ -6,10 +6,7 @@ build({ outdir: "./out/esbuild", plugins: [ sentryEsbuildPlugin({ - sourcemaps: { - assets: "./out/esbuild/**", - deleteFilesAfterUpload: "./out/esbuild/**/*.map", - }, + debug: true, }), ], minify: true, diff --git a/packages/playground/build-webpack4.js b/packages/playground/build-webpack4.js index d238e58b..089820be 100644 --- a/packages/playground/build-webpack4.js +++ b/packages/playground/build-webpack4.js @@ -16,10 +16,7 @@ webpack4( }, plugins: [ sentryWebpackPlugin({ - sourcemaps: { - assets: "./out/webpack4/**", - deleteFilesAfterUpload: "./out/webpack4/**/*.map", - }, + debug: true, }), ], devtool: "source-map", diff --git a/packages/playground/build-webpack5.js b/packages/playground/build-webpack5.js index d4f56bf9..060891e4 100644 --- a/packages/playground/build-webpack5.js +++ b/packages/playground/build-webpack5.js @@ -18,10 +18,7 @@ webpack5( mode: "production", plugins: [ sentryWebpackPlugin({ - sourcemaps: { - assets: "./out/webpack5/**", - deleteFilesAfterUpload: "./out/webpack5/**/*.map", - }, + debug: true, }), ], devtool: "source-map", diff --git a/packages/playground/rollup.config.mjs b/packages/playground/rollup.config.mjs index f69ca7b8..4adf3b4c 100644 --- a/packages/playground/rollup.config.mjs +++ b/packages/playground/rollup.config.mjs @@ -8,10 +8,7 @@ export default { input, plugins: [ sentryRollupPlugin({ - sourcemaps: { - assets: "./out/rollup/**", - deleteFilesAfterUpload: "./out/rollup/**/*.map", - }, + debug: true, }), ], output: { diff --git a/packages/playground/vite.config.js b/packages/playground/vite.config.js index 074802dc..3efe0283 100644 --- a/packages/playground/vite.config.js +++ b/packages/playground/vite.config.js @@ -16,10 +16,7 @@ export default defineConfig({ }, plugins: [ sentryVitePlugin({ - sourcemaps: { - assets: "./out/vite/**", - deleteFilesAfterUpload: "./out/vite/**/*.map", - }, + debug: true, }), ], }); diff --git a/packages/rollup-plugin/README_TEMPLATE.md b/packages/rollup-plugin/README_TEMPLATE.md index b84c027c..dbece44e 100644 --- a/packages/rollup-plugin/README_TEMPLATE.md +++ b/packages/rollup-plugin/README_TEMPLATE.md @@ -42,33 +42,12 @@ export default { plugins: [ // Put the Sentry rollup plugin after all other plugins sentryRollupPlugin({ - org: "___ORG_SLUG___", - project: "___PROJECT_SLUG___", + org: process.env.SENTRY_ORG, + project: process.env.SENTRY_PROJECT, // Auth tokens can be obtained from https://sentry.io/settings/account/api/auth-tokens/ // and need `project:releases` and `org:read` scopes - authToken: env.SENTRY_AUTH_TOKEN, - - sourcemaps: { - // Specify the directory containing build artifacts - assets: "./**", - // Don't upload the source maps of dependencies - ignore: ["./node_modules/**"], - }, - - // Helps troubleshooting - set to false to make plugin less noisy - debug: true, - - // Use the following option if you're on an SDK version lower than 7.47.0: - // release: { - // uploadLegacySourcemaps: { - // include: ".", - // ignore: ["node_modules"], - // }, - // }, - - // Optionally uncomment the line below to override automatic release name detection - // release: env.RELEASE, + authToken: process.env.SENTRY_AUTH_TOKEN, }), ], output: { diff --git a/packages/rollup-plugin/src/index.ts b/packages/rollup-plugin/src/index.ts index 8e6da892..8357e5c8 100644 --- a/packages/rollup-plugin/src/index.ts +++ b/packages/rollup-plugin/src/index.ts @@ -3,6 +3,7 @@ import { Options, createRollupReleaseInjectionHooks, createRollupDebugIdInjectionHooks, + createRollupDebugIdUploadHooks, } from "@sentry/bundler-plugin-core"; import type { UnpluginOptions } from "unplugin"; @@ -20,9 +21,19 @@ function rollupDebugIdInjectionPlugin(): UnpluginOptions { }; } +function rollupDebugIdUploadPlugin( + upload: (buildArtifacts: string[]) => Promise +): UnpluginOptions { + return { + name: "sentry-rollup-debug-id-upload-plugin", + rollup: createRollupDebugIdUploadHooks(upload), + }; +} + const sentryUnplugin = sentryUnpluginFactory({ releaseInjectionPlugin: rollupReleaseInjectionPlugin, debugIdInjectionPlugin: rollupDebugIdInjectionPlugin, + debugIdUploadPlugin: rollupDebugIdUploadPlugin, }); // eslint-disable-next-line @typescript-eslint/no-explicit-any diff --git a/packages/vite-plugin/README_TEMPLATE.md b/packages/vite-plugin/README_TEMPLATE.md index 4718ac92..961ebff3 100644 --- a/packages/vite-plugin/README_TEMPLATE.md +++ b/packages/vite-plugin/README_TEMPLATE.md @@ -56,27 +56,6 @@ export default defineConfig({ // Auth tokens can be obtained from https://sentry.io/settings/account/api/auth-tokens/ // and need `project:releases` and `org:read` scopes authToken: process.env.SENTRY_AUTH_TOKEN, - - sourcemaps: { - // Specify the directory containing build artifacts - assets: "./**", - // Don't upload the source maps of dependencies - ignore: ["./node_modules/**"], - }, - - // Helps troubleshooting - set to false to make plugin less noisy - debug: true, - - // Use the following option if you're on an SDK version lower than 7.47.0: - // release: { - // uploadLegacySourcemaps: { - // include: ".", - // ignore: ["node_modules"], - // }, - // }, - - // Optionally uncomment the line below to override automatic release name detection - // release: env.RELEASE, }), ], }); diff --git a/packages/vite-plugin/src/index.ts b/packages/vite-plugin/src/index.ts index d956aef7..9b41a210 100644 --- a/packages/vite-plugin/src/index.ts +++ b/packages/vite-plugin/src/index.ts @@ -3,6 +3,7 @@ import { Options, createRollupReleaseInjectionHooks, createRollupDebugIdInjectionHooks, + createRollupDebugIdUploadHooks, } from "@sentry/bundler-plugin-core"; import { UnpluginOptions } from "unplugin"; @@ -21,9 +22,19 @@ function viteDebugIdInjectionPlugin(): UnpluginOptions { }; } +function viteDebugIdUploadPlugin( + upload: (buildArtifacts: string[]) => Promise +): UnpluginOptions { + return { + name: "sentry-vite-debug-id-upload-plugin", + vite: createRollupDebugIdUploadHooks(upload), + }; +} + const sentryUnplugin = sentryUnpluginFactory({ releaseInjectionPlugin: viteReleaseInjectionPlugin, debugIdInjectionPlugin: viteDebugIdInjectionPlugin, + debugIdUploadPlugin: viteDebugIdUploadPlugin, }); // eslint-disable-next-line @typescript-eslint/no-explicit-any diff --git a/packages/webpack-plugin/README_TEMPLATE.md b/packages/webpack-plugin/README_TEMPLATE.md index 1df0741f..07f4b55e 100644 --- a/packages/webpack-plugin/README_TEMPLATE.md +++ b/packages/webpack-plugin/README_TEMPLATE.md @@ -50,27 +50,6 @@ module.exports = { // Auth tokens can be obtained from https://sentry.io/settings/account/api/auth-tokens/ // and need `project:releases` and `org:read` scopes authToken: process.env.SENTRY_AUTH_TOKEN, - - sourcemaps: { - // Specify the directory containing build artifacts - assets: "./**", - // Don't upload the source maps of dependencies - ignore: ["./node_modules/**"], - }, - - // Helps troubleshooting - set to false to make plugin less noisy - debug: true, - - // Use the following option if you're on an SDK version lower than 7.47.0: - // release: { - // uploadLegacySourcemaps: { - // include: ".", - // ignore: ["node_modules"], - // }, - // }, - - // Optionally uncomment the line below to override automatic release name detection - // release: env.RELEASE, }), ], }; diff --git a/packages/webpack-plugin/src/index.ts b/packages/webpack-plugin/src/index.ts index 0ee18bbb..99b409dc 100644 --- a/packages/webpack-plugin/src/index.ts +++ b/packages/webpack-plugin/src/index.ts @@ -1,4 +1,5 @@ import { getDebugIdSnippet, Options, sentryUnpluginFactory } from "@sentry/bundler-plugin-core"; +import * as path from "path"; import { UnpluginOptions } from "unplugin"; import { v4 as uuidv4 } from "uuid"; @@ -7,11 +8,8 @@ import { v4 as uuidv4 } from "uuid"; import { BannerPlugin as Webpack4BannerPlugin } from "webpack-4"; function webpackReleaseInjectionPlugin(injectionCode: string): UnpluginOptions { - const pluginName = "sentry-webpack-release-injection-plugin"; - return { - name: pluginName, - + name: "sentry-webpack-release-injection-plugin", webpack(compiler) { if (compiler?.webpack?.BannerPlugin) { compiler.options.plugins.push( @@ -36,11 +34,8 @@ function webpackReleaseInjectionPlugin(injectionCode: string): UnpluginOptions { } function webpackDebugIdInjectionPlugin(): UnpluginOptions { - const pluginName = "sentry-webpack-debug-id-injection-plugin"; - return { - name: pluginName, - + name: "sentry-webpack-debug-id-injection-plugin", webpack(compiler) { if (compiler?.webpack?.BannerPlugin) { compiler.options.plugins.push( @@ -64,9 +59,30 @@ function webpackDebugIdInjectionPlugin(): UnpluginOptions { }; } +function webpackDebugIdUploadPlugin( + upload: (buildArtifacts: string[]) => Promise +): UnpluginOptions { + const pluginName = "sentry-webpack-debug-id-upload-plugin"; + return { + name: pluginName, + webpack(compiler) { + compiler.hooks.afterEmit.tapAsync(pluginName, (compilation, callback) => { + const outputPath = compilation.outputOptions.path ?? path.resolve(); + const buildArtifacts = Object.keys(compilation.assets).map((asset) => + path.join(outputPath, asset) + ); + void upload(buildArtifacts).then(() => { + callback(); + }); + }); + }, + }; +} + const sentryUnplugin = sentryUnpluginFactory({ releaseInjectionPlugin: webpackReleaseInjectionPlugin, debugIdInjectionPlugin: webpackDebugIdInjectionPlugin, + debugIdUploadPlugin: webpackDebugIdUploadPlugin, }); // eslint-disable-next-line @typescript-eslint/no-explicit-any From 119c5deb47ded63247c435952467f541ef4f51a3 Mon Sep 17 00:00:00 2001 From: Luca Forstner Date: Tue, 23 May 2023 17:59:40 +0200 Subject: [PATCH 2/3] Log message --- packages/bundler-plugin-core/src/debug-id-upload.ts | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/packages/bundler-plugin-core/src/debug-id-upload.ts b/packages/bundler-plugin-core/src/debug-id-upload.ts index 84727e9b..0a0c2c57 100644 --- a/packages/bundler-plugin-core/src/debug-id-upload.ts +++ b/packages/bundler-plugin-core/src/debug-id-upload.ts @@ -59,8 +59,18 @@ export function createDebugIdUploadFunction({ folderToCleanUp = tmpUploadFolder; + let globAssets; + if (assets) { + globAssets = assets; + } else { + logger.debug( + "Not `sourcemaps.assets` option provided, falling back to uploading detected build artifacts." + ); + globAssets = buildArtifactPaths; + } + const debugIdChunkFilePaths = ( - await glob(assets ?? buildArtifactPaths, { + await glob(globAssets, { absolute: true, nodir: true, ignore: ignore, From 76a23a29ec831b0f0980289ed7a0d8e2a231416f Mon Sep 17 00:00:00 2001 From: Luca Forstner Date: Wed, 24 May 2023 10:58:45 +0200 Subject: [PATCH 3/3] Update packages/bundler-plugin-core/src/debug-id-upload.ts Co-authored-by: Lukas Stracke --- packages/bundler-plugin-core/src/debug-id-upload.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/bundler-plugin-core/src/debug-id-upload.ts b/packages/bundler-plugin-core/src/debug-id-upload.ts index 0a0c2c57..cd575670 100644 --- a/packages/bundler-plugin-core/src/debug-id-upload.ts +++ b/packages/bundler-plugin-core/src/debug-id-upload.ts @@ -64,7 +64,7 @@ export function createDebugIdUploadFunction({ globAssets = assets; } else { logger.debug( - "Not `sourcemaps.assets` option provided, falling back to uploading detected build artifacts." + "No `sourcemaps.assets` option provided, falling back to uploading detected build artifacts." ); globAssets = buildArtifactPaths; }