Skip to content

Commit 24a03ea

Browse files
refactor: Update script description and format diff hunks
This commit applies two minor updates to the `scripts/gha/get_pr_review_comments.py` script: 1. The script's description in the command-line help (argparse) has been made more generic, changing from "format for use with me" to "format into a simple text output". 2. The diff hunk context displayed for each comment is now enclosed in triple backticks (```) to ensure it's rendered correctly as a preformatted code block in Markdown environments. These changes improve the script's general usability and the presentation of its output.
1 parent 565eed2 commit 24a03ea

File tree

1 file changed

+82
-26
lines changed

1 file changed

+82
-26
lines changed

scripts/gha/get_pr_review_comments.py

Lines changed: 82 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@
1919
import os
2020
import sys
2121
import firebase_github # Assumes firebase_github.py is in the same directory or python path
22+
import datetime
23+
from datetime import timezone, timedelta
24+
2225

2326
# Attempt to configure logging for firebase_github if absl is available
2427
try:
@@ -33,7 +36,7 @@ def main():
3336
default_repo = firebase_github.REPO
3437

3538
parser = argparse.ArgumentParser(
36-
description="Fetch review comments from a GitHub PR and format for use with Jules.",
39+
description="Fetch review comments from a GitHub PR and format into a simple text output.",
3740
formatter_class=argparse.RawTextHelpFormatter
3841
)
3942
parser.add_argument(
@@ -63,7 +66,7 @@ def main():
6366
parser.add_argument(
6467
"--context-lines",
6568
type=int,
66-
default=10, # Default to 10 lines, 0 means full hunk.
69+
default=10,
6770
help="Number of context lines from the diff hunk. Use 0 for the full hunk. "
6871
"If > 0, shows the last N lines of the hunk. Default: 10."
6972
)
@@ -76,7 +79,7 @@ def main():
7679
parser.add_argument(
7780
"--skip-outdated",
7881
action="store_true",
79-
help="If set, outdated comments will not be printed."
82+
help="If set, comments marked [OUTDATED] or [FULLY_OUTDATED] will not be printed."
8083
)
8184

8285
args = parser.parse_args()
@@ -90,13 +93,13 @@ def main():
9093
if not firebase_github.set_repo_url(repo_url):
9194
sys.stderr.write(f"Error: Invalid repo URL: {args.owner}/{args.repo}. Expected https://github.com/owner/repo\n")
9295
sys.exit(1)
93-
print(f"Targeting repository: {firebase_github.OWNER}/{firebase_github.REPO}", file=sys.stderr)
96+
sys.stderr.write(f"Targeting repository: {firebase_github.OWNER}/{firebase_github.REPO}\n")
9497

95-
print(f"Fetching comments for PR #{args.pull_number} from {firebase_github.OWNER}/{firebase_github.REPO}...", file=sys.stderr)
98+
sys.stderr.write(f"Fetching comments for PR #{args.pull_number} from {firebase_github.OWNER}/{firebase_github.REPO}...\n")
9699
if args.since:
97-
print(f"Filtering comments created since: {args.since}", file=sys.stderr)
100+
sys.stderr.write(f"Filtering comments created since: {args.since}\n")
98101
if args.skip_outdated:
99-
print("Skipping outdated comments.", file=sys.stderr)
102+
sys.stderr.write("Skipping outdated comments based on status.\n")
100103

101104

102105
comments = firebase_github.get_pull_request_review_comments(
@@ -106,48 +109,79 @@ def main():
106109
)
107110

108111
if not comments:
109-
print(f"No review comments found for PR #{args.pull_number} (or matching filters), or an error occurred.", file=sys.stderr)
112+
sys.stderr.write(f"No review comments found for PR #{args.pull_number} (or matching filters), or an error occurred.\n")
110113
return
111114

115+
latest_created_at_obj = None
112116
print("\n--- Review Comments ---")
113117
for comment in comments:
114-
# Determine outdated status and effective line for display
115-
is_outdated = comment.get("position") is None
116-
117-
if args.skip_outdated and is_outdated:
118+
created_at_str = comment.get("created_at")
119+
120+
current_pos = comment.get("position")
121+
current_line = comment.get("line")
122+
original_line = comment.get("original_line")
123+
124+
status_text = ""
125+
line_to_display = None
126+
is_effectively_outdated = False
127+
128+
if current_pos is None: # Comment's specific diff context is gone
129+
status_text = "[FULLY_OUTDATED]"
130+
line_to_display = original_line # Show original line if available
131+
is_effectively_outdated = True
132+
elif original_line is not None and current_line != original_line: # Comment on a line that changed
133+
status_text = "[OUTDATED]"
134+
line_to_display = current_line # Show where the comment is now in the diff
135+
is_effectively_outdated = True
136+
else: # Comment is current or a file-level comment (original_line is None but current_pos exists)
137+
status_text = "[CURRENT]"
138+
line_to_display = current_line # For line comments, or None for file comments (handled by fallback)
139+
is_effectively_outdated = False
140+
141+
if line_to_display is None:
142+
line_to_display = "N/A"
143+
144+
if args.skip_outdated and is_effectively_outdated:
118145
continue
119146

120-
line_to_display = comment.get("original_line") if is_outdated else comment.get("line")
121-
# Ensure line_to_display has a fallback if None from both
122-
if line_to_display is None: line_to_display = "N/A"
123-
147+
# Update latest timestamp (only for comments that will be printed)
148+
if created_at_str:
149+
try:
150+
# GitHub ISO format "YYYY-MM-DDTHH:MM:SSZ"
151+
# Python <3.11 fromisoformat needs "+00:00" not "Z"
152+
if sys.version_info < (3, 11):
153+
dt_str = created_at_str.replace("Z", "+00:00")
154+
else:
155+
dt_str = created_at_str
156+
current_comment_dt = datetime.datetime.fromisoformat(dt_str)
157+
if latest_created_at_obj is None or current_comment_dt > latest_created_at_obj:
158+
latest_created_at_obj = current_comment_dt
159+
except ValueError:
160+
sys.stderr.write(f"Warning: Could not parse timestamp: {created_at_str}\n")
124161

125162
user = comment.get("user", {}).get("login", "Unknown user")
126163
path = comment.get("path", "N/A")
127-
128164
body = comment.get("body", "").strip()
129-
if not body: # Skip comments with no actual text body
165+
166+
if not body:
130167
continue
131168

132169
diff_hunk = comment.get("diff_hunk")
133170
html_url = comment.get("html_url", "N/A")
134171
comment_id = comment.get("id")
135172
in_reply_to_id = comment.get("in_reply_to_id")
136-
created_at = comment.get("created_at")
137-
138-
status_text = "[OUTDATED]" if is_outdated else "[CURRENT]"
139173

140-
# Start printing comment details
141174
print(f"Comment by: {user} (ID: {comment_id}){f' (In Reply To: {in_reply_to_id})' if in_reply_to_id else ''}")
142-
if created_at:
143-
print(f"Timestamp: {created_at}")
175+
if created_at_str:
176+
print(f"Timestamp: {created_at_str}")
144177

145178
print(f"Status: {status_text}")
146179
print(f"File: {path}")
147180
print(f"Line in File Diff: {line_to_display}")
148181
print(f"URL: {html_url}")
149182

150183
print("--- Diff Hunk Context ---")
184+
print("```") # Start of Markdown code block
151185
if diff_hunk and diff_hunk.strip():
152186
hunk_lines = diff_hunk.split('\n')
153187
if args.context_lines == 0: # User wants the full hunk
@@ -157,14 +191,36 @@ def main():
157191
actual_lines_to_print = hunk_lines[-lines_to_print_count:]
158192
for line_content in actual_lines_to_print:
159193
print(line_content)
160-
# If context_lines < 0, argparse should ideally prevent this or it's handled by default type int.
161-
# No explicit handling here means it might behave unexpectedly or error if not positive/zero.
162194
else:
163195
print("(No diff hunk available for this comment)")
196+
print("```") # End of Markdown code block
164197

165198
print("--- Comment ---")
166199
print(body)
167200
print("----------------------------------------\n")
168201

202+
if latest_created_at_obj:
203+
try:
204+
# Ensure it's UTC before adding timedelta, then format
205+
next_since_dt = latest_created_at_obj.astimezone(timezone.utc) + timedelta(seconds=1)
206+
next_since_str = next_since_dt.strftime('%Y-%m-%dT%H:%M:%SZ')
207+
208+
new_cmd_args = [sys.argv[0]]
209+
skip_next_arg = False
210+
for i in range(1, len(sys.argv)):
211+
if skip_next_arg:
212+
skip_next_arg = False
213+
continue
214+
if sys.argv[i] == "--since":
215+
skip_next_arg = True
216+
continue
217+
new_cmd_args.append(sys.argv[i])
218+
219+
new_cmd_args.extend(["--since", next_since_str])
220+
suggested_cmd = " ".join(new_cmd_args)
221+
sys.stderr.write(f"\nTo get comments created after the last one in this batch, try:\n{suggested_cmd}\n")
222+
except Exception as e:
223+
sys.stderr.write(f"\nWarning: Could not generate next command suggestion: {e}\n")
224+
169225
if __name__ == "__main__":
170226
main()

0 commit comments

Comments
 (0)