@@ -517,3 +517,73 @@ def test_downstream_koji_build_cancel_uses_event_based_filtering(monkeypatch):
517517 job_config = job_config ,
518518 )
519519 assert first_dict_value (results ["job" ])["success" ]
520+
521+
522+ def test_downstream_koji_scratch_build_cancel_uses_event_based_filtering (
523+ mock_distgit_pr_functionality ,
524+ monkeypatch ,
525+ ):
526+ """Test that cancel_cutoff_time is set for Fedora CI scratch builds.
527+
528+ The Fedora CI code path (process_fedora_ci_jobs) used to skip setting
529+ cancel_cutoff_time because it didn't call create_tasks(). This test
530+ verifies the fix: process_fedora_ci_jobs now queries
531+ PipelineModel.get_latest_datetime_for_event and serializes the cutoff
532+ into the event dict, so the handler can cancel stale builds.
533+ """
534+ monkeypatch .setenv ("CANCEL_RUNNING_JOBS" , "1" )
535+
536+ cutoff_time = datetime (2025 , 1 , 15 , 10 , 30 , 0 , tzinfo = timezone .utc )
537+
538+ # Override the autouse fixture mock — return a specific cutoff time
539+ flexmock (PipelineModel ).should_receive ("get_latest_datetime_for_event" ).with_args (
540+ project_event_type = ProjectEventModelType .pull_request ,
541+ event_id = 9 ,
542+ ).and_return (cutoff_time ).once ()
543+
544+ # Mocks for the build execution flow inside _run()
545+ flexmock (PackitAPI ).should_receive ("init_kerberos_ticket" )
546+ koji_build_target = flexmock (
547+ id = 123 ,
548+ target = "main" ,
549+ status = "queued" ,
550+ set_status = lambda x : None ,
551+ set_task_id = lambda x : None ,
552+ set_web_url = lambda x : None ,
553+ set_build_logs_urls = lambda x : None ,
554+ set_data = lambda x : None ,
555+ set_build_submission_stdout = lambda x : None ,
556+ )
557+ flexmock (KojiBuildTargetModel ).should_receive ("create" ).and_return (koji_build_target )
558+ flexmock (KojiBuildGroupModel ).should_receive ("create" ).and_return (
559+ flexmock (grouped_targets = [koji_build_target ]),
560+ )
561+ flexmock (commands ).should_receive ("run_command_remote" ).and_return (
562+ flexmock (stdout = "some output" ),
563+ )
564+ flexmock (distgit_handlers ).should_receive ("get_koji_task_id_and_url_from_stdout" ).and_return (
565+ (123 , "koji-web-url" ),
566+ )
567+
568+ # The key assertion: get_running must be called with event-based parameters
569+ flexmock (KojiBuildGroupModel ).should_receive ("get_running" ).with_args (
570+ project_event_type = ProjectEventModelType .pull_request ,
571+ event_id = 9 ,
572+ created_before = cutoff_time ,
573+ targets = None ,
574+ ).and_return ([]).once ()
575+
576+ processing_results = SteveJobs ().process_message (mock_distgit_pr_functionality )
577+ event_dict , _ , job_config , package_config = get_parameters_from_results (
578+ processing_results [:1 ],
579+ )
580+
581+ # Verify that cancel_cutoff_time was serialized into the event dict
582+ assert event_dict .get ("cancel_cutoff_time" ) == cutoff_time .timestamp ()
583+
584+ results = run_downstream_koji_scratch_build_handler (
585+ package_config = package_config ,
586+ event = event_dict ,
587+ job_config = job_config ,
588+ )
589+ assert first_dict_value (results ["job" ])["success" ]
0 commit comments