3939 Task ,
4040)
4141from common .utils import redis_client , fix_await
42+ from common .models import ReproducerInfo
4243from constants import I_AM_JOTNAR , CAREFULLY_REVIEW_CHANGES
4344from observability import setup_observability
4445from tools .commands import RunShellCommandTool
@@ -288,6 +289,12 @@ def get_prompt() -> str:
288289 Everything from the previous attempt has been reset. Start over, follow the instructions from the start
289290 and don't forget to fix the issue.
290291 {{/build_error}}
292+ {{#reproducer_failed}}
293+ The reproducer failed after the first backport attempt.
294+ Keep it in mind and try to fix the patches you apply to make the reproducer pass.
295+ You can inspect the reproducer test at {{tmt_reproducer.git_url}}/blob/{{tmt_reproducer.git_ref}}/{{tmt_reproducer.test}}.
296+ The test is located in the {{tmt_reproducer.git_ref}} branch of the {{tmt_reproducer.git_url}} repository.
297+ {{/reproducer_failed}}
291298 """
292299
293300
@@ -535,9 +542,12 @@ class State(PackageUpdateState):
535542 attempts_remaining : int = Field (default = max_build_attempts )
536543 used_cherry_pick_workflow : bool = Field (default = False ) # Track if cherry-pick was used
537544 incremental_fix_attempts : int = Field (default = 0 ) # Track how many times we tried incremental fix
545+ build_url : str | None = Field (default = None )
546+ reproducer_failed : bool = Field (default = False )
547+ reproducer_info : ReproducerInfo | None = Field (default = None )
538548
539549 async def run_workflow (
540- package , dist_git_branch , upstream_patches , jira_issue , cve_id , redis_conn = None
550+ package , dist_git_branch , upstream_patches , jira_issue , cve_id , redis_conn = None , reproducer_info = None
541551 ):
542552 local_tool_options ["working_directory" ] = None
543553
@@ -603,6 +613,7 @@ async def run_backport_agent(state):
603613 cve_id = state .cve_id ,
604614 upstream_patches = state .upstream_patches ,
605615 build_error = state .build_error ,
616+ reproducer_failed = state .reproducer_failed ,
606617 ),
607618 ),
608619 expected_output = BackportOutputSchema ,
@@ -663,6 +674,7 @@ async def fix_build_error(state):
663674 cve_id = state .cve_id ,
664675 upstream_patches = state .upstream_patches ,
665676 build_error = state .build_error ,
677+ reproducer_failed = state .reproducer_failed ,
666678 ),
667679 ),
668680 expected_output = BackportOutputSchema ,
@@ -736,10 +748,14 @@ async def run_build_agent(state):
736748 if build_result .success :
737749 # Build succeeded - reset incremental fix counter for potential future failures
738750 state .incremental_fix_attempts = 0
739- return "update_release"
751+ state .build_url = build_result .url
752+ if state .reproducer_info :
753+ return "run_reproducer"
754+ else :
755+ return "update_release"
740756 if build_result .is_timeout :
741757 logger .info (f"Build timed out for { state .jira_issue } , proceeding" )
742- return "update_release "
758+ return "run_testing_farm_test "
743759 state .attempts_remaining -= 1
744760 if state .attempts_remaining <= 0 :
745761 state .backport_result .success = False
@@ -878,6 +894,30 @@ async def create_merge_request_checklist(state):
878894 async def add_fusa_label (state ):
879895 return await PackageUpdateStep .add_fusa_label (state , "comment_in_jira" , dry_run = dry_run , gateway_tools = gateway_tools )
880896
897+ async def run_reproducer (state ):
898+ reproducer_result = await tasks .run_tool (
899+ "run_testing_farm_test" ,
900+ git_url = state .reproducer_info .git_url ,
901+ git_ref = state .reproducer_info .git_ref ,
902+ path_to_test = state .reproducer_info .test ,
903+ package = state .build_url ,
904+ compose = state .dist_git_branch .upper () + "Nightly" ,
905+ available_tools = gateway_tools ,
906+ )
907+ if reproducer_result :
908+ return "update_release"
909+ else :
910+ state .reproducer_failed = True
911+ state .attempts_remaining -= 1
912+ if state .attempts_remaining <= 0 :
913+ state .backport_result .success = False
914+ state .backport_result .error = (
915+ f"Unable to successfully run the reproducer in { max_build_attempts } attempts"
916+ )
917+ return "comment_in_jira"
918+ # Run the backport agent again to try to fix the reproducer error
919+ return "run_backport_agent"
920+
881921 async def comment_in_jira (state ):
882922 if dry_run :
883923 return Workflow .END
@@ -903,6 +943,7 @@ async def comment_in_jira(state):
903943 workflow .add_step ("run_backport_agent" , run_backport_agent )
904944 workflow .add_step ("fix_build_error" , fix_build_error )
905945 workflow .add_step ("run_build_agent" , run_build_agent )
946+ workflow .add_step ("run_reproducer" , run_reproducer )
906947 workflow .add_step ("update_release" , update_release )
907948 workflow .add_step ("stage_changes" , stage_changes )
908949 workflow .add_step ("run_log_agent" , run_log_agent )
@@ -919,6 +960,8 @@ async def comment_in_jira(state):
919960 upstream_patches = upstream_patches ,
920961 jira_issue = jira_issue ,
921962 cve_id = cve_id ,
963+ reproducer_info = reproducer_info ,
964+ reproducer_failed = False ,
922965 ),
923966 )
924967 return response .state
@@ -931,13 +974,24 @@ async def comment_in_jira(state):
931974 ):
932975 upstream_patches = upstream_patches_raw .split ("," )
933976 logger .info ("Running in direct mode with environment variables" )
977+ reproducer_info_repo_url = os .getenv ("REPRODUCER_INFO_REPO_URL" , None )
978+ reproducer_info_repo_ref = os .getenv ("REPRODUCER_INFO_REPO_REF" , None )
979+ reproducer_info_test = os .getenv ("REPRODUCER_INFO_TEST" , None )
980+ reproducer_info = None
981+ if reproducer_info_repo_url and reproducer_info_repo_ref and reproducer_info_test :
982+ reproducer_info = ReproducerInfo (
983+ git_url = reproducer_info_repo_url ,
984+ git_ref = reproducer_info_repo_ref ,
985+ test = reproducer_info_test ,
986+ )
934987 state = await run_workflow (
935988 package = package ,
936989 dist_git_branch = branch ,
937990 upstream_patches = upstream_patches ,
938991 jira_issue = jira_issue ,
939992 cve_id = os .getenv ("CVE_ID" , None ),
940993 redis_conn = None ,
994+ reproducer_info = reproducer_info ,
941995 )
942996 logger .info (f"Direct run completed: { state .backport_result .model_dump_json (indent = 4 )} " )
943997 return
@@ -967,7 +1021,7 @@ async def comment_in_jira(state):
9671021 logger .info (
9681022 f"Processing backport for package: { backport_data .package } , "
9691023 f"JIRA: { backport_data .jira_issue } , branch: { dist_git_branch } , "
970- f"attempt: { task .attempts + 1 } "
1024+ f"attempt: { task .attempts + 1 } , reproducer info: { backport_data . reproducer_info } "
9711025 )
9721026
9731027 async def retry (task , error ):
@@ -1000,6 +1054,7 @@ async def retry(task, error):
10001054 jira_issue = backport_data .jira_issue ,
10011055 cve_id = backport_data .cve_id ,
10021056 redis_conn = redis ,
1057+ reproducer_info = backport_data .reproducer_info ,
10031058 )
10041059 logger .info (
10051060 f"Backport processing completed for { backport_data .jira_issue } , " f"success: { state .backport_result .success } "
0 commit comments