Staging Environment remains when promoting from staging to prod without an extra build step
Problem Statement
An issue has been identified with the @sentry/vite-plugin in relation to Heroku pipeline workflows:
- The Sentry configuration is injected during the initial build step, typically executed in a staging environment.
- Upon promotion from staging to production within Heroku, an additional build step is not triggered. As a result, the staging Sentry settings persist and remain active in the production environment.
This causes two significant problems:
- Errors originating from the production environment are incorrectly reported to the staging environment in Sentry.
- Flexible strategies for source map deletion, such as deleting sourcemaps post-upload exclusively in production, are currently unavailable.
Desired Behavior
The Sentry Vite plugin should ideally support environment-specific configurations or allow dynamic injection of configurations post-build, improving compatibility with pipeline workflows like Heroku. Specifically:
- Provide functionality to dynamically inject or override Sentry configurations at runtime instead of only at the initial build step.
- (not specifically related)Support distinct configurations for source map deletion between staging and production environments, possibly through post-promotion scripting.
In theory the environment is never determined at build-time, only at runtime 🤔 I am wondering how that comes to be. Is the customer maybe bundling the environment into their bundles themselves? If so it is not something we can control from within the bundler plugins.
In theory the environment is never determined at build-time, only at runtime 🤔 I am wondering how that comes to be. Is the customer maybe bundling the environment into their bundles themselves? If so it is not something we can control from within the bundler plugins.
We (beehiiv) are the customer who reported this so happy to step in! So with Heroku or Coolify, you have separate apps for each stage in the pipeline (most commonly staging & production, plus development if you have review apps).
We have separate Sentry configs for staging & production and want to expose sourcemaps to the browser in staging for our developers to easier debug. With the Vite plugin, we have to define project, sourcemap config, etc. in the vite.config.mts, which only is running once — when it builds on staging. It doesn't rebuild on promotion to prod. So the static assets created on staging are 1-to-1 with production.
Our workaround for non-sensitive environment variables here is that we run a script on our Rails server (obviously not static) responsible for serving our Vite-built static assets that injects anything with the VITE_ prefix into the window.env, so it can change at runtime. If an environment variable is changed, that variable script reruns and injects the updated variables into the window, which the JavaScript app is then consuming.
Issue here obviously is our Sentry secrets are not able to be publicly exposed and because it does all the Sentry config on build with the Vite plugin, the config on staging is identical to the one that gets promoted.
Was just thinking through this further: I wonder if we could use a fetch function to get the Sentry config info at runtime?
I've seen folks write similar API endpoints so they can realtime fetch secrets during build. Not sure if the Sentry Vite plugin is capable of doing this but it'd work.
I hate having to respond with this answer but unfortunately this is not a limitation of the Sentry SDK - it's not even something that we can resolve from within the SDK - it's simply a limitation of static bundles. If you want to change static values you have to rebuild. There is no way around it.
The only workaround you seem to already have discovered, which is having a side effect that tries to figure out whether you are in prod or staging and informing the SDK with the corresponding env based on that.
I hate having to respond with this answer but unfortunately this is not a limitation of the Sentry SDK - it's not even something that we can resolve from within the SDK - it's simply a limitation of static bundles. If you want to change static values you have to rebuild. There is no way around it.
The only workaround you seem to already have discovered, which is having a side effect that tries to figure out whether you are in prod or staging and informing the SDK with the corresponding env based on that.
That's alright. I figured it could be a limitation around static bundling in general.
Do you know if the Sentry Vite plugin would be able to accept a function as the value for project and deploy.env? Happy to write a workaround if it can.
Do you know if the Sentry Vite plugin would be able to accept a function as the value for project and deploy.env?
@JacobNWolf correct me if I am wrong but can't you just compute these values before calling sentryVitePlugin() and pass them directly? I don't quite see the value behind a function here yet.
Do you know if the Sentry Vite plugin would be able to accept a function as the value for project and deploy.env?
@JacobNWolf correct me if I am wrong but can't you just compute these values before calling
sentryVitePlugin()and pass them directly? I don't quite see the value behind a function here yet.
I think we might hit the same issue we're hitting originally here, which is that the vite.config.mts is only running at build time so it won't run again. My idea for a function was that we could have an endpoint(s) somewhere on the Rails side that returns the appropriate Sentry environment information. That could be hit as a before action hook that fires prior to the telemetry info being sent to Sentry.
I think we might hit the same issue we're hitting originally here
@JacobNWolf sounds like it. Unfortunately, as I originally pointed out, this is past the scope of the SDK.