@@ -564,6 +564,15 @@ export function createSentryBuildPluginManager(
564564        return ; 
565565      } 
566566
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+ 
567576      await  startSpan ( 
568577        // This is `forceTransaction`ed because this span is used in dashboards in the form of indexed transactions. 
569578        {  name : "debug-id-sourcemap-upload" ,  scope : sentryScope ,  forceTransaction : true  } , 
@@ -578,65 +587,77 @@ export function createSentryBuildPluginManager(
578587          const  freeUploadDependencyOnBuildArtifacts  =  createDependencyOnBuildArtifacts ( ) ; 
579588
580589          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 [ ] ; 
592593
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+               } 
603605
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 : false , 
618+                       dist : options . release . dist , 
619+                     } , 
620+                   ] , 
621+                   ignore : ignorePaths , 
622+                   live : "rejectOnError" , 
623+                 } ) ; 
624+               } ) ; 
609625
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+               } 
613638
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+                   } ) 
621647              ) ; 
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-                 } ) ; 
638648
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+                 ) ; 
640661              }  else  { 
641662                const  tmpUploadFolder  =  await  startSpan ( 
642663                  {  name : "mkdtemp" ,  scope : sentryScope  } , 
0 commit comments