@@ -230,16 +230,34 @@ def is_project_updated(self, dt_project: Dict[str, Any]) -> bool:
230
230
if not dt_project :
231
231
self .print_stderr ('Warning: No project details supplied. Returning False.' )
232
232
return False
233
- last_import = dt_project .get ('lastBomImport' , 0 )
234
- last_vulnerability_analysis = dt_project .get ('lastVulnerabilityAnalysis' , 0 )
233
+
234
+ # Safely extract and normalise timestamp values to numeric types
235
+ def _safe_timestamp (field , value = None , default = 0 ) -> float :
236
+ """Convert timestamp value to float, handling string/numeric types safely."""
237
+ if value is None :
238
+ return float (default )
239
+ try :
240
+ return float (value )
241
+ except (ValueError , TypeError ):
242
+ self .print_stderr (f'Warning: Invalid timestamp for { field } , value: { value } , using default: { default } ' )
243
+ return float (default )
244
+
245
+ last_import = _safe_timestamp ('lastBomImport' , dt_project .get ('lastBomImport' ), 0 )
246
+ last_vulnerability_analysis = _safe_timestamp ('lastVulnerabilityAnalysis' ,
247
+ dt_project .get ('lastVulnerabilityAnalysis' ), 0
248
+ )
235
249
metrics = dt_project .get ('metrics' , {})
236
- last_occurrence = metrics .get ('lastOccurrence' , 0 ) if isinstance (metrics , dict ) else 0
250
+ last_occurrence = _safe_timestamp ('lastOccurrence' ,
251
+ metrics .get ('lastOccurrence' , 0 )
252
+ if isinstance (metrics , dict ) else 0 , 0
253
+ )
237
254
if self .debug :
238
255
self .print_msg (f'last_import: { last_import } ' )
239
256
self .print_msg (f'last_vulnerability_analysis: { last_vulnerability_analysis } ' )
240
257
self .print_msg (f'last_occurrence: { last_occurrence } ' )
241
258
self .print_msg (f'last_vulnerability_analysis is updated: { last_vulnerability_analysis >= last_import } ' )
242
259
self .print_msg (f'last_occurrence is updated: { last_occurrence >= last_import } ' )
260
+ # If all timestamps are zero, this indicates no processing has occurred
243
261
if last_vulnerability_analysis == 0 or last_occurrence == 0 or last_import == 0 :
244
262
self .print_stderr (f'Warning: Some project data appears to be unset. Returning False: { dt_project } ' )
245
263
return False
@@ -434,12 +452,16 @@ def run(self) -> int:
434
452
return PolicyStatus .ERROR .value
435
453
# Get project violations from Dependency Track
436
454
dt_project_violations = self .dep_track_service .get_project_violations (self .project_id )
455
+ # Handle case where service returns None (API error) vs empty list (no violations)
456
+ if dt_project_violations is None :
457
+ self .print_stderr ('Error: Failed to retrieve project violations from Dependency Track' )
458
+ return PolicyStatus .ERROR .value
437
459
# Sort violations by priority and format output
438
460
formatter = self ._get_formatter ()
439
461
if formatter is None :
440
462
self .print_stderr ('Error: Invalid format specified.' )
441
463
return PolicyStatus .ERROR .value
442
- # Format and output data
464
+ # Format and output data - handle empty results gracefully
443
465
data = formatter (self ._sort_project_violations (dt_project_violations ))
444
466
self .print_to_file_or_stdout (data ['details' ], self .output )
445
467
self .print_to_file_or_stderr (data ['summary' ], self .status )
0 commit comments