1919# by the cherry-picked commits have any other modifications in the target branch history
2020# that are not included in the cherry-pick list.
2121import argparse
22- import subprocess
2322import json
23+ import subprocess
2424import sys
2525from collections import defaultdict
2626
27+
2728def main ():
2829 parser = argparse .ArgumentParser (description = "Generate cherry-pick script from PRs with a specific label." )
2930 parser .add_argument ("--label" , required = True , help = "Label to filter PRs" )
3031 parser .add_argument ("--output" , required = True , help = "Output cmd file path" )
3132 parser .add_argument ("--repo" , default = "microsoft/onnxruntime" , help = "Repository (default: microsoft/onnxruntime)" )
32- parser .add_argument ("--branch" , default = "HEAD" , help = "Target branch to compare against for dependency checks (default: HEAD)" )
33+ parser .add_argument (
34+ "--branch" , default = "HEAD" , help = "Target branch to compare against for dependency checks (default: HEAD)"
35+ )
3336 args = parser .parse_args ()
3437
3538 # Fetch merged PRs with the specified label using gh CLI
3639 print (f"Fetching merged PRs with label '{ args .label } ' from { args .repo } ..." )
3740 cmd = [
38- "gh" , "pr" , "list" ,
39- "--repo" , args .repo ,
40- "--label" , args .label ,
41- "--state" , "merged" ,
42- "--json" , "number,title,mergeCommit,mergedAt" ,
43- "-L" , "200"
41+ "gh" ,
42+ "pr" ,
43+ "list" ,
44+ "--repo" ,
45+ args .repo ,
46+ "--label" ,
47+ args .label ,
48+ "--state" ,
49+ "merged" ,
50+ "--json" ,
51+ "number,title,mergeCommit,mergedAt" ,
52+ "-L" ,
53+ "200" ,
4454 ]
4555
4656 try :
@@ -60,7 +70,7 @@ def main():
6070 return
6171
6272 # Sort by mergedAt (ISO 8601 strings sort correctly in chronological order)
63- prs .sort (key = lambda x : x [' mergedAt' ])
73+ prs .sort (key = lambda x : x [" mergedAt" ])
6474
6575 # Write to output cmd file
6676 commit_count = 0
@@ -70,15 +80,15 @@ def main():
7080 f .write ("rem Sorted by merge time (oldest first)\n \n " )
7181
7282 for pr in prs :
73- number = pr [' number' ]
74- title = pr [' title' ]
75- safe_title = title .replace (' \n ' , ' ' )
83+ number = pr [" number" ]
84+ title = pr [" title" ]
85+ safe_title = title .replace (" \n " , " " )
7686
77- if not pr .get (' mergeCommit' ):
87+ if not pr .get (" mergeCommit" ):
7888 print (f"Warning: PR #{ number } has no merge commit OID. Skipping." , file = sys .stderr )
7989 continue
8090
81- oid = pr [' mergeCommit' ][ ' oid' ]
91+ oid = pr [" mergeCommit" ][ " oid" ]
8292 f .write (f"rem PR { number } : { safe_title } \n " )
8393 f .write (f"git cherry-pick { oid } \n \n " )
8494 commit_count += 1
@@ -88,11 +98,11 @@ def main():
8898 # Write to markdown file. You can use it as the pull request description.
8999 md_output = "cherry_pick_pr_description.md"
90100 with open (md_output , "w" , encoding = "utf-8" ) as f :
91- f .write (f "This cherry-picks the following commits for the release:\n " )
101+ f .write ("This cherry-picks the following commits for the release:\n " )
92102 for pr in prs :
93- if not pr .get (' mergeCommit' ):
103+ if not pr .get (" mergeCommit" ):
94104 continue
95- number = pr [' number' ]
105+ number = pr [" number" ]
96106 f .write (f"- #{ number } \n " )
97107
98108 print (f"Generated { md_output } with { commit_count } commits." )
@@ -103,21 +113,23 @@ def main():
103113 # Collect OIDs being cherry-picked
104114 cherry_pick_oids = set ()
105115 for pr in prs :
106- if pr .get (' mergeCommit' ):
107- cherry_pick_oids .add (pr [' mergeCommit' ][ ' oid' ])
116+ if pr .get (" mergeCommit" ):
117+ cherry_pick_oids .add (pr [" mergeCommit" ][ " oid" ])
108118
109119 for pr in prs :
110- if not pr .get (' mergeCommit' ):
120+ if not pr .get (" mergeCommit" ):
111121 continue
112122
113- oid = pr [' mergeCommit' ][ ' oid' ]
114- number = pr [' number' ]
123+ oid = pr [" mergeCommit" ][ " oid" ]
124+ number = pr [" number" ]
115125
116126 # Get files changed by this commit
117127 try :
118128 res = subprocess .run (
119129 ["git" , "diff-tree" , "--no-commit-id" , "--name-only" , "-r" , oid ],
120- capture_output = True , text = True , check = True
130+ capture_output = True ,
131+ text = True ,
132+ check = True ,
121133 )
122134 files = res .stdout .strip ().splitlines ()
123135 except subprocess .CalledProcessError as e :
@@ -132,10 +144,12 @@ def main():
132144 try :
133145 res = subprocess .run (
134146 ["git" , "log" , oid , "--not" , args .branch , "--format=%H %s" , "--" , filepath ],
135- capture_output = True , text = True , check = True
147+ capture_output = True ,
148+ text = True ,
149+ check = True ,
136150 )
137151 for line in res .stdout .strip ().splitlines ():
138- parts = line .split (' ' , 1 )
152+ parts = line .split (" " , 1 )
139153 c = parts [0 ]
140154 title = parts [1 ] if len (parts ) > 1 else ""
141155
@@ -155,8 +169,11 @@ def main():
155169 # Print deduplicated warnings
156170 for missing_oid , (title , affected_files ) in missing_commits .items ():
157171 files_str = ", " .join (affected_files )
158- print (f"WARNING: PR #{ number } ({ oid } ) depends on commit { missing_oid } ({ title } ) "
159- f"which is not in the cherry-pick list. Affected files: { files_str } " )
172+ print (
173+ f"WARNING: PR #{ number } ({ oid } ) depends on commit { missing_oid } ({ title } ) "
174+ f"which is not in the cherry-pick list. Affected files: { files_str } "
175+ )
176+
160177
161178if __name__ == "__main__" :
162179 main ()
0 commit comments