@@ -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,22 +218,26 @@ 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 in the current working directory.
222+ They are called `<JIRA_ISSUE>-<N>.patch` where <N> is a 0-based index. For example,
223+ for a `RHEL-12345` Jira issue the first patch would be called `RHEL-12345-0.patch`.
222224
223- 3a. Backport the patch:
224- - Use the `git_patch_apply` tool with the patch file: {{local_clone}}/{{jira_issue}}.patch
225+ Backport all patches individually using the steps 3a and 3b below.
226+
227+ 3a. Backport one patch at a time using the following steps:
228+ - Use the `git_patch_apply` tool with the patch file: <JIRA_ISSUE>-<N>.patch
225229 - Resolve all conflicts and leave the repository in a dirty state. Delete all *.rej files.
226230 - Use the `git_apply_finish` tool to finish the patch application.
227231
228232 3b. Once there are no more conflicts, use the `git_patch_create` tool with the patch file path
229- {{local_clone}}/{{jira_issue}} .patch to update the patch file.
233+ <JIRA_ISSUE>-<N> .patch to update the patch file.
230234
231- 4. Update the spec file. Add a new `Patch` tag pointing to the <UPSTREAM_FIX> patch file .
235+ 4. Update the spec file. Add a new `Patch` tag for every patch in <UPSTREAM_PATCHES> .
232236 Add the new `Patch` tag after all existing `Patch` tags and, if `Patch` tags are numbered,
233237 make sure it has the highest number. Make sure the patch is applied in the "%prep" section
234238 and the `-p` argument is correct. Add an upstream URL as a comment above
235239 the `Patch:` tag - this URL references the related upstream commit or a pull/merge request.
236- Default to <UPSTREAM_FIX> if it is an URL .
240+ Include every patch defined in <UPSTREAM_PATCHES> list .
237241 IMPORTANT: Only ADD new patches. Do NOT modify existing Patch tags or their order.
238242
239243 5. Run `centpkg --name=<PACKAGE> --namespace=rpms --release=<DIST_GIT_BRANCH> prep` to see if the new patch
@@ -269,7 +273,10 @@ def get_prompt() -> str:
269273 {{dist_git_branch}} dist-git branch has been checked out. You are working on Jira issue {{jira_issue}}
270274 {{#cve_id}}(a.k.a. {{.}}){{/cve_id}}.
271275 {{^build_error}}
272- Backport upstream fix {{upstream_fix}}.
276+ Backport upstream patches:
277+ {{#upstream_patches}}
278+ - {{.}}
279+ {{/upstream_patches}}
273280 Unpacked upstream sources are in {{unpacked_sources}}.
274281 {{/build_error}}
275282 {{#build_error}}
@@ -289,7 +296,12 @@ def get_fix_build_error_prompt() -> str:
289296 {{dist_git_branch}} dist-git branch has been checked out. You are working on Jira issue {{jira_issue}}
290297 {{#cve_id}}(a.k.a. {{.}}){{/cve_id}}.
291298
292- The backport of {{upstream_fix}} was initially successful using the cherry-pick workflow,
299+ Upstream patches that were backported:
300+ {{#upstream_patches}}
301+ - {{.}}
302+ {{/upstream_patches}}
303+
304+ The backport of upstream patches was initially successful using the cherry-pick workflow,
293305 but the build failed with the following error:
294306
295307 {{build_error}}
@@ -492,7 +504,7 @@ async def main() -> None:
492504 local_tool_options = {"working_directory" : None }
493505
494506 class State (PackageUpdateState ):
495- upstream_fix : str
507+ upstream_patches : list [ str ]
496508 cve_id : str | None
497509 unpacked_sources : Path | None = Field (default = None )
498510 backport_log : list [str ] = Field (default = [])
@@ -502,7 +514,7 @@ class State(PackageUpdateState):
502514 incremental_fix_attempts : int = Field (default = 0 ) # Track how many times we tried incremental fix
503515
504516 async def run_workflow (
505- package , dist_git_branch , upstream_fix , jira_issue , cve_id , redis_conn = None
517+ package , dist_git_branch , upstream_patches , jira_issue , cve_id , redis_conn = None
506518 ):
507519 local_tool_options ["working_directory" ] = None
508520
@@ -545,11 +557,14 @@ async def fork_and_prepare_dist_git(state):
545557 state .unpacked_sources = get_unpacked_sources (state .local_clone , state .package )
546558 timeout = aiohttp .ClientTimeout (total = 30 )
547559 async with aiohttp .ClientSession (timeout = timeout ) as session :
548- async with session .get (state .upstream_fix ) as response :
549- if response .status < 400 :
550- (state .local_clone / f"{ state .jira_issue } .patch" ).write_text (await response .text ())
551- else :
552- raise ValueError (f"Failed to fetch upstream fix: { response .status } " )
560+ for idx , upstream_patch in enumerate (state .upstream_patches ):
561+ # should we guess the patch name with log agent?
562+ patch_name = f"{ state .jira_issue } -{ idx } .patch"
563+ async with session .get (upstream_patch ) as response :
564+ if response .status < 400 :
565+ (state .local_clone / patch_name ).write_text (await response .text ())
566+ else :
567+ raise ValueError (f"Failed to fetch upstream patch: { response .status } " )
553568 return "run_backport_agent"
554569
555570 async def run_backport_agent (state ):
@@ -563,7 +578,7 @@ async def run_backport_agent(state):
563578 dist_git_branch = state .dist_git_branch ,
564579 jira_issue = state .jira_issue ,
565580 cve_id = state .cve_id ,
566- upstream_fix = state .upstream_fix ,
581+ upstream_patches = state .upstream_patches ,
567582 build_error = state .build_error ,
568583 ),
569584 ),
@@ -624,7 +639,7 @@ async def fix_build_error(state):
624639 dist_git_branch = state .dist_git_branch ,
625640 jira_issue = state .jira_issue ,
626641 cve_id = state .cve_id ,
627- upstream_fix = state .upstream_fix ,
642+ upstream_patches = state .upstream_patches ,
628643 build_error = state .build_error ,
629644 ),
630645 ),
@@ -774,21 +789,22 @@ async def run_log_agent(state):
774789 log_output = log_output ,
775790 operation_type = "backport" ,
776791 package = state .package ,
777- details = state .upstream_fix ,
792+ details = str ( state .upstream_patches ) ,
778793 )
779794 state .log_result = log_output
780795
781796 return "stage_changes"
782797
783798 async def commit_push_and_open_mr (state ):
784799 try :
800+ formatted_patches = "\n " .join (f" - { p } " for p in state .upstream_patches )
785801 state .merge_request_url = await tasks .commit_push_and_open_mr (
786802 local_clone = state .local_clone ,
787803 commit_message = (
788804 f"{ state .log_result .title } \n \n "
789805 f"{ state .log_result .description } \n \n "
790806 + (f"CVE: { state .cve_id } \n " if state .cve_id else "" )
791- + f "Upstream fix: { state . upstream_fix } \n "
807+ + "Upstream patches: \n " + formatted_patches + " \n "
792808 + f"Resolves: { state .jira_issue } \n \n "
793809 f"This commit was backported { I_AM_JOTNAR } \n \n "
794810 "Assisted-by: Jotnar\n "
@@ -801,7 +817,7 @@ async def commit_push_and_open_mr(state):
801817 f"This merge request was created { I_AM_JOTNAR } \n "
802818 f"{ CAREFULLY_REVIEW_CHANGES } \n \n "
803819 f"{ state .log_result .description } \n \n "
804- f "Upstream patch: { state . upstream_fix } \n \n "
820+ + "Upstream patches: \n " + formatted_patches + " \n "
805821 f"Resolves: { state .jira_issue } \n \n "
806822 f"Backporting steps:\n \n { state .backport_log [- 1 ]} "
807823 ),
@@ -849,7 +865,7 @@ async def comment_in_jira(state):
849865 State (
850866 package = package ,
851867 dist_git_branch = dist_git_branch ,
852- upstream_fix = upstream_fix ,
868+ upstream_patches = upstream_patches ,
853869 jira_issue = jira_issue ,
854870 cve_id = cve_id ,
855871 ),
@@ -859,14 +875,15 @@ async def comment_in_jira(state):
859875 if (
860876 (package := os .getenv ("PACKAGE" , None ))
861877 and (branch := os .getenv ("BRANCH" , None ))
862- and (upstream_fix := os .getenv ("UPSTREAM_FIX " , None ))
878+ and (upstream_patches_raw := os .getenv ("UPSTREAM_PATCHES " , None ))
863879 and (jira_issue := os .getenv ("JIRA_ISSUE" , None ))
864880 ):
881+ upstream_patches = upstream_patches_raw .split ("," )
865882 logger .info ("Running in direct mode with environment variables" )
866883 state = await run_workflow (
867884 package = package ,
868885 dist_git_branch = branch ,
869- upstream_fix = upstream_fix ,
886+ upstream_patches = upstream_patches ,
870887 jira_issue = jira_issue ,
871888 cve_id = os .getenv ("CVE_ID" , None ),
872889 redis_conn = None ,
@@ -928,7 +945,7 @@ async def retry(task, error):
928945 state = await run_workflow (
929946 package = backport_data .package ,
930947 dist_git_branch = dist_git_branch ,
931- upstream_fix = backport_data .patch_url ,
948+ upstream_patches = backport_data .patch_urls ,
932949 jira_issue = backport_data .jira_issue ,
933950 cve_id = backport_data .cve_id ,
934951 redis_conn = redis ,
0 commit comments