honeybadger-js: [rollup-plugin] - Sourcemaps failing to upload when directory containing them has been deleted prior to upload happening

What are the steps to reproduce this issue?

  1. Set up an app which runs vite build in a Heroku Nodejs buildpack
  2. Have the build command run in the buildpack

What happens?

  • Most sourcemap files that are output are uploaded
  • Sourcemap files that are found in the ephemeral tmp/build_... directory are not uploaded because they no longer exist, even though their entries show up in the bundle object which this plugin reads entries from. The build fails because this results in an Error being thrown.

What were you expecting to happen?

  • No issues. Sourcemaps are uploaded successfully.

Any logs, error output, etc?

image

Any other comments?

What versions are you using?

Operating System: Building on the Heroku-20 stack -----> Using buildpacks: 1. heroku/nodejs 2. heroku/ruby Package Name: @honeybadger-io/rollup-plugin Package Version: 5.1.5 Browser Version: N/A

About this issue

  • Original URL
  • State: closed
  • Created a year ago
  • Reactions: 1
  • Comments: 16 (6 by maintainers)

Commits related to this issue

Most upvoted comments

Hey @joekrump, we just released v5.4.0 of the @honeybadger-io/rollup-plugin with an ingorePaths option and an algorithm improvement to skip source maps that have empty sourcesContent.

Thank you for all your help on this!

cc @BethanyBerkowitz

Thanks @subzero10! Any chance you can make that sample app open source that sample vite app? It might help me out and others in the future.

Here it is. Note that it doesn’t even create a static page. I just added the nodejs buildpack on Heroku and made sure that the build step is executed:

-----> Build
       Running build
       
       > vite-js-1053@0.0.1 build
       > vue-tsc && vite build
       
       vite v4.3.1 building for production...
       transforming...
       ✓ 18 modules transformed.
       rendering chunks...
       computing gzip size...
       dist/index.html                  0.45 kB │ gzip:  0.30 kB
       dist/assets/vue-5532db34.svg     0.50 kB │ gzip:  0.31 kB
       dist/assets/index-c322ae43.css   1.30 kB │ gzip:  0.67 kB
       dist/assets/index-2424b2d8.js   54.54 kB │ gzip: 22.02 kB │ map: 565.12 kB
       Successfully uploaded assets/index-2424b2d8.js.map to Honeybadger
       1 sourcemap file(s) successfully uploaded to Honeybadger
       ✓ built in 1.54s
       
-----> Caching build
       - npm cache
       
-----> Pruning devDependencies
       
       up to date, audited 22 packages in 287ms
       
       2 packages are looking for funding
         run `npm fund` for details
       
       found 0 vulnerabilities
       npm notice 
       npm notice New minor version of npm available! 9.5.1 -> 9.6.5
       npm notice Changelog: <https://github.com/npm/cli/releases/tag/v9.6.5>
       npm notice Run `npm install -g npm@9.6.5` to update!
       npm notice 
       
-----> Build succeeded!
 !     This app may not specify any way to start a node process
       https://devcenter.heroku.com/articles/nodejs-support#default-web-process-type
-----> Discovering process types
       Procfile declares types     -> (none)
       Default types for buildpack -> web
-----> Compressing...
       Done: 45.7M
-----> Launching...
       Released v4
       https://vite-js-1053.herokuapp.com/ deployed to Heroku

I am thinking that if sourcesContent is empty, we should probably ignore those files by default.

💯 That would be a great default to add and would fix my issue I think.

If that’s the case, the ignorePath could still be helpful, but what might be even more helpful might be something like an ignoreSourcemapFn or something like that which would allow someone to run some custom check on a sourcemap before determining it’s something that should be uploaded or not. What do you think?

In my case, I’d want to have a guard that did something like JSON.parse(sourcemap.source).sourcesContent !== []

Thanks @subzero10! Any chance you can make that sample app open source that sample vite app? It might help me out and others in the future.

The files in tmp get copied over into my public directory and so all the files will end up existing there.

Re vite.config.ts. I’ve defined HONEYBADGER_API_KEY, etc because they are used elsewhere in some other js code where I’m calling Honeybadger.configure() when my vue app first mounts.

