Skip to content

Commit

Permalink
fix(nextjs): Download CLI binary if it can't be found (#9584)
Browse files Browse the repository at this point in the history
  • Loading branch information
lforst authored Nov 16, 2023
1 parent 5698094 commit ed2b201
Show file tree
Hide file tree
Showing 3 changed files with 100 additions and 36 deletions.
2 changes: 1 addition & 1 deletion packages/nextjs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
"@sentry/types": "7.80.1",
"@sentry/utils": "7.80.1",
"@sentry/vercel-edge": "7.80.1",
"@sentry/webpack-plugin": "1.20.0",
"@sentry/webpack-plugin": "1.21.0",
"chalk": "3.0.0",
"resolve": "1.22.8",
"rollup": "2.78.0",
Expand Down
93 changes: 68 additions & 25 deletions packages/nextjs/src/config/webpack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import * as chalk from 'chalk';
import * as fs from 'fs';
import * as path from 'path';
import { sync as resolveSync } from 'resolve';
import type { Compiler } from 'webpack';

import type { VercelCronsConfig } from '../common/types';
// Note: If you need to import a type from Webpack, do it in `types.ts` and export it from there. Otherwise, our
Expand All @@ -22,6 +23,7 @@ import type {
WebpackConfigObjectWithModuleRules,
WebpackEntryProperty,
WebpackModuleRule,
WebpackPluginInstance,
} from './types';

