@@ -7,6 +7,7 @@ import * as chalk from 'chalk';
7
7
import * as fs from 'fs' ;
8
8
import * as path from 'path' ;
9
9
import { sync as resolveSync } from 'resolve' ;
10
+ import type { Compiler } from 'webpack' ;
10
11
11
12
import type { VercelCronsConfig } from '../common/types' ;
12
13
// Note: If you need to import a type from Webpack, do it in `types.ts` and export it from there. Otherwise, our
@@ -22,6 +23,7 @@ import type {
22
23
WebpackConfigObjectWithModuleRules ,
23
24
WebpackEntryProperty ,
24
25
WebpackModuleRule ,
26
+ WebpackPluginInstance ,
25
27
} from './types' ;
26
28
27
29
const RUNTIME_TO_SDK_ENTRYPOINT_MAP = {
@@ -35,8 +37,8 @@ const RUNTIME_TO_SDK_ENTRYPOINT_MAP = {
35
37
let showedMissingAuthTokenErrorMsg = false ;
36
38
let showedMissingOrgSlugErrorMsg = false ;
37
39
let showedMissingProjectSlugErrorMsg = false ;
38
- let showedMissingCLiBinaryErrorMsg = false ;
39
40
let showedHiddenSourceMapsWarningMsg = false ;
41
+ let showedMissingCliBinaryWarningMsg = false ;
40
42
41
43
// TODO: merge default SentryWebpackPlugin ignore with their SentryWebpackPlugin ignore or ignoreFile
42
44
// TODO: merge default SentryWebpackPlugin include with their SentryWebpackPlugin include
@@ -376,6 +378,7 @@ export function constructWebpackConfigFunction(
376
378
const SentryWebpackPlugin = loadModule < SentryCliPlugin > ( '@sentry/webpack-plugin' ) ;
377
379
if ( SentryWebpackPlugin ) {
378
380
newConfig . plugins = newConfig . plugins || [ ] ;
381
+ newConfig . plugins . push ( new SentryCliDownloadPlugin ( ) ) ;
379
382
newConfig . plugins . push (
380
383
// @ts -expect-error - this exists, the dynamic import just doesn't know about it
381
384
new SentryWebpackPlugin (
@@ -739,6 +742,19 @@ export function getWebpackPluginOptions(
739
742
if ( err ) {
740
743
const errorMessagePrefix = `${ chalk . red ( 'error' ) } -` ;
741
744
745
+ if ( err . message . includes ( 'ENOENT' ) ) {
746
+ if ( ! showedMissingCliBinaryWarningMsg ) {
747
+ // eslint-disable-next-line no-console
748
+ console . error (
749
+ `\n${ errorMessagePrefix } ${ chalk . bold (
750
+ 'The Sentry binary to upload sourcemaps could not be found.' ,
751
+ ) } 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`,
752
+ ) ;
753
+ showedMissingCliBinaryWarningMsg = true ;
754
+ }
755
+ return ;
756
+ }
757
+
742
758
// Hardcoded way to check for missing auth token until we have a better way of doing this.
743
759
if ( err . message . includes ( 'Authentication credentials were not provided.' ) ) {
744
760
let msg ;
@@ -835,30 +851,6 @@ function shouldEnableWebpackPlugin(buildContext: BuildContext, userSentryOptions
835
851
const { isServer } = buildContext ;
836
852
const { disableServerWebpackPlugin, disableClientWebpackPlugin } = userSentryOptions ;
837
853
838
- /** Non-negotiable */
839
-
840
- // This check is necessary because currently, `@sentry/cli` uses a post-install script to download an
841
- // architecture-specific version of the `sentry-cli` binary. If `yarn install`, `npm install`, or `npm ci` are run
842
- // with the `--ignore-scripts` option, this will be blocked and the missing binary will cause an error when users
843
- // try to build their apps.
844
- const SentryWebpackPlugin = loadModule < SentryCliPlugin > ( '@sentry/webpack-plugin' ) ;
845
-
846
- // @ts -expect-error - this exists, the dynamic import just doesn't know it
847
- if ( ! SentryWebpackPlugin || ! SentryWebpackPlugin . cliBinaryExists ( ) ) {
848
- if ( ! showedMissingCLiBinaryErrorMsg ) {
849
- // eslint-disable-next-line no-console
850
- console . error (
851
- `${ chalk . red ( 'error' ) } - ${ chalk . bold (
852
- 'Sentry CLI binary not found.' ,
853
- ) } 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`,
854
- ) ;
855
- showedMissingCLiBinaryErrorMsg = true ;
856
- }
857
- return false ;
858
- }
859
-
860
- /** User override */
861
-
862
854
if ( isServer && disableServerWebpackPlugin !== undefined ) {
863
855
return ! disableServerWebpackPlugin ;
864
856
} else if ( ! isServer && disableClientWebpackPlugin !== undefined ) {
@@ -1047,3 +1039,54 @@ function getRequestAsyncStorageModuleLocation(
1047
1039
1048
1040
return undefined ;
1049
1041
}
1042
+
1043
+ let downloadingCliAttempted = false ;
1044
+
1045
+ class SentryCliDownloadPlugin implements WebpackPluginInstance {
1046
+ public apply ( compiler : Compiler ) : void {
1047
+ compiler . hooks . beforeRun . tapAsync ( 'SentryCliDownloadPlugin' , ( compiler , callback ) => {
1048
+ const SentryWebpackPlugin = loadModule < SentryCliPlugin > ( '@sentry/webpack-plugin' ) ;
1049
+ if ( ! SentryWebpackPlugin ) {
1050
+ // Pretty much an invariant.
1051
+ return callback ( ) ;
1052
+ }
1053
+
1054
+ // @ts -expect-error - this exists, the dynamic import just doesn't know it
1055
+ if ( SentryWebpackPlugin . cliBinaryExists ( ) ) {
1056
+ return callback ( ) ;
1057
+ }
1058
+
1059
+ if ( ! downloadingCliAttempted ) {
1060
+ downloadingCliAttempted = true ;
1061
+ // eslint-disable-next-line no-console
1062
+ console . log (
1063
+ `\n${ chalk . cyan ( 'info' ) } - ${ chalk . bold (
1064
+ 'Sentry binary to upload source maps not found.' ,
1065
+ ) } Package manager post-install scripts are likely disabled or there is a caching issue. Manually downloading instead...`,
1066
+ ) ;
1067
+
1068
+ // @ts -expect-error - this exists, the dynamic import just doesn't know it
1069
+ const cliDownloadPromise : Promise < void > = SentryWebpackPlugin . downloadCliBinary ( {
1070
+ log : ( ) => {
1071
+ // No logs from directly from CLI
1072
+ } ,
1073
+ } ) ;
1074
+
1075
+ cliDownloadPromise . then (
1076
+ ( ) => {
1077
+ // eslint-disable-next-line no-console
1078
+ console . log ( `${ chalk . cyan ( 'info' ) } - Sentry binary was successfully downloaded.\n` ) ;
1079
+ return callback ( ) ;
1080
+ } ,
1081
+ e => {
1082
+ // eslint-disable-next-line no-console
1083
+ console . error ( `${ chalk . red ( 'error' ) } - Sentry binary download failed:` , e ) ;
1084
+ return callback ( ) ;
1085
+ } ,
1086
+ ) ;
1087
+ } else {
1088
+ return callback ( ) ;
1089
+ }
1090
+ } ) ;
1091
+ }
1092
+ }
0 commit comments