@@ -86,7 +86,7 @@ def get_instructions() -> str:
8686 return """
8787 You are an expert on backporting upstream patches to packages in RHEL ecosystem.
8888
89- To backport upstream fix <UPSTREAM_FIX > to package <PACKAGE> in dist-git branch <DIST_GIT_BRANCH>, do the following:
89+ To backport upstream patches <UPSTREAM_PATCHES > to package <PACKAGE> in dist-git branch <DIST_GIT_BRANCH>, do the following:
9090
9191 CRITICAL: Do NOT modify, delete, or touch any existing patches in the dist-git repository.
9292 Only add new patches for the current backport. Existing patches are there for a reason
@@ -97,7 +97,7 @@ def get_instructions() -> str:
9797 end the process with `success=True` and `status="Backport already applied"`.
9898
9999 2. Use the `git_prepare_package_sources` tool to prepare package sources in directory <UNPACKED_SOURCES>
100- for application of the upstream fix .
100+ for application of the upstream patch .
101101
102102 3. Determine which backport approach to use:
103103
@@ -108,7 +108,7 @@ def get_instructions() -> str:
108108 - <UPSTREAM_REPO>: A temporary upstream repository clone (created in step 3c with -upstream suffix)
109109
110110 When to use this workflow:
111- - <UPSTREAM_FIX > is a commit or pull request URL
111+ - <UPSTREAM_PATCHES > is a list of commit or pull request URLs
112112 - This includes URLs with .patch suffix (e.g., https://github.com/.../commit/abc123.patch)
113113 - If URL extraction fails, fall back to approach B
114114
@@ -218,7 +218,9 @@ def get_instructions() -> str:
218218
219219 B. GIT AM WORKFLOW (Fallback approach):
220220
221- Note: For this workflow, use the pre-downloaded patch file at {{local_clone}}/{{jira_issue}}.patch
221+ Note: For this workflow, use the pre-downloaded patch files at {{local_clone}}.
222+ Their name is {{jira_issue}}-N.patch where N is the index starting from 0.
223+ For example, the first patch is at {{local_clone}}/{{jira_issue}}-0.patch
222224
223225 3a. Backport the patch:
224226 - Use the `git_patch_apply` tool with the patch file: {{local_clone}}/{{jira_issue}}.patch
@@ -228,7 +230,7 @@ def get_instructions() -> str:
228230 3b. Once there are no more conflicts, use the `git_patch_create` tool with the patch file path
229231 {{local_clone}}/{{jira_issue}}.patch to update the patch file.
230232
231- 4. Update the spec file. Add a new `Patch` tag pointing to the <UPSTREAM_FIX> patch file .
233+ 4. Update the spec file. Add a new `Patch` tag for every patch in <UPSTREAM_PATCHES> .
232234 Add the new `Patch` tag after all existing `Patch` tags and, if `Patch` tags are numbered,
233235 make sure it has the highest number. Make sure the patch is applied in the "%prep" section
234236 and the `-p` argument is correct.
@@ -267,7 +269,7 @@ def get_prompt() -> str:
267269 {{dist_git_branch}} dist-git branch has been checked out. You are working on Jira issue {{jira_issue}}
268270 {{#cve_id}}(a.k.a. {{.}}){{/cve_id}}.
269271 {{^build_error}}
270- Backport upstream fix {{upstream_fix }}.
272+ Backport upstream patches {{upstream_patches }}.
271273 Unpacked upstream sources are in {{unpacked_sources}}.
272274 {{/build_error}}
273275 {{#build_error}}
@@ -287,7 +289,7 @@ def get_fix_build_error_prompt() -> str:
287289 {{dist_git_branch}} dist-git branch has been checked out. You are working on Jira issue {{jira_issue}}
288290 {{#cve_id}}(a.k.a. {{.}}){{/cve_id}}.
289291
290- The backport of {{upstream_fix }} was initially successful using the cherry-pick workflow,
292+ The backport of {{upstream_patches }} was initially successful using the cherry-pick workflow,
291293 but the build failed with the following error:
292294
293295 {{build_error}}
@@ -490,7 +492,7 @@ async def main() -> None:
490492 local_tool_options = {"working_directory" : None }
491493
492494 class State (PackageUpdateState ):
493- upstream_fix : str
495+ upstream_patches : list [ str ]
494496 cve_id : str | None
495497 unpacked_sources : Path | None = Field (default = None )
496498 backport_log : list [str ] = Field (default = [])
@@ -500,7 +502,7 @@ class State(PackageUpdateState):
500502 incremental_fix_attempts : int = Field (default = 0 ) # Track how many times we tried incremental fix
501503
502504 async def run_workflow (
503- package , dist_git_branch , upstream_fix , jira_issue , cve_id , redis_conn = None
505+ package , dist_git_branch , upstream_patches , jira_issue , cve_id , redis_conn = None
504506 ):
505507 local_tool_options ["working_directory" ] = None
506508
@@ -543,11 +545,14 @@ async def fork_and_prepare_dist_git(state):
543545 state .unpacked_sources = get_unpacked_sources (state .local_clone , state .package )
544546 timeout = aiohttp .ClientTimeout (total = 30 )
545547 async with aiohttp .ClientSession (timeout = timeout ) as session :
546- async with session .get (state .upstream_fix ) as response :
547- if response .status < 400 :
548- (state .local_clone / f"{ state .jira_issue } .patch" ).write_text (await response .text ())
549- else :
550- raise ValueError (f"Failed to fetch upstream fix: { response .status } " )
548+ for idx , upstream_patch in enumerate (state .upstream_patches ):
549+ # should we guess the patch name with log agent?
550+ patch_name = f"{ state .jira_issue } -{ idx } .patch"
551+ async with session .get (upstream_patch ) as response :
552+ if response .status < 400 :
553+ (state .local_clone / patch_name ).write_text (await response .text ())
554+ else :
555+ raise ValueError (f"Failed to fetch upstream patch: { response .status } " )
551556 return "run_backport_agent"
552557
553558 async def run_backport_agent (state ):
@@ -561,7 +566,7 @@ async def run_backport_agent(state):
561566 dist_git_branch = state .dist_git_branch ,
562567 jira_issue = state .jira_issue ,
563568 cve_id = state .cve_id ,
564- upstream_fix = state .upstream_fix ,
569+ upstream_patches = state .upstream_patches ,
565570 build_error = state .build_error ,
566571 ),
567572 ),
@@ -622,7 +627,7 @@ async def fix_build_error(state):
622627 dist_git_branch = state .dist_git_branch ,
623628 jira_issue = state .jira_issue ,
624629 cve_id = state .cve_id ,
625- upstream_fix = state .upstream_fix ,
630+ upstream_patches = state .upstream_patches ,
626631 build_error = state .build_error ,
627632 ),
628633 ),
@@ -772,21 +777,22 @@ async def run_log_agent(state):
772777 log_output = log_output ,
773778 operation_type = "backport" ,
774779 package = state .package ,
775- details = state .upstream_fix ,
780+ details = state .upstream_patches ,
776781 )
777782 state .log_result = log_output
778783
779784 return "stage_changes"
780785
781786 async def commit_push_and_open_mr (state ):
782787 try :
788+ formatted_patches = "\n " .join (f" - { p } " for p in state .upstream_patches )
783789 state .merge_request_url = await tasks .commit_push_and_open_mr (
784790 local_clone = state .local_clone ,
785791 commit_message = (
786792 f"{ state .log_result .title } \n \n "
787793 f"{ state .log_result .description } \n \n "
788794 + (f"CVE: { state .cve_id } \n " if state .cve_id else "" )
789- + f "Upstream fix: { state . upstream_fix } \n "
795+ + "Upstream patches: \n " + formatted_patches + " \n "
790796 + f"Resolves: { state .jira_issue } \n \n "
791797 f"This commit was backported { I_AM_JOTNAR } \n \n "
792798 "Assisted-by: Jotnar\n "
@@ -799,7 +805,7 @@ async def commit_push_and_open_mr(state):
799805 f"This merge request was created { I_AM_JOTNAR } \n "
800806 f"{ CAREFULLY_REVIEW_CHANGES } \n \n "
801807 f"{ state .log_result .description } \n \n "
802- f "Upstream patch: { state . upstream_fix } \n \n "
808+ + "Upstream patches: \n " + formatted_patches + " \n "
803809 f"Resolves: { state .jira_issue } \n \n "
804810 f"Backporting steps:\n \n { state .backport_log [- 1 ]} "
805811 ),
@@ -847,7 +853,7 @@ async def comment_in_jira(state):
847853 State (
848854 package = package ,
849855 dist_git_branch = dist_git_branch ,
850- upstream_fix = upstream_fix ,
856+ upstream_patches = upstream_patches ,
851857 jira_issue = jira_issue ,
852858 cve_id = cve_id ,
853859 ),
@@ -857,14 +863,15 @@ async def comment_in_jira(state):
857863 if (
858864 (package := os .getenv ("PACKAGE" , None ))
859865 and (branch := os .getenv ("BRANCH" , None ))
860- and (upstream_fix := os .getenv ("UPSTREAM_FIX " , None ))
866+ and (upstream_patches_raw := os .getenv ("UPSTREAM_PATCHES " , None ))
861867 and (jira_issue := os .getenv ("JIRA_ISSUE" , None ))
862868 ):
869+ upstream_patches = upstream_patches_raw .split ("," )
863870 logger .info ("Running in direct mode with environment variables" )
864871 state = await run_workflow (
865872 package = package ,
866873 dist_git_branch = branch ,
867- upstream_fix = upstream_fix ,
874+ upstream_patches = upstream_patches ,
868875 jira_issue = jira_issue ,
869876 cve_id = os .getenv ("CVE_ID" , None ),
870877 redis_conn = None ,
@@ -926,7 +933,7 @@ async def retry(task, error):
926933 state = await run_workflow (
927934 package = backport_data .package ,
928935 dist_git_branch = dist_git_branch ,
929- upstream_fix = backport_data .patch_url ,
936+ upstream_patches = backport_data .patch_urls ,
930937 jira_issue = backport_data .jira_issue ,
931938 cve_id = backport_data .cve_id ,
932939 redis_conn = redis ,
0 commit comments