Hey @BethanyBerkowitz sorry for the delay in getting back to you. I think the reason things are ending up in tmp is because the build is happening in a Heroku buildpack which is ephemeral and by the time the upload attempts to happen, it is no longer available.

It’s a similar problem as to what is described in this SO post: https://stackoverflow.com/questions/73552104/cant-access-heroku-tmp-build-sha-build-files-in-github-action-once-build-has

.js.map files that were successfully uploaded existed in my app’s public/vite/assets directory.

So I think that what is happening is that because the build happens in this ephemeral Heroku buildpack, that in the output bundle file is created (which is read by this rollup plugin), it lists that there are .js.map files within the tmp directory (which there were at the time of the build), however, by the time the sourcemap upload happens, those files and that entire directory have been cleaned up and only the files in public/vite/assets remain.

vite.config.ts:

import { defineConfig } from 'vite';
import rubyPlugin from 'vite-plugin-ruby';
import vue from '@vitejs/plugin-vue';
import svgLoader from 'vite-svg-loader';
import fullReload from 'vite-plugin-full-reload';
import { brotliCompress } from 'zlib';
import { promisify } from 'util';
import gzipPlugin from 'rollup-plugin-gzip';
import honeybadgerRollupPlugin from '@honeybadger-io/rollup-plugin';

const HONEYBADGER_API_KEY = JSON.stringify(process.env.HONEYBADGER_FRONTEND_API_KEY)?.trim();
const HONEYBADGER_REVISION = JSON.stringify(process.env.SOURCE_VERSION)?.trim();
const ENVIRONMENT = JSON.stringify(process.env.ENVIRONMENT)?.trim();
// eslint-disable-next-line no-relative-import-paths/no-relative-import-paths, import/extensions
import { RESOLUTION_ALIASES } from './config/vite';

const plugins = [
  // Do a full reload when changes are made to files with paths that match these.
  fullReload(['app/views/**/*']),
  rubyPlugin(),
  svgLoader(),
  vue(),
];

const rollupPlugins = [];

// Only compress assets in non-development environments.
if (process.env.VITE_RUBY_MODE && process.env.VITE_RUBY_MODE !== 'development') {
  const honeybadgerPluginOptions = {
    apiKey: process.env.HONEYBADGER_FRONTEND_API_KEY,
    assetsUrl:
      process.env.ENVIRONMENT === 'staging'
        ? 'https://staging-asset-url.com'
        : 'https://production-asset-url.com',
    revision: process.env.SOURCE_VERSION,
  };
  // used for uploading sourcemaps to honeybadger to allow for better debugging
  rollupPlugins.push(honeybadgerRollupPlugin(honeybadgerPluginOptions));

  const brotliPromise = promisify(brotliCompress);
  plugins.push(
    gzipPlugin({
      customCompression: (content) => brotliPromise(Buffer.from(content)),
      fileName: '.br',
    })
  );
}

export default defineConfig({
  build: {
    sourcemap: process.env?.VITE_RUBY_MODE === 'development' ? 'inline' : 'hidden',
    rollupOptions: {
      plugins: rollupPlugins
    }
  },
  resolve: {
    alias: RESOLUTION_ALIASES,
  },
  define: {
    HONEYBADGER_API_KEY,
    ENVIRONMENT,
    HONEYBADGER_REVISION,
  },
  plugins,
});

Hi @joekrump, thanks for reaching out! Just to clarify, you believe the files in tmp/ should not be uploaded, correct? I want to understand why they’re even being generated since I don’t see that happening when building locally with Vite. When I build, it looks like I just get assets in /dist/assets. Do you know if this is a Heroku thing?

Your suggestion of setting an ignorePath seems very reasonable, I’m just wondering if dumping files into /tmp and then deleting them is expected behavior… if so, perhaps we should exclude those files by default rather than adding additional config.

Are you able to tell what folder those assets that were successfully uploaded were located in?

Also, would you mind sharing your vite.config.js just in case there’s anything relevant?

It would be great if I could set something like an ignorePath regex or glob which I could set to "tmp/build_*" in the plugin config options. That would then be able to be used in isSourcemap: https://github.com/honeybadger-io/honeybadger-js/blob/a10f68655e4949e32f0fbe0ed8cdb763232d6497/packages/rollup-plugin/src/rollupUtils.ts#LL21C25-L21C25