2020 get_args ,
2121)
2222
23- from github_action_utils import debug , error , set_output , warning
23+ from github_action_utils import debug , notice , error , set_output , warning
2424from result import Err , Ok , Result
2525
2626System = Literal ["x86_64-linux" , "aarch64-linux" , "aarch64-darwin" ]
@@ -60,6 +60,13 @@ class GitHubActionPackage(TypedDict):
6060 postgresql_version : NotRequired [str ]
6161
6262
63+ class NixEvalError (TypedDict ):
64+ """Error information from nix evaluation."""
65+
66+ attr : str
67+ error : str
68+
69+
6370BUILD_RUNNER_MAP : Dict [RunnerType , Dict [System , RunsOnConfig ]] = {
6471 "ephemeral" : {
6572 "aarch64-linux" : {
@@ -107,24 +114,25 @@ def build_nix_eval_command(max_workers: int, flake_outputs: List[str]) -> List[s
107114
108115def parse_nix_eval_line (
109116 line : str , drv_paths : Set [str ]
110- ) -> Result [Optional [NixEvalJobsOutput ], str ]:
117+ ) -> Result [Optional [NixEvalJobsOutput ], NixEvalError ]:
111118 """Parse a single line of nix-eval-jobs output.
112119
113120 Returns:
114121 Ok(package_data) if successful (None for empty/duplicate lines)
115- Err(error_message ) if a nix evaluation error occurred
122+ Err(NixEvalError ) if a nix evaluation error occurred
116123 """
117124 if not line .strip ():
118125 return Ok (None )
119126
120127 try :
121128 data : NixEvalJobsOutput = json .loads (line )
122129 if "error" in data :
123- error_msg = (
124- f"Error in nix-eval-jobs output for { data ['attr' ]} : { data ['error' ]} "
125- )
126- error (error_msg , title = "Nix Evaluation Error" )
127- return Err (error_msg )
130+ error_msg = data ["error" ]
131+ # Strip the redundant first line if it contains "does not have valid outputs"
132+ error_lines = error_msg .split ("\n " )
133+ if len (error_lines ) > 1 and "does not have valid outputs" in error_lines [0 ]:
134+ error_msg = "\n " .join (error_lines [1 :]).strip ()
135+ return Err ({"attr" : data ["attr" ], "error" : error_msg })
128136 if data ["drvPath" ] in drv_paths :
129137 return Ok (None )
130138 drv_paths .add (data ["drvPath" ])
@@ -136,11 +144,11 @@ def parse_nix_eval_line(
136144
137145def run_nix_eval_jobs (
138146 cmd : List [str ],
139- ) -> Tuple [List [NixEvalJobsOutput ], List [str ], bool ]:
140- """Run nix-eval-jobs and return parsed package data, warnings, and error status .
147+ ) -> Tuple [List [NixEvalJobsOutput ], List [str ], List [ NixEvalError ] ]:
148+ """Run nix-eval-jobs and return parsed package data, warnings, and errors .
141149
142150 Returns:
143- Tuple of (packages, warnings_list, had_errors )
151+ Tuple of (packages, warnings_list, errors_list )
144152 """
145153 debug (f"Running command: { ' ' .join (cmd )} " )
146154
@@ -152,11 +160,11 @@ def run_nix_eval_jobs(
152160 # Parse stdout for packages
153161 packages : List [NixEvalJobsOutput ] = []
154162 drv_paths : Set [str ] = set ()
155- had_errors = False
163+ errors_list : List [ NixEvalError ] = []
156164 for line in stdout_data .splitlines ():
157165 result = parse_nix_eval_line (line , drv_paths )
158166 if result .is_err ():
159- had_errors = True
167+ errors_list . append ( result . err_value )
160168 elif result .ok_value is not None :
161169 packages .append (result .ok_value )
162170
@@ -174,7 +182,7 @@ def run_nix_eval_jobs(
174182 title = "Process Failure" ,
175183 )
176184
177- return packages , warnings_list , had_errors
185+ return packages , warnings_list , errors_list
178186
179187
180188def is_extension_pkg (pkg : NixEvalJobsOutput ) -> bool :
@@ -260,8 +268,8 @@ def main() -> None:
260268
261269 cmd = build_nix_eval_command (max_workers , args .flake_outputs )
262270
263- # Run evaluation and collect packages and warnings
264- packages , warnings_list , had_errors = run_nix_eval_jobs (cmd )
271+ # Run evaluation and collect packages, warnings, and errors
272+ packages , warnings_list , errors_list = run_nix_eval_jobs (cmd )
265273 gh_action_packages = sort_pkgs_by_closures (packages )
266274
267275 def clean_package_for_output (pkg : NixEvalJobsOutput ) -> GitHubActionPackage :
@@ -318,13 +326,31 @@ def clean_package_for_output(pkg: NixEvalJobsOutput) -> GitHubActionPackage:
318326 else :
319327 warning (warn_msg , title = "Nix Evaluation Warning" )
320328
321- # Output matrix to GitHub Actions
322- debug (f"Generated GitHub Actions matrix: { json .dumps (gh_output , indent = 2 )} " )
323- set_output ("matrix" , json .dumps (gh_output ))
329+ if errors_list :
330+ # Group errors by error message
331+ errors_by_message : Dict [str , List [str ]] = defaultdict (list )
332+ for err in errors_list :
333+ errors_by_message [err ["error" ]].append (err ["attr" ])
334+
335+ for error_msg , attrs in errors_by_message .items ():
336+ if len (attrs ) > 1 :
337+ error (
338+ f"{ error_msg } \n Affected attributes: { ', ' .join (attrs )} " ,
339+ title = "Nix Evaluation Error" ,
340+ )
341+ else :
342+ error (
343+ f"{ error_msg } \n Attribute: { attrs [0 ]} " ,
344+ title = "Nix Evaluation Error" ,
345+ )
324346
325347 # Exit with error code if any evaluation errors occurred
326- if had_errors :
348+ if errors_list :
327349 sys .exit (1 )
350+ else :
351+ # Output matrix to GitHub Actions
352+ notice (f"Generated GitHub Actions matrix: { json .dumps (gh_output , indent = 2 )} " )
353+ set_output ("matrix" , json .dumps (gh_output ))
328354
329355
330356if __name__ == "__main__" :
0 commit comments