Skip to content

Commit 252b5fa

Browse files
Feat: Auto-detect PR number from current git branch
- Makes the --pull_number argument optional. - If --pull_number is not provided, the script now attempts to: 1. Determine the current git branch. 2. Fetch open pull requests for this branch using the GitHub API. 3. Select the most recently created open PR. - If a PR cannot be determined either way, an error is shown. - Incorporates the `list_pull_requests` function from the original `firebase_github.py` to support this feature. - Adds error handling for git operations and API calls related to PR detection.
1 parent 815d605 commit 252b5fa

File tree

1 file changed

+98
-4
lines changed

1 file changed

+98
-4
lines changed

scripts/gha/get_pr_review_comments_standalone.py

Lines changed: 98 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,74 @@ def get_pull_request_review_comments(token, pull_number, since=None):
109109
return results
110110

111111

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+
112180
def main():
113181
STATUS_IRRELEVANT = "[IRRELEVANT]"
114182
STATUS_OLD = "[OLD]"
@@ -151,6 +219,12 @@ def parse_repo_url(url_string):
151219
help="Pull request number."
152220
)
153221
# 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+
)
154228
parser.add_argument(
155229
"--url",
156230
type=str,
@@ -255,22 +329,42 @@ def parse_repo_url(url_string):
255329
parser.print_help()
256330
sys.exit(1)
257331

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
259333
sys.stderr.write(f"Error: Could not set repository to {final_owner}/{final_repo}. Ensure owner/repo are correct.\n")
260334
sys.exit(1)
261335

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")
263357
if args.since:
264358
sys.stderr.write(f"Filtering comments updated since: {args.since}\n")
265359

266360
comments = get_pull_request_review_comments(
267361
args.token,
268-
args.pull_number,
362+
pull_request_number,
269363
since=args.since
270364
)
271365

272366
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")
274368
return
275369

276370
latest_activity_timestamp_obj = None

0 commit comments

Comments
 (0)