@@ -2374,6 +2374,34 @@ def get_by_id(cls, id_: int) -> Optional["CoprBuildTargetModel"]:
23742374 with sa_session_transaction () as session :
23752375 return session .query (CoprBuildTargetModel ).filter_by (id = id_ ).first ()
23762376
2377+ @classmethod
2378+ def has_newer_run (cls , run : "CoprBuildTargetModel" ) -> bool :
2379+ """Check if a newer build exists for the same target+identifier
2380+ on the same project object (e.g. same PR).
2381+
2382+ Used to avoid overwriting a newer build's check status when
2383+ processing results for an older (e.g. canceled) build.
2384+ """
2385+ project_event = run .get_project_event_model ()
2386+ if not project_event or not run .submitted_time :
2387+ return False
2388+ with sa_session_transaction () as session :
2389+ return session .query (
2390+ session .query (CoprBuildTargetModel )
2391+ .join (CoprBuildGroupModel )
2392+ .join (PipelineModel )
2393+ .join (ProjectEventModel )
2394+ .filter (
2395+ ProjectEventModel .type == project_event .type ,
2396+ ProjectEventModel .event_id == project_event .event_id ,
2397+ CoprBuildTargetModel .identifier == run .identifier ,
2398+ CoprBuildTargetModel .target == run .target ,
2399+ CoprBuildTargetModel .submitted_time > run .submitted_time ,
2400+ CoprBuildTargetModel .id != run .id ,
2401+ )
2402+ .exists ()
2403+ ).scalar ()
2404+
23772405 @classmethod
23782406 def get_all (cls ) -> Iterable ["CoprBuildTargetModel" ]:
23792407 with sa_session_transaction () as session :
@@ -3014,6 +3042,33 @@ def get_by_id(cls, id_: int) -> Optional["KojiBuildTargetModel"]:
30143042 with sa_session_transaction () as session :
30153043 return session .query (KojiBuildTargetModel ).filter_by (id = id_ ).first ()
30163044
3045+ @classmethod
3046+ def has_newer_run (cls , run : "KojiBuildTargetModel" ) -> bool :
3047+ """Check if a newer build exists for the same target
3048+ on the same project object (e.g. same PR).
3049+
3050+ Used to avoid overwriting a newer build's check status when
3051+ processing results for an older (e.g. canceled) build.
3052+ """
3053+ project_event = run .get_project_event_model ()
3054+ if not project_event or not run .submitted_time :
3055+ return False
3056+ with sa_session_transaction () as session :
3057+ return session .query (
3058+ session .query (KojiBuildTargetModel )
3059+ .join (KojiBuildGroupModel )
3060+ .join (PipelineModel )
3061+ .join (ProjectEventModel )
3062+ .filter (
3063+ ProjectEventModel .type == project_event .type ,
3064+ ProjectEventModel .event_id == project_event .event_id ,
3065+ KojiBuildTargetModel .target == run .target ,
3066+ KojiBuildTargetModel .submitted_time > run .submitted_time ,
3067+ KojiBuildTargetModel .id != run .id ,
3068+ )
3069+ .exists ()
3070+ ).scalar ()
3071+
30173072 @classmethod
30183073 def get_all (cls ) -> Iterable ["KojiBuildTargetModel" ]:
30193074 with sa_session_transaction () as session :
@@ -3855,6 +3910,34 @@ def get_by_pipeline_id(cls, pipeline_id: str) -> Optional["TFTTestRunTargetModel
38553910 with sa_session_transaction () as session :
38563911 return session .query (TFTTestRunTargetModel ).filter_by (pipeline_id = pipeline_id ).first ()
38573912
3913+ @classmethod
3914+ def has_newer_run (cls , run : "TFTTestRunTargetModel" ) -> bool :
3915+ """Check if a newer test run exists for the same target+identifier
3916+ on the same project object (e.g. same PR).
3917+
3918+ Used to avoid overwriting a newer run's check status when
3919+ processing results for an older (e.g. canceled) run.
3920+ """
3921+ project_event = run .get_project_event_model ()
3922+ if not project_event or not run .submitted_time :
3923+ return False
3924+ with sa_session_transaction () as session :
3925+ return session .query (
3926+ session .query (TFTTestRunTargetModel )
3927+ .join (TFTTestRunGroupModel )
3928+ .join (PipelineModel )
3929+ .join (ProjectEventModel )
3930+ .filter (
3931+ ProjectEventModel .type == project_event .type ,
3932+ ProjectEventModel .event_id == project_event .event_id ,
3933+ TFTTestRunTargetModel .identifier == run .identifier ,
3934+ TFTTestRunTargetModel .target == run .target ,
3935+ TFTTestRunTargetModel .submitted_time > run .submitted_time ,
3936+ TFTTestRunTargetModel .id != run .id ,
3937+ )
3938+ .exists ()
3939+ ).scalar ()
3940+
38583941 @classmethod
38593942 def get_all_by_status (
38603943 cls ,
0 commit comments