const RUNTIME_TO_SDK_ENTRYPOINT_MAP = {
Expand All @@ -35,8 +37,8 @@ const RUNTIME_TO_SDK_ENTRYPOINT_MAP = {
let showedMissingAuthTokenErrorMsg = false;
let showedMissingOrgSlugErrorMsg = false;
let showedMissingProjectSlugErrorMsg = false;
let showedMissingCLiBinaryErrorMsg = false;
let showedHiddenSourceMapsWarningMsg = false;
let showedMissingCliBinaryWarningMsg = false;

// TODO: merge default SentryWebpackPlugin ignore with their SentryWebpackPlugin ignore or ignoreFile
// TODO: merge default SentryWebpackPlugin include with their SentryWebpackPlugin include
Expand Down Expand Up @@ -376,6 +378,7 @@ export function constructWebpackConfigFunction(
const SentryWebpackPlugin = loadModule<SentryCliPlugin>('@sentry/webpack-plugin');
if (SentryWebpackPlugin) {
newConfig.plugins = newConfig.plugins || [];
newConfig.plugins.push(new SentryCliDownloadPlugin());
newConfig.plugins.push(
// @ts-expect-error - this exists, the dynamic import just doesn't know about it
new SentryWebpackPlugin(
Expand Down Expand Up @@ -739,6 +742,19 @@ export function getWebpackPluginOptions(
if (err) {
const errorMessagePrefix = `${chalk.red('error')} -`;

if (err.message.includes('ENOENT')) {
if (!showedMissingCliBinaryWarningMsg) {
// eslint-disable-next-line no-console
console.error(
`\n${errorMessagePrefix} ${chalk.bold(
'The Sentry binary to upload sourcemaps could not be found.',
)} Source maps will not be uploaded. Please check that post-install scripts are enabled in your package manager when installing your dependencies and please run your build once without any caching to avoid caching issues of dependencies.\n`,
);
showedMissingCliBinaryWarningMsg = true;
}
return;
}

// Hardcoded way to check for missing auth token until we have a better way of doing this.
if (err.message.includes('Authentication credentials were not provided.')) {
let msg;
Expand Down Expand Up @@ -835,30 +851,6 @@ function shouldEnableWebpackPlugin(buildContext: BuildContext, userSentryOptions
const { isServer } = buildContext;
const { disableServerWebpackPlugin, disableClientWebpackPlugin } = userSentryOptions;

/** Non-negotiable */

// This check is necessary because currently, `@sentry/cli` uses a post-install script to download an
// architecture-specific version of the `sentry-cli` binary. If `yarn install`, `npm install`, or `npm ci` are run
// with the `--ignore-scripts` option, this will be blocked and the missing binary will cause an error when users
// try to build their apps.
const SentryWebpackPlugin = loadModule<SentryCliPlugin>('@sentry/webpack-plugin');

// @ts-expect-error - this exists, the dynamic import just doesn't know it
if (!SentryWebpackPlugin || !SentryWebpackPlugin.cliBinaryExists()) {
if (!showedMissingCLiBinaryErrorMsg) {
// eslint-disable-next-line no-console
console.error(
`${chalk.red('error')} - ${chalk.bold(
'Sentry CLI binary not found.',
)} Source maps will not be uploaded. Please check that postinstall scripts are enabled in your package manager when installing your dependencies and please run your build once without any caching to avoid caching issues of dependencies.\n`,
);
showedMissingCLiBinaryErrorMsg = true;
}
return false;
}

/** User override */

if (isServer && disableServerWebpackPlugin !== undefined) {
return !disableServerWebpackPlugin;
} else if (!isServer && disableClientWebpackPlugin !== undefined) {
Expand Down Expand Up @@ -1047,3 +1039,54 @@ function getRequestAsyncStorageModuleLocation(

return undefined;
}

let downloadingCliAttempted = false;

class SentryCliDownloadPlugin implements WebpackPluginInstance {
public apply(compiler: Compiler): void {
compiler.hooks.beforeRun.tapAsync('SentryCliDownloadPlugin', (compiler, callback) => {
const SentryWebpackPlugin = loadModule<SentryCliPlugin>('@sentry/webpack-plugin');
if (!SentryWebpackPlugin) {
// Pretty much an invariant.
return callback();
}

// @ts-expect-error - this exists, the dynamic import just doesn't know it
if (SentryWebpackPlugin.cliBinaryExists()) {
return callback();
}

if (!downloadingCliAttempted) {
downloadingCliAttempted = true;
// eslint-disable-next-line no-console
console.log(
`\n${chalk.cyan('info')} - ${chalk.bold(
'Sentry binary to upload source maps not found.',
)} Package manager post-install scripts are likely disabled or there is a caching issue. Manually downloading instead...`,
);

// @ts-expect-error - this exists, the dynamic import just doesn't know it
const cliDownloadPromise: Promise<void> = SentryWebpackPlugin.downloadCliBinary({
log: () => {
// No logs from directly from CLI
},
});

cliDownloadPromise.then(
() => {
// eslint-disable-next-line no-console
console.log(`${chalk.cyan('info')} - Sentry binary was successfully downloaded.\n`);
return callback();
},
e => {
// eslint-disable-next-line no-console
console.error(`${chalk.red('error')} - Sentry binary download failed:`, e);
return callback();
},
);
} else {
return callback();
}
});
}
}
41 changes: 31 additions & 10 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -5067,7 +5067,7 @@
magic-string "0.27.0"
unplugin "1.0.1"

"@sentry/cli@^1.74.4", "@sentry/cli@^1.74.6":
"@sentry/cli@^1.74.4":
version "1.74.6"
resolved "https://registry.yarnpkg.com/@sentry/cli/-/cli-1.74.6.tgz#c4f276e52c6f5e8c8d692845a965988068ebc6f5"
integrity sha512-pJ7JJgozyjKZSTjOGi86chIngZMLUlYt2HOog+OJn+WGvqEkVymu8m462j1DiXAnex9NspB4zLLNuZ/R6rTQHg==
Expand All @@ -5080,6 +5080,18 @@
proxy-from-env "^1.1.0"
which "^2.0.2"

"@sentry/cli@^1.77.1":
version "1.77.1"
resolved "https://registry.yarnpkg.com/@sentry/cli/-/cli-1.77.1.tgz#ebcf884712ef6c3c75443f491ec16f6a22148aec"
integrity sha512-OtJ7U9LeuPUAY/xow9wwcjM9w42IJIpDtClTKI/RliE685vd/OJUIpiAvebHNthDYpQynvwb/0iuF4fonh+CKw==
dependencies:
https-proxy-agent "^5.0.0"
mkdirp "^0.5.5"
node-fetch "^2.6.7"
progress "^2.0.3"
proxy-from-env "^1.1.0"
which "^2.0.2"

"@sentry/cli@^2.17.0":
version "2.17.0"
resolved "https://registry.yarnpkg.com/@sentry/cli/-/cli-2.17.0.tgz#fc809ecd721eb5323502625fa904b786af28ad89"
Expand Down Expand Up @@ -5124,12 +5136,12 @@
dependencies:
"@sentry/cli" "^1.74.4"

"@sentry/webpack-plugin@1.20.0":
version "1.20.0"
resolved "https://registry.yarnpkg.com/@sentry/webpack-plugin/-/webpack-plugin-1.20.0.tgz#e7add76122708fb6b4ee7951294b521019720e58"
integrity sha512-Ssj1mJVFsfU6vMCOM2d+h+KQR7QHSfeIP16t4l20Uq/neqWXZUQ2yvQfe4S3BjdbJXz/X4Rw8Hfy1Sd0ocunYw==
"@sentry/webpack-plugin@1.21.0":
version "1.21.0"
resolved "https://registry.yarnpkg.com/@sentry/webpack-plugin/-/webpack-plugin-1.21.0.tgz#bbe7cb293751f80246a4a56f9a7dd6de00f14b58"
integrity sha512-x0PYIMWcsTauqxgl7vWUY6sANl+XGKtx7DCVnnY7aOIIlIna0jChTAPANTfA2QrK+VK+4I/4JxatCEZBnXh3Og==
dependencies:
"@sentry/cli" "^1.74.6"
"@sentry/cli" "^1.77.1"
webpack-sources "^2.0.0 || ^3.0.0"

"@sideway/address@^4.1.3":
Expand Down Expand Up @@ -8290,10 +8302,10 @@ aws4@^1.8.0:
resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.11.0.tgz#d61f46d83b2519250e2784daf5b09479a8b41c59"
integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==

axios@1.3.4, axios@^1.2.2:
version "1.3.4"
resolved "https://registry.yarnpkg.com/axios/-/axios-1.3.4.tgz#f5760cefd9cfb51fd2481acf88c05f67c4523024"
integrity sha512-toYm+Bsyl6VC5wSkfkbbNB6ROv7KY93PEBBL6xyDczaIHasAiv4wPqQ/c4RjoQzipxRD2W5g21cOqQulZ7rHwQ==
axios@1.6.0:
version "1.6.0"
resolved "https://registry.yarnpkg.com/axios/-/axios-1.6.0.tgz#f1e5292f26b2fd5c2e66876adc5b06cdbd7d2102"
integrity sha512-EZ1DYihju9pwVB+jg67ogm+Tmqc6JmhamRN6I4Zt8DfZu5lbcQGw3ozH9lFejSJgs/ibaef3A9PMXPLeefFGJg==
dependencies:
follow-redirects "^1.15.0"
form-data "^4.0.0"
Expand All @@ -8316,6 +8328,15 @@ axios@^1.0.0:
form-data "^4.0.0"
proxy-from-env "^1.1.0"

axios@^1.2.2:
version "1.3.4"
resolved "https://registry.yarnpkg.com/axios/-/axios-1.3.4.tgz#f5760cefd9cfb51fd2481acf88c05f67c4523024"
integrity sha512-toYm+Bsyl6VC5wSkfkbbNB6ROv7KY93PEBBL6xyDczaIHasAiv4wPqQ/c4RjoQzipxRD2W5g21cOqQulZ7rHwQ==
dependencies:
follow-redirects "^1.15.0"
form-data "^4.0.0"
proxy-from-env "^1.1.0"

b4a@^1.6.4:
version "1.6.4"
resolved "https://registry.yarnpkg.com/b4a/-/b4a-1.6.4.tgz#ef1c1422cae5ce6535ec191baeed7567443f36c9"
Expand Down

0 comments on commit ed2b201

Please sign in to comment.