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,11 @@ 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 )
538547
539548 async def run_workflow (
540- package , dist_git_branch , upstream_patches , jira_issue , cve_id , redis_conn = None
549+ package , dist_git_branch , upstream_patches , jira_issue , cve_id , redis_conn = None , reproducer_info = None
541550 ):
542551 local_tool_options ["working_directory" ] = None
543552
@@ -603,6 +612,7 @@ async def run_backport_agent(state):
603612 cve_id = state .cve_id ,
604613 upstream_patches = state .upstream_patches ,
605614 build_error = state .build_error ,
615+ reproducer_failed = state .reproducer_failed ,
606616 ),
607617 ),
608618 expected_output = BackportOutputSchema ,
@@ -663,6 +673,7 @@ async def fix_build_error(state):
663673 cve_id = state .cve_id ,
664674 upstream_patches = state .upstream_patches ,
665675 build_error = state .build_error ,
676+ reproducer_failed = state .reproducer_failed ,
666677 ),
667678 ),
668679 expected_output = BackportOutputSchema ,
@@ -736,10 +747,14 @@ async def run_build_agent(state):
736747 if build_result .success :
737748 # Build succeeded - reset incremental fix counter for potential future failures
738749 state .incremental_fix_attempts = 0
739- return "update_release"
750+ state .build_url = build_result .url
751+ if state .reproducer_info :
752+ return "run_reproducer"
753+ else :
754+ return "update_release"
740755 if build_result .is_timeout :
741756 logger .info (f"Build timed out for { state .jira_issue } , proceeding" )
742- return "update_release "
757+ return "run_testing_farm_test "
743758 state .attempts_remaining -= 1
744759 if state .attempts_remaining <= 0 :
745760 state .backport_result .success = False
@@ -878,6 +893,30 @@ async def create_merge_request_checklist(state):
878893 async def add_fusa_label (state ):
879894 return await PackageUpdateStep .add_fusa_label (state , "comment_in_jira" , dry_run = dry_run , gateway_tools = gateway_tools )
880895
896+ async def run_reproducer (state ):
897+ reproducer_result = await tasks .run_tool (
898+ "run_testing_farm_test" ,
899+ git_url = state .reproducer_info .git_url ,
900+ git_ref = state .reproducer_info .git_ref ,
901+ path_to_test = state .reproducer_info .test ,
902+ package = state .build_url ,
903+ compose = state .dist_git_branch .upper () + "Nightly" ,
904+ available_tools = gateway_tools ,
905+ )
906+ if reproducer_result :
907+ return "update_release"
908+ else :
909+ state .reproducer_failed = True
910+ state .attempts_remaining -= 1
911+ if state .attempts_remaining <= 0 :
912+ state .backport_result .success = False
913+ state .backport_result .error = (
914+ f"Unable to successfully run the reproducer in { max_build_attempts } attempts"
915+ )
916+ return "comment_in_jira"
917+ # Run the backport agent again to try to fix the reproducer error
918+ return "run_backport_agent"
919+
881920 async def comment_in_jira (state ):
882921 if dry_run :
883922 return Workflow .END
@@ -903,6 +942,7 @@ async def comment_in_jira(state):
903942 workflow .add_step ("run_backport_agent" , run_backport_agent )
904943 workflow .add_step ("fix_build_error" , fix_build_error )
905944 workflow .add_step ("run_build_agent" , run_build_agent )
945+ workflow .add_step ("run_reproducer" , run_reproducer )
906946 workflow .add_step ("update_release" , update_release )
907947 workflow .add_step ("stage_changes" , stage_changes )
908948 workflow .add_step ("run_log_agent" , run_log_agent )
@@ -919,6 +959,8 @@ async def comment_in_jira(state):
919959 upstream_patches = upstream_patches ,
920960 jira_issue = jira_issue ,
921961 cve_id = cve_id ,
962+ reproducer_info = reproducer_info ,
963+ reproducer_failed = False ,
922964 ),
923965 )
924966 return response .state
@@ -931,13 +973,24 @@ async def comment_in_jira(state):
931973 ):
932974 upstream_patches = upstream_patches_raw .split ("," )
933975 logger .info ("Running in direct mode with environment variables" )
976+ reproducer_info_repo_url = os .getenv ("REPRODUCER_INFO_REPO_URL" , None )
977+ reproducer_info_repo_ref = os .getenv ("REPRODUCER_INFO_REPO_REF" , None )
978+ reproducer_info_test = os .getenv ("REPRODUCER_INFO_TEST" , None )
979+ reproducer_info = None
980+ if reproducer_info_repo_url and reproducer_info_repo_ref and reproducer_info_test :
981+ reproducer_info = ReproducerInfo (
982+ git_url = reproducer_info_repo_url ,
983+ git_ref = reproducer_info_repo_ref ,
984+ test = reproducer_info_test ,
985+ )
934986 state = await run_workflow (
935987 package = package ,
936988 dist_git_branch = branch ,
937989 upstream_patches = upstream_patches ,
938990 jira_issue = jira_issue ,
939991 cve_id = os .getenv ("CVE_ID" , None ),
940992 redis_conn = None ,
993+ reproducer_info = reproducer_info ,
941994 )
942995 logger .info (f"Direct run completed: { state .backport_result .model_dump_json (indent = 4 )} " )
943996 return
@@ -967,7 +1020,7 @@ async def comment_in_jira(state):
9671020 logger .info (
9681021 f"Processing backport for package: { backport_data .package } , "
9691022 f"JIRA: { backport_data .jira_issue } , branch: { dist_git_branch } , "
970- f"attempt: { task .attempts + 1 } "
1023+ f"attempt: { task .attempts + 1 } , reproducer info: { backport_data . reproducer_info } "
9711024 )
9721025
9731026 async def retry (task , error ):
@@ -1000,6 +1053,7 @@ async def retry(task, error):
10001053 jira_issue = backport_data .jira_issue ,
10011054 cve_id = backport_data .cve_id ,
10021055 redis_conn = redis ,
1056+ reproducer_info = backport_data .reproducer_info ,
10031057 )
10041058 logger .info (
10051059 f"Backport processing completed for { backport_data .jira_issue } , " f"success: { state .backport_result .success } "
0 commit comments