33import  argparse 
44import  json 
55import  multiprocessing 
6+ import  os 
67import  shlex 
78import  subprocess 
89import  sys 
1617RED  =  "\033 [91m" 
1718RESET  =  "\033 [0m" 
1819
20+ def  is_github_actions () ->  bool :
21+     """Check if running in GitHub Actions environment.""" 
22+     return  os .getenv ("GITHUB_ACTIONS" ) ==  "true" 
23+ 
24+ def  github_error (message : str , title : str  =  "" ) ->  None :
25+     """Output GitHub Actions error annotation.""" 
26+     if  title :
27+         print (f"::error title={ title }  ::{ message }  " )
28+     else :
29+         print (f"::error::{ message }  " )
30+ 
31+ def  github_warning (message : str , title : str  =  "" ) ->  None :
32+     """Output GitHub Actions warning annotation.""" 
33+     if  title :
34+         print (f"::warning title={ title }  ::{ message }  " )
35+     else :
36+         print (f"::warning::{ message }  " )
37+ 
38+ def  format_nix_error (error_text : str ) ->  str :
39+     """Format nix evaluation error for better readability.""" 
40+     lines  =  error_text .strip ().split ('\n ' )
41+     # Try to extract the most relevant error line 
42+     for  line  in  lines :
43+         if  'error:'  in  line .lower ():
44+             return  line .strip ()
45+     # If no specific error line found, return first non-empty line 
46+     for  line  in  lines :
47+         if  line .strip ():
48+             return  line .strip ()
49+     return  error_text .strip ()
50+ 
1951def  parse_args () ->  argparse .Namespace :
2052    parser  =  argparse .ArgumentParser (description = "Run hardware tests" )
2153    parser .add_argument (
@@ -63,8 +95,19 @@ def run_eval_test(gcroot_dir: Path, jobs: int) -> list[str]:
6395            attr  =  data .get ("attr" )
6496            if  "error"  in  data :
6597                failed_profiles .append (attr )
98+                 error_msg  =  data ['error' ]
99+                 formatted_error  =  format_nix_error (error_msg )
100+                 
101+                 # Output for terminal 
66102                print (f"{ RED }  FAIL { attr }  :{ RESET }  " , file = sys .stderr )
67-                 print (f"{ RED } { data ['error' ]} { RESET }  " , file = sys .stderr )
103+                 print (f"{ RED } { error_msg } { RESET }  " , file = sys .stderr )
104+                 
105+                 # Output for GitHub Actions 
106+                 if  is_github_actions ():
107+                     github_error (
108+                         formatted_error ,
109+                         title = f"Hardware profile evaluation failed: { attr }  " 
110+                     )
68111            else :
69112                print (f"{ GREEN }  OK { attr } { RESET }  " )
70113    return  failed_profiles 
@@ -80,9 +123,18 @@ def main() -> None:
80123        failed_profiles  =  run_eval_test (gcroot_dir , args .jobs )
81124
82125    if  len (failed_profiles ) >  0 :
83-         print (f"\n { RED }  The following { len (failed_profiles )}   test(s) failed:{ RESET }  " )
126+         failure_msg  =  f"The following { len (failed_profiles )}   test(s) failed:" 
127+         print (f"\n { RED } { failure_msg } { RESET }  " )
84128        for  profile  in  failed_profiles :
85129            print (f" '{ profile }  '" )
130+         
131+         # GitHub Actions summary 
132+         if  is_github_actions ():
133+             github_error (
134+                 f"{ failure_msg }   { ', ' .join (failed_profiles )}  " ,
135+                 title = "Hardware Profile Tests Failed" 
136+             )
137+         
86138        sys .exit (1 )
87139
88140
0 commit comments