getsentry / sentry-javascript-bundler-plugins

JavaScript Bundler Plugins for Sentry
https://sentry.io
BSD 3-Clause "New" or "Revised" License
141 stars 36 forks source link

Could not resolve `_sentry-release-injection-stub` #614

Open ZeroX-DG opened 1 month ago

ZeroX-DG commented 1 month ago

Hi, I'm using @sentry/esbuild-plugin@2.22.4 with @angular-builders/custom-esbuild@18 and the Angular build failed with this error:

✘ [ERROR] Could not resolve "/path/to/project/_sentry-release-injection-stub" [plugin angular-compiler]

I think it could be that the newer version of esbuild some how break this line: https://github.com/getsentry/sentry-javascript-bundler-plugins/blob/75a5d1debb8793a572ab495361b613138b452bb2/packages/esbuild-plugin/src/index.ts#L15

The only workaround that I could find is to set release.inject to false which would make the build succeed but then there's no debugID injected to the build output & so sentry-esbuild-plugin would just ignore and not upload any of our code artifacts.

[sentry-esbuild-plugin] Warning: Didn't find any matching sources for debug ID upload. Please check the `sourcemaps.assets` option.
lforst commented 1 month ago

Hi, would you mind providing a small repro example so we can take a closer look? Thanks!

ZeroX-DG commented 1 month ago

Hi @lforst, I've created a test repo here: https://github.com/ZeroX-DG/sentry-esbuild-demo

Although I don't have a test sentry org & auth token to replace to the config so I can't test if it's actually working.

You can fill in the sentry authentication key in custom-esbuild-plugins.ts and run yarn build to see if the error actually occurs.

lforst commented 1 month ago

Thanks! We're a bit busy this week so I need to put this on the backlog. Feel free to investigate on your own in the meantime.

ex0ns commented 1 month ago

Following my investigation on #616 (thanks again for linking me to this issue), which is based on tsup (using esbuild under the hood), it seems that the onResolve and onLoad callbacks are only called for "internal" modules (i.e importing relative path).

I would believe that a fix could be to replace all occurrences of _sentry-release-injection-stub and _sentry-debug-id-ingestion-stub with ./_sentry-release-injection-stub and ./_sentry-debug-id-ingestion-stub, those would be considered local and correctly processed by esbuild.

My current workaround is to add this to my tsup.config.ts:

  noExternal: ["_sentry-debug-id-injection-stub"],

Which forces esbuild to consider the file as a local file. the generated file looks correct:

// _sentry-release-injection-stub
var _global = typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : {};
_global.SENTRY_RELEASE = { id: "012ec3c3a45c4f3d921e71aeb5a29abeeaab6b98" };

// sentry-debug-id-stub:_sentry-debug-id-injection-stub?sentry-module-id=996d7825-4b8c-4053-a10c-9e9232bbeefb
!function() {
  try {
    var e = "undefined" != typeof window ? window : "undefined" != typeof global ? global : "undefined" != typeof self ? self : {}, n = new e.Error().stack;
    n && (e._sentryDebugIds = e._sentryDebugIds || {}, e._sentryDebugIds[n] = "5ea6224e-be36-45c9-b0c7-ea8b9fb1af0f", e._sentryDebugIdIdentifier = "sentry-dbid-5ea6224e-be36-45c9-b0c7-ea8b9fb1af0f");
  } catch (e2) {
  }
}();

// src/instrument.ts

I don't know when this broke and if esbuild changed the way plugins are working but I would be glad to provide you more information if needed.

lforst commented 1 month ago

@ex0ns that is some nice investigation. Thanks! A bit of an annoying nuance that esbuild has.

Do you feel like contributing the change or should we take care of it? Maybe you're able to try it out for your setup and verify whether it works!

ex0ns commented 1 month ago

I will try to contribute and add a fix, but I can't promise anything yet. After trying the above fix, the issue I'm now facing https://github.com/getsentry/sentry-javascript-bundler-plugins/issues/608 which I did not get any chance to investigate.

Edit: After a quick investigation it seems that the original guess reported on #608 is correct, when the onEnd callback of the debug id upload plugin is called the file are not written to disk yet. I did not use previous version of esbuild/sentry/tsup so I don't know if this is a regression somewhere or if it has always been that way (that would surprise me), but I think that the main issue is coming from this line: https://github.com/getsentry/sentry-javascript-bundler-plugins/blob/2.22.5/packages/bundler-plugin-core/src/debug-id-upload.ts#L93

globAssets in the case correctly contains the list of relative file path for "files that will be written to disk later". But the result of the glob function is always an empty array (as those do not exists on disk yet).

I don't know this codebase (or tsup's) well enough yet to think of a fix, but my guess is that onEnd is called before the file are written to disk in order to give a last chance to any plugin to update their content. I guess this is happening whenever the clean: true flag is set in tsup's config as it will clean the dist folder before running the build, which lead me to think that people not using the clean: true flag might be uploaded their old output instead of the newly created (as long as the filenames are matching).

lforst commented 1 month ago

Re the first issue:

I would believe that a fix could be to replace all occurrences of _sentry-release-injection-stub and _sentry-debug-id-ingestion-stub with ./_sentry-release-injection-stub and ./_sentry-debug-id-ingestion-stub, those would be considered local and correctly processed by esbuild.

The unlucky thing is that it needs to be absolute for older eslint versions 🤔 Maybe we just drop support and release a major.