2323 lookup_latest_component ,
2424)
2525from macaron .errors import GenerateBuildSpecError , QueryMacaronDatabaseError
26+ from macaron .json_tools import json_extract
2627from macaron .slsa_analyzer .checks .build_tool_check import BuildToolFacts
2728
2829logger : logging .Logger = logging .getLogger (__name__ )
@@ -122,7 +123,7 @@ def compose_shell_commands(cmds_sequence: list[list[str]]) -> str:
122123
123124def get_macaron_build_tools (
124125 build_tool_facts : Sequence [BuildToolFacts ], target_language : str
125- ) -> dict [str , dict [str , str | None ]] | None :
126+ ) -> dict [str , dict [str , float | str | None ]] | None :
126127 """
127128 Retrieve the Macaron build tool names for supported projects from the database facts.
128129
@@ -142,21 +143,26 @@ def get_macaron_build_tools(
142143 The corresponding Macaron build tool name, config_path, confidence score, optional build tool version,
143144 and optional root config path if present.
144145 """
145- build_tools = {}
146+ build_tools : dict [ str , dict [ str , float | str | None ]] = {}
146147 for fact in build_tool_facts :
147148 if fact .language .lower () == target_language :
148149 try :
149150 tool_name = MacaronBuildToolName (fact .build_tool_name ).value
150- build_tool_info = {
151+ current_confidence : float = float (fact .confidence )
152+ build_tool_info : dict [str , float | str | None ] = {
151153 "build_config_path" : fact .build_config_path ,
152- "confidence_score" : fact . confidence ,
154+ "confidence_score" : current_confidence ,
153155 "build_tool_version" : fact .build_tool_version ,
154156 "root_build_config_path" : fact .root_build_config_path ,
155157 }
156158 existing_build_tool_info = build_tools .get (tool_name )
159+ existing_confidence = (
160+ existing_build_tool_info .get ("confidence_score" ) if existing_build_tool_info is not None else None
161+ )
157162 if (
158163 existing_build_tool_info is None
159- or build_tool_info ["confidence_score" ] > existing_build_tool_info ["confidence_score" ]
164+ or not isinstance (existing_confidence , float )
165+ or current_confidence > existing_confidence
160166 ):
161167 build_tools [tool_name ] = build_tool_info
162168 except ValueError :
@@ -166,7 +172,7 @@ def get_macaron_build_tools(
166172
167173def get_build_tools (
168174 component_id : int , session : sqlalchemy .orm .Session , target_language : str
169- ) -> dict [str , dict [str , float , str | None ]] | None :
175+ ) -> dict [str , dict [str , float | str | None ]] | None :
170176 """Retrieve the Macaron build tool names for a given component.
171177
172178 Queries the database for build tool facts associated with the specified component ID.
@@ -295,6 +301,36 @@ def get_language_version(
295301 return None
296302
297303
304+ def _build_spec_build_command (
305+ build_tools : dict [str , dict [str , float | str | None ]],
306+ build_tool_name : str ,
307+ command : list [str ],
308+ ) -> SpecBuildCommandDict | None :
309+ """Build a single SpecBuildCommandDict entry for a given build tool."""
310+ build_config_path = json_extract (build_tools , [build_tool_name , "build_config_path" ], str )
311+ # build_config_path is a required field.
312+ if build_config_path is None :
313+ return None
314+
315+ root_build_config_path = json_extract (build_tools , [build_tool_name , "root_build_config_path" ], str )
316+ build_tool_version = json_extract (build_tools , [build_tool_name , "build_tool_version" ], str )
317+ confidence_score = json_extract (build_tools , [build_tool_name , "confidence_score" ], float )
318+ if confidence_score is None :
319+ return None
320+
321+ build_spec = SpecBuildCommandDict (
322+ build_tool = build_tool_name ,
323+ command = command ,
324+ build_config_path = build_config_path ,
325+ confidence_score = confidence_score ,
326+ )
327+ if root_build_config_path is not None :
328+ build_spec ["root_build_config_path" ] = root_build_config_path
329+ if build_tool_version is not None :
330+ build_spec ["build_tool_version" ] = build_tool_version
331+ return build_spec
332+
333+
298334def gen_generic_build_spec (
299335 purl : PackageURL ,
300336 session : sqlalchemy .orm .Session ,
@@ -384,30 +420,24 @@ def gen_generic_build_spec(
384420 db_build_command_info or "Cannot find any." ,
385421 )
386422 lang_version = get_language_version (db_build_command_info ) if db_build_command_info else ""
387- spec_build_commad_info_list .append (
388- SpecBuildCommandDict (
389- build_tool = db_build_command_info .build_tool_name ,
390- command = db_build_command_info .command ,
391- build_config_path = build_tools [db_build_command_info .build_tool_name ]["build_config_path" ],
392- root_build_config_path = build_tools [db_build_command_info .build_tool_name ]["root_build_config_path" ],
393- build_config_version = build_tools [db_build_command_info .build_tool_name ]["build_tool_version" ],
394- confidence_score = build_tools [db_build_command_info .build_tool_name ]["confidence_score" ],
395- )
423+ build_spec_command = _build_spec_build_command (
424+ build_tools = build_tools ,
425+ build_tool_name = db_build_command_info .build_tool_name ,
426+ command = db_build_command_info .command ,
396427 )
428+ if build_spec_command is not None :
429+ spec_build_commad_info_list .append (build_spec_command )
397430
398431 # If no build commands were found from the analyze phase, add default commands for the identified build tools.
399432 if not db_build_command_info_list :
400433 for build_tool_name in build_tool_names :
401- spec_build_commad_info_list .append (
402- SpecBuildCommandDict (
403- build_tool = build_tool_name ,
404- command = [],
405- build_config_path = build_tools [build_tool_name ]["build_config_path" ],
406- root_build_config_path = build_tools [build_tool_name ]["root_build_config_path" ],
407- build_config_version = build_tools [build_tool_name ]["build_tool_version" ],
408- confidence_score = build_tools [build_tool_name ]["confidence_score" ],
409- )
434+ build_spec_command = _build_spec_build_command (
435+ build_tools = build_tools ,
436+ build_tool_name = build_tool_name ,
437+ command = [],
410438 )
439+ if build_spec_command is not None :
440+ spec_build_commad_info_list .append (build_spec_command )
411441
412442 base_build_spec_dict = BaseBuildSpecDict (
413443 {
0 commit comments