3939
4040
4141class IDPPublisher :
42- def __init__ (self ):
42+ def __init__ (self , verbose = False ):
4343 self .console = Console ()
44+ self .verbose = verbose
4445 self .bucket_basename = None
4546 self .prefix = None
4647 self .region = None
4748 self .acl = None
4849 self .bucket = None
4950 self .prefix_and_version = None
5051 self .version = None
52+ self .build_errors = [] # Track build errors for verbose reporting
53+
54+ def log_verbose (self , message , style = "dim" ):
55+ """Log verbose messages if verbose mode is enabled"""
56+ if self .verbose :
57+ self .console .print (f"[{ style } ]{ message } [/{ style } ]" )
58+
59+ def log_error_details (self , component , error_output ):
60+ """Log detailed error information and store for summary"""
61+ error_info = {
62+ "component" : component ,
63+ "error" : error_output
64+ }
65+ self .build_errors .append (error_info )
66+
67+ if self .verbose :
68+ self .console .print (f"[red]❌ { component } build failed:[/red]" )
69+ self .console .print (f"[red]{ error_output } [/red]" )
70+ else :
71+ self .console .print (f"[red]❌ { component } build failed (use --verbose for details)[/red]" )
72+
73+ def print_error_summary (self ):
74+ """Print summary of all build errors"""
75+ if not self .build_errors :
76+ return
77+
78+ self .console .print ("\n [red]❌ Build Error Summary:[/red]" )
79+ for i , error_info in enumerate (self .build_errors , 1 ):
80+ self .console .print (f"\n [red]{ i } . { error_info ['component' ]} :[/red]" )
81+ if self .verbose :
82+ self .console .print (f"[red]{ error_info ['error' ]} [/red]" )
83+ else :
84+ # Show first few lines of error for non-verbose mode
85+ error_lines = error_info ['error' ].strip ().split ('\n ' )
86+ preview_lines = error_lines [:3 ] # Show first 3 lines
87+ for line in preview_lines :
88+ self .console .print (f"[red] { line } [/red]" )
89+ if len (error_lines ) > 3 :
90+ self .console .print (f"[dim] ... ({ len (error_lines ) - 3 } more lines, use --verbose for full output)[/dim]" )
5191 self .public_sample_udop_model = ""
5292 self .public = False
5393 self .main_template = "idp-main.yaml"
@@ -579,23 +619,29 @@ def build_and_package_template(self, directory):
579619 shutil .rmtree (cache_dir )
580620
581621 sam_build_start = time .time ()
622+ self .log_verbose (f"Running SAM build command: { ' ' .join (cmd )} " )
582623 result = subprocess .run (
583624 cmd , cwd = abs_directory , capture_output = True , text = True
584625 )
585626 sam_build_time = time .time () - sam_build_start
586627
587628 if result .returncode != 0 :
588629 # If cached build fails, try without cache
630+ self .log_verbose (f"Cached build failed for { directory } , retrying without cache" )
589631 self .console .print (
590632 f"[yellow]Cached build failed for { directory } , retrying without cache[/yellow]"
591633 )
592634 cmd_no_cache = [c for c in cmd if c != "--cached" ]
593635 sam_build_start = time .time ()
636+ self .log_verbose (f"Running SAM build command (no cache): { ' ' .join (cmd_no_cache )} " )
594637 result = subprocess .run (
595638 cmd_no_cache , cwd = abs_directory , capture_output = True , text = True
596639 )
597640 sam_build_time = time .time () - sam_build_start
598641 if result .returncode != 0 :
642+ # Log detailed error information
643+ error_output = f"STDOUT:\n { result .stdout } \n \n STDERR:\n { result .stderr } "
644+ self .log_error_details (f"SAM build for { directory } " , error_output )
599645 return False
600646
601647 # Package the template
@@ -620,12 +666,16 @@ def build_and_package_template(self, directory):
620666 ]
621667
622668 sam_package_start = time .time ()
669+ self .log_verbose (f"Running SAM package command: { ' ' .join (cmd )} " )
623670 result = subprocess .run (
624671 cmd , cwd = abs_directory , capture_output = True , text = True
625672 )
626673 sam_package_time = time .time () - sam_package_start
627674
628675 if result .returncode != 0 :
676+ # Log detailed error information
677+ error_output = f"STDOUT:\n { result .stdout } \n \n STDERR:\n { result .stderr } "
678+ self .log_error_details (f"SAM package for { directory } " , error_output )
629679 return False
630680
631681 # Log timing information
@@ -726,6 +776,11 @@ def build_patterns_concurrently(self, max_workers=None):
726776 progress .update (main_task , completed = completed )
727777
728778 except Exception as e :
779+ # Log detailed error information
780+ import traceback
781+ error_output = f"Exception: { str (e )} \n \n Traceback:\n { traceback .format_exc ()} "
782+ self .log_error_details (f"Pattern { pattern } build exception" , error_output )
783+
729784 progress .update (
730785 pattern_tasks [pattern ],
731786 description = f"[red]{ pattern } [/red] - Error: { str (e )[:30 ]} ..." ,
@@ -815,6 +870,11 @@ def build_options_concurrently(self, max_workers=None):
815870 progress .update (main_task , completed = completed )
816871
817872 except Exception as e :
873+ # Log detailed error information
874+ import traceback
875+ error_output = f"Exception: { str (e )} \n \n Traceback:\n { traceback .format_exc ()} "
876+ self .log_error_details (f"Option { option } build exception" , error_output )
877+
818878 progress .update (
819879 option_tasks [option ],
820880 description = f"[red]{ option } [/red] - Error: { str (e )[:30 ]} ..." ,
@@ -1020,8 +1080,11 @@ def build_main_template(self, webui_zipfile):
10201080 self .prefix_and_version ,
10211081 ]
10221082
1023- result = subprocess .run (cmd )
1083+ self .log_verbose (f"Running main template SAM package command: { ' ' .join (cmd )} " )
1084+ result = subprocess .run (cmd , capture_output = True , text = True )
10241085 if result .returncode != 0 :
1086+ error_output = f"STDOUT:\n { result .stdout } \n \n STDERR:\n { result .stderr } "
1087+ self .log_error_details ("Main template SAM package" , error_output )
10251088 self .console .print ("[red]Error packaging main template[/red]" )
10261089 sys .exit (1 )
10271090 finally :
@@ -1171,9 +1234,12 @@ def run(self, args):
11711234 patterns_time = time .time () - patterns_start
11721235
11731236 if not patterns_success :
1237+ self .print_error_summary ()
11741238 self .console .print (
11751239 "[red]❌ Error: Failed to build one or more patterns[/red]"
11761240 )
1241+ if not self .verbose :
1242+ self .console .print ("[dim]Use --verbose flag for detailed error information[/dim]" )
11771243 sys .exit (1 )
11781244
11791245 # Build options concurrently
@@ -1185,9 +1251,12 @@ def run(self, args):
11851251 options_time = time .time () - options_start
11861252
11871253 if not options_success :
1254+ self .print_error_summary ()
11881255 self .console .print (
11891256 "[red]❌ Error: Failed to build one or more options[/red]"
11901257 )
1258+ if not self .verbose :
1259+ self .console .print ("[dim]Use --verbose flag for detailed error information[/dim]" )
11911260 sys .exit (1 )
11921261
11931262 total_build_time = time .time () - start_time
@@ -1244,6 +1313,9 @@ def main(
12441313 "--max-workers" ,
12451314 help = "Maximum number of concurrent workers (default: auto-detect)" ,
12461315 ),
1316+ verbose : bool = typer .Option (
1317+ False , "--verbose" , "-v" , help = "Enable verbose output for debugging"
1318+ ),
12471319):
12481320 """
12491321 [bold cyan]GenAI IDP Publisher[/bold cyan]
@@ -1262,7 +1334,11 @@ def main(
12621334 if max_workers is not None :
12631335 args .extend (["--max-workers" , str (max_workers )])
12641336
1265- publisher = IDPPublisher ()
1337+ publisher = IDPPublisher (verbose = verbose )
1338+
1339+ if verbose :
1340+ console .print ("[dim]Verbose mode enabled - detailed error output will be shown[/dim]" )
1341+
12661342 publisher .run (args )
12671343
12681344 except KeyboardInterrupt :
0 commit comments