-
-
Notifications
You must be signed in to change notification settings - Fork 952
Description
Provide environment information
N/A
Describe the bug
Expected behavior: Sourcemaps should be automatically uploaded to Sentry during deployment when using the sentryEsbuildPlugin with the documented configuration.
Actual behavior: No sourcemaps are uploaded. The plugin appears to run but doesn't detect or upload any files.
Potential root causes:
-
Timing issue: The plugin runs during esbuild, but files aren't finalized yet. Even with
placement: "last", the build continues modifying files, so the plugin can't find them. -
File extension mismatch: Trigger.dev outputs
.mjsand.mjs.mapfiles, but Sentry's plugin defaults to looking for.jsand.js.mapfiles. -
Path prefix mismatch: Sentry expects paths prefixed with
/app/, but the built sourcemap files don't have this prefix.
Reproduction repo
N/A
To reproduce
- Configure
sentryEsbuildPluginintrigger.config.tsas documented:
import { defineConfig } from "@trigger.dev/sdk";
import { esbuildPlugin } from "@trigger.dev/build/extensions";
import { sentryEsbuildPlugin } from "@sentry/esbuild-plugin";
export default defineConfig({
project: "<project ref>",
build: {
extensions: [
esbuildPlugin(
sentryEsbuildPlugin({
org: process.env.SENTRY_ORG,
project: process.env.SENTRY_PROJECT,
authToken: process.env.SENTRY_AUTH_TOKEN,
}),
{ placement: "last", target: "deploy" }
),
],
},
});
-
Set required environment variables (
SENTRY_ORG,SENTRY_PROJECT,SENTRY_AUTH_TOKEN,COMMIT) -
Run
trigger.dev deploy -
Check Sentry dashboard - no sourcemaps are uploaded
Additional information
Workaround solution
Workaround implemented using the onBuildComplete hook:
{
name: "sentry-sourcemap-upload",
async onBuildComplete(context, manifest) {
if (context.target !== "deploy") {
context.logger.debug(
"[Sentry] Skipping sourcemap upload for non-deploy target",
);
return;
}
const release = process.env.COMMIT;
const authToken = process.env.SENTRY_AUTH_TOKEN;
if (!release || !authToken) {
context.logger.warn(
"[Sentry] Missing required env vars, skipping sourcemap upload",
);
return;
}
const outputPath = manifest.outputPath;
context.logger.log(
`[Sentry] Uploading sourcemaps from ${outputPath} for release ${release}`,
);
const { execSync } = await import("child_process");
try {
// Create the release
execSync(
`npx @sentry/cli releases new ${release} --org replo-hq --project trigger`,
{
env: { ...process.env, SENTRY_AUTH_TOKEN: authToken },
stdio: "inherit",
},
);
// Inject debug IDs into the built files. This modifies the .mjs files
// to include debug IDs that Sentry uses to match errors to sourcemaps.
execSync(
`npx @sentry/cli sourcemaps inject --ext mjs --ignore node_modules "${outputPath}"`,
{
env: { ...process.env, SENTRY_AUTH_TOKEN: authToken },
stdio: "inherit",
},
);
// Upload sourcemaps (debug IDs are now in both .mjs and .mjs.map files)
execSync(
`npx @sentry/cli sourcemaps upload --release ${release} --org replo-hq --project trigger --ext mjs --ext map --ignore node_modules --url-prefix /app/ "${outputPath}"`,
{
env: { ...process.env, SENTRY_AUTH_TOKEN: authToken },
stdio: "inherit",
},
);
// Finalize the release
execSync(
`npx @sentry/cli releases finalize ${release} --org replo-hq --project trigger`,
{
env: { ...process.env, SENTRY_AUTH_TOKEN: authToken },
stdio: "inherit",
},
);
context.logger.log("[Sentry] Sourcemap upload complete");
} catch (error) {
context.logger.warn(`[Sentry] Sourcemap upload failed: ${error}`);
}
},
}