@@ -109,6 +109,74 @@ def get_pull_request_review_comments(token, pull_number, since=None):
109
109
return results
110
110
111
111
112
+ def list_pull_requests (token , state , head , base ):
113
+ """https://docs.github.com/en/rest/reference/pulls#list-pull-requests"""
114
+ url = f'{ GITHUB_API_URL } /pulls'
115
+ headers = {'Accept' : 'application/vnd.github.v3+json' , 'Authorization' : f'token { token } ' }
116
+ page = 1
117
+ per_page = 100
118
+ results = []
119
+ keep_going = True
120
+ while keep_going :
121
+ params = {'per_page' : per_page , 'page' : page }
122
+ if state : params .update ({'state' : state })
123
+ if head : params .update ({'head' : head })
124
+ if base : params .update ({'base' : base })
125
+ page = page + 1
126
+ keep_going = False
127
+ # Ensure GITHUB_API_URL is set before this function is called if OWNER/REPO are not passed explicitly
128
+ # For standalone script, OWNER and REPO are global and GITHUB_API_URL is set by set_repo_url_standalone
129
+ try :
130
+ with requests_retry_session ().get (url , headers = headers , params = params ,
131
+ stream = True , timeout = TIMEOUT ) as response :
132
+ logging .info ("list_pull_requests: %s params: %s response: %s" , url , params , response )
133
+ response .raise_for_status () # Raise an exception for bad status codes
134
+ current_page_results = response .json ()
135
+ if not current_page_results : # No more results on this page
136
+ break
137
+ results .extend (current_page_results )
138
+ # If exactly per_page results were retrieved, read the next page.
139
+ keep_going = (len (current_page_results ) == per_page )
140
+ except requests .exceptions .RequestException as e :
141
+ logging .error (f"Error listing pull requests (page { params .get ('page' , 'N/A' )} , params: { params } ) for { OWNER } /{ REPO } : { e } " )
142
+ break # Stop trying if there's an error
143
+ return results
144
+
145
+
146
+ def get_current_branch_name ():
147
+ """Gets the current git branch name."""
148
+ try :
149
+ branch_bytes = subprocess .check_output (["git" , "rev-parse" , "--abbrev-ref" , "HEAD" ], stderr = subprocess .PIPE )
150
+ return branch_bytes .decode ().strip ()
151
+ except (subprocess .CalledProcessError , FileNotFoundError , UnicodeDecodeError ) as e :
152
+ sys .stderr .write (f"Could not determine current git branch: { e } \n " )
153
+ return None
154
+
155
+ def get_latest_pr_for_branch (token , owner , repo , branch_name ):
156
+ """Fetches the most recent open pull request for a given branch."""
157
+ if not owner or not repo :
158
+ sys .stderr .write ("Owner and repo must be set to find PR for branch.\n " )
159
+ return None
160
+
161
+ head_branch_spec = f"{ owner } :{ branch_name } " # GitHub API requires owner in head spec for forks
162
+ prs = list_pull_requests (token = token , state = "open" , head = head_branch_spec , base = None ) # base can be None
163
+
164
+ if not prs :
165
+ return None
166
+
167
+ # Sort PRs by creation date, most recent first
168
+ # PRs are dictionaries, 'created_at' is an ISO 8601 string
169
+ try :
170
+ prs .sort (key = lambda pr : pr .get ("created_at" , "" ), reverse = True )
171
+ except Exception as e :
172
+ sys .stderr .write (f"Could not sort PRs by creation date: { e } \n " )
173
+ return None # Or handle more gracefully
174
+
175
+ if prs : # Check if list is not empty after sort
176
+ return prs [0 ].get ("number" )
177
+ return None
178
+
179
+
112
180
def main ():
113
181
STATUS_IRRELEVANT = "[IRRELEVANT]"
114
182
STATUS_OLD = "[OLD]"
@@ -151,6 +219,12 @@ def parse_repo_url(url_string):
151
219
help = "Pull request number."
152
220
)
153
221
# Arguments for repository specification
222
+ parser .add_argument (
223
+ "--pull_number" ,
224
+ type = int ,
225
+ default = None , # Now optional
226
+ help = "Pull request number. If not provided, script attempts to find the latest open PR for the current git branch."
227
+ )
154
228
parser .add_argument (
155
229
"--url" ,
156
230
type = str ,
@@ -255,22 +329,42 @@ def parse_repo_url(url_string):
255
329
parser .print_help ()
256
330
sys .exit (1 )
257
331
258
- if not set_repo_url_standalone (final_owner , final_repo ):
332
+ if not set_repo_url_standalone (final_owner , final_repo ): # Sets global OWNER and REPO
259
333
sys .stderr .write (f"Error: Could not set repository to { final_owner } /{ final_repo } . Ensure owner/repo are correct.\n " )
260
334
sys .exit (1 )
261
335
262
- sys .stderr .write (f"Fetching comments for PR #{ args .pull_number } from { OWNER } /{ REPO } ...\n " )
336
+ pull_request_number = args .pull_number
337
+ if not pull_request_number :
338
+ sys .stderr .write ("Pull number not specified, attempting to find PR for current branch...\n " )
339
+ current_branch = get_current_branch_name ()
340
+ if current_branch :
341
+ sys .stderr .write (f"Current git branch is: { current_branch } \n " )
342
+ # Pass global OWNER and REPO which are set by set_repo_url_standalone
343
+ pull_request_number = get_latest_pr_for_branch (args .token , OWNER , REPO , current_branch )
344
+ if pull_request_number :
345
+ sys .stderr .write (f"Found PR #{ pull_request_number } for branch { current_branch } .\n " )
346
+ else :
347
+ sys .stderr .write (f"No open PR found for branch { current_branch } in { OWNER } /{ REPO } .\n " )
348
+ else :
349
+ sys .stderr .write ("Could not determine current git branch. Cannot find PR automatically.\n " )
350
+
351
+ if not pull_request_number :
352
+ sys .stderr .write ("Error: Pull request number is required. Provide --pull_number or ensure an open PR exists for the current branch.\n " )
353
+ parser .print_help ()
354
+ sys .exit (1 )
355
+
356
+ sys .stderr .write (f"Fetching comments for PR #{ pull_request_number } from { OWNER } /{ REPO } ...\n " )
263
357
if args .since :
264
358
sys .stderr .write (f"Filtering comments updated since: { args .since } \n " )
265
359
266
360
comments = get_pull_request_review_comments (
267
361
args .token ,
268
- args . pull_number ,
362
+ pull_request_number ,
269
363
since = args .since
270
364
)
271
365
272
366
if not comments :
273
- sys .stderr .write (f"No review comments found for PR #{ args . pull_number } (or matching filters), or an error occurred.\n " )
367
+ sys .stderr .write (f"No review comments found for PR #{ pull_request_number } (or matching filters), or an error occurred.\n " )
274
368
return
275
369
276
370
latest_activity_timestamp_obj = None
0 commit comments