@@ -564,6 +564,15 @@ export function createSentryBuildPluginManager(
564
564
return ;
565
565
}
566
566
567
+ // Early exit if assets is explicitly set to an empty array
568
+ const assets = options . sourcemaps ?. assets ;
569
+ if ( Array . isArray ( assets ) && assets . length === 0 ) {
570
+ logger . debug (
571
+ "Empty `sourcemaps.assets` option provided. Will not upload sourcemaps with debug ID."
572
+ ) ;
573
+ return ;
574
+ }
575
+
567
576
await startSpan (
568
577
// This is `forceTransaction`ed because this span is used in dashboards in the form of indexed transactions.
569
578
{ name : "debug-id-sourcemap-upload" , scope : sentryScope , forceTransaction : true } ,
@@ -578,65 +587,77 @@ export function createSentryBuildPluginManager(
578
587
const freeUploadDependencyOnBuildArtifacts = createDependencyOnBuildArtifacts ( ) ;
579
588
580
589
try {
581
- const assets = options . sourcemaps ?. assets ;
582
-
583
- let globAssets : string | string [ ] ;
584
- if ( assets ) {
585
- globAssets = assets ;
586
- } else {
587
- logger . debug (
588
- "No `sourcemaps.assets` option provided, falling back to uploading detected build artifacts."
589
- ) ;
590
- globAssets = buildArtifactPaths ;
591
- }
590
+ if ( ! shouldPrepare ) {
591
+ // Direct CLI upload from existing artifact paths (no globbing, no preparation)
592
+ let pathsToUpload : string [ ] ;
592
593
593
- const globResult = await startSpan (
594
- { name : "glob" , scope : sentryScope } ,
595
- async ( ) =>
596
- await glob ( globAssets , {
597
- absolute : true ,
598
- // If we do not use a temp folder, we allow directories and files; CLI will traverse as needed when given paths.
599
- nodir : shouldPrepare ,
600
- ignore : options . sourcemaps ?. ignore ,
601
- } )
602
- ) ;
594
+ if ( assets ) {
595
+ pathsToUpload = Array . isArray ( assets ) ? assets : [ assets ] ;
596
+ logger . debug (
597
+ `Direct upload mode: passing user-provided assets directly to CLI: ${ pathsToUpload . join (
598
+ ", "
599
+ ) } `
600
+ ) ;
601
+ } else {
602
+ // Use original paths e.g. like ['.next/server'] directly –> preferred way when no globbing is done
603
+ pathsToUpload = buildArtifactPaths ;
604
+ }
603
605
604
- const debugIdChunkFilePaths = shouldPrepare
605
- ? globResult . filter ( ( debugIdChunkFilePath ) => {
606
- return ! ! stripQueryAndHashFromPath ( debugIdChunkFilePath ) . match ( / \. ( j s | m j s | c j s ) $ / ) ;
607
- } )
608
- : globResult ;
606
+ const ignorePaths = options . sourcemaps ?. ignore
607
+ ? Array . isArray ( options . sourcemaps ?. ignore )
608
+ ? options . sourcemaps ?. ignore
609
+ : [ options . sourcemaps ?. ignore ]
610
+ : [ ] ;
611
+ await startSpan ( { name : "upload" , scope : sentryScope } , async ( ) => {
612
+ const cliInstance = createCliInstance ( options ) ;
613
+ await cliInstance . releases . uploadSourceMaps ( options . release . name ?? "undefined" , {
614
+ include : [
615
+ {
616
+ paths : pathsToUpload ,
617
+ rewrite : true ,
618
+ dist : options . release . dist ,
619
+ } ,
620
+ ] ,
621
+ ignore : ignorePaths ,
622
+ live : "rejectOnError" ,
623
+ } ) ;
624
+ } ) ;
609
625
610
- // The order of the files output by glob() is not deterministic
611
- // Ensure order within the files so that {debug-id}-{chunkIndex} coupling is consistent
612
- debugIdChunkFilePaths . sort ( ) ;
626
+ logger . info ( "Successfully uploaded source maps to Sentry" ) ;
627
+ } else {
628
+ // Prepare artifacts in temp folder before uploading
629
+ let globAssets : string | string [ ] ;
630
+ if ( assets ) {
631
+ globAssets = assets ;
632
+ } else {
633
+ logger . debug (
634
+ "No `sourcemaps.assets` option provided, falling back to uploading detected build artifacts."
635
+ ) ;
636
+ globAssets = buildArtifactPaths ;
637
+ }
613
638
614
- if ( Array . isArray ( assets ) && assets . length === 0 ) {
615
- logger . debug (
616
- "Empty `sourcemaps.assets` option provided. Will not upload sourcemaps with debug ID."
617
- ) ;
618
- } else if ( debugIdChunkFilePaths . length === 0 ) {
619
- logger . warn (
620
- "Didn't find any matching sources for debug ID upload. Please check the `sourcemaps.assets` option."
639
+ const globResult = await startSpan (
640
+ { name : "glob" , scope : sentryScope } ,
641
+ async ( ) =>
642
+ await glob ( globAssets , {
643
+ absolute : true ,
644
+ nodir : true , // We need individual files for preparation
645
+ ignore : options . sourcemaps ?. ignore ,
646
+ } )
621
647
) ;
622
- } else {
623
- if ( ! shouldPrepare ) {
624
- // Direct CLI upload from existing artifact paths (no preparation or temp copies)
625
- await startSpan ( { name : "upload" , scope : sentryScope } , async ( ) => {
626
- const cliInstance = createCliInstance ( options ) ;
627
- await cliInstance . releases . uploadSourceMaps ( options . release . name ?? "undefined" , {
628
- include : [
629
- {
630
- paths : debugIdChunkFilePaths ,
631
- rewrite : false ,
632
- dist : options . release . dist ,
633
- } ,
634
- ] ,
635
- live : "rejectOnError" ,
636
- } ) ;
637
- } ) ;
638
648
639
- logger . info ( "Successfully uploaded source maps to Sentry" ) ;
649
+ const debugIdChunkFilePaths = globResult . filter ( ( debugIdChunkFilePath ) => {
650
+ return ! ! stripQueryAndHashFromPath ( debugIdChunkFilePath ) . match ( / \. ( j s | m j s | c j s ) $ / ) ;
651
+ } ) ;
652
+
653
+ // The order of the files output by glob() is not deterministic
654
+ // Ensure order within the files so that {debug-id}-{chunkIndex} coupling is consistent
655
+ debugIdChunkFilePaths . sort ( ) ;
656
+
657
+ if ( debugIdChunkFilePaths . length === 0 ) {
658
+ logger . warn (
659
+ "Didn't find any matching sources for debug ID upload. Please check the `sourcemaps.assets` option."
660
+ ) ;
640
661
} else {
641
662
const tmpUploadFolder = await startSpan (
642
663
{ name : "mkdtemp" , scope : sentryScope } ,
0 commit comments