Skip to content

Commit b68335c

Browse files
Feat: Enhance 'next command' suggestion with overall review timestamps
Improves the accuracy and applicability of the suggested next command for fetching subsequent comments. - The script now tracks the latest `submitted_at` timestamp from overall PR reviews, in addition to the latest `updated_at` timestamp from line-specific comments. - The `--since` value in the suggested next command is now based on the globally latest timestamp found across both overall reviews and line comments. - This ensures that a 'next command' suggestion can be provided even if only overall reviews (or only line comments) were found, and that the timestamp used is the most recent activity of either type.
1 parent 5df954d commit b68335c

File tree

1 file changed

+70
-12
lines changed

1 file changed

+70
-12
lines changed

scripts/gha/get_pr_review_comments_standalone.py

Lines changed: 70 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -427,20 +427,36 @@ def parse_repo_url(url_string):
427427
except Exception as e: # Broad exception for safety
428428
sys.stderr.write(f"Warning: Could not sort overall reviews: {e}\n")
429429

430+
# Output overall reviews if any exist after filtering
430431
if filtered_overall_reviews:
431-
print("# Overall Review Summaries\n\n")
432+
print("# Code Reviews\n\n") # Changed heading
432433
for review in filtered_overall_reviews:
433434
user = review.get("user", {}).get("login", "Unknown user")
434-
submitted_at = review.get("submitted_at", "N/A")
435+
submitted_at_str = review.get("submitted_at", "N/A") # Keep original string for printing
435436
state = review.get("state", "N/A")
436437
body = review.get("body", "").strip()
438+
439+
# Track latest overall review timestamp
440+
if submitted_at_str and submitted_at_str != "N/A":
441+
try:
442+
if sys.version_info < (3, 11):
443+
dt_str_submitted = submitted_at_str.replace("Z", "+00:00")
444+
else:
445+
dt_str_submitted = submitted_at_str
446+
current_review_submitted_dt = datetime.datetime.fromisoformat(dt_str_submitted)
447+
if latest_overall_review_activity_dt is None or current_review_submitted_dt > latest_overall_review_activity_dt:
448+
latest_overall_review_activity_dt = current_review_submitted_dt
449+
except ValueError:
450+
sys.stderr.write(f"Warning: Could not parse overall review submitted_at for --since suggestion: {submitted_at_str}\n")
451+
437452
html_url = review.get("html_url", "N/A")
438453
review_id = review.get("id", "N/A")
439454

440455
print(f"## Review by: **{user}** (ID: `{review_id}`)\n")
441-
print(f"* **Submitted At**: `{submitted_at}`")
456+
print(f"* **Submitted At**: `{submitted_at_str}`") # Print original string
442457
print(f"* **State**: `{state}`")
443458
print(f"* **URL**: <{html_url}>\n")
459+
# Removed duplicated lines here
444460

445461
if body:
446462
print("\n### Summary Comment:")
@@ -469,10 +485,43 @@ def parse_repo_url(url_string):
469485
# Handling for empty line comments will be just before their processing loop.
470486
# if not comments: (handled later)
471487

472-
latest_activity_timestamp_obj = None # This is for line comments' 'since' suggestion
488+
latest_overall_review_activity_dt = None
489+
latest_line_comment_activity_dt = None # Renamed from latest_activity_timestamp_obj
473490
processed_comments_count = 0 # This tracks line comments
474-
print("# Review Comments\n\n")
475-
for comment in comments:
491+
492+
# Only print line comments header if there are comments to process
493+
# The 'comments' list here has already been checked for None (API error)
494+
# and for being empty (no comments found, in which case script would have exited).
495+
# However, all comments could be filtered out by status or content.
496+
# So, we'll print the header, and if nothing follows, it's acceptable.
497+
# A more robust check would be to see if any comment *will* be printed.
498+
# For now, let's check if the list is non-empty before printing the header.
499+
# The user's request was "if there are no review comments to display".
500+
# This means after all filtering. The current loop structure processes then prints.
501+
# A simple way is to print header only if `comments` list is not empty,
502+
# and then if the loop results in `processed_comments_count == 0`, the section will be empty.
503+
# Or, delay printing header until first comment is processed.
504+
505+
# Let's try: print header only if comments list is not empty *before* the loop.
506+
# If all get filtered out, an empty section is fine.
507+
# The existing "No review comments found..." handles the case of an initially empty list.
508+
# The current plan asks for "processed_comments_count > 0". This requires a look-ahead or restructuring.
509+
510+
# Simpler approach: If the `comments` list (from API) is not empty, print header.
511+
# If all get filtered out inside the loop, the section will be empty.
512+
# The earlier check `elif not comments:` handles the case of truly no comments from API.
513+
# So, if we reach here, `comments` is a non-empty list.
514+
# The condition should be: if any comments *survive* the loop's internal filters.
515+
# This is best done by checking `processed_comments_count` *after* the loop,
516+
# but the header needs to be printed *before*.
517+
# So, we print the header if `comments` is not empty, and accept an empty section if all are filtered.
518+
# The user's request can be interpreted as "don't print the header if the `comments` list is empty
519+
# *after fetching and initial checks*".
520+
521+
if comments: # If the list from API (after None check) is not empty
522+
print("# Review Comments\n\n")
523+
524+
for comment in comments: # `comments` is guaranteed to be a list here
476525
created_at_str = comment.get("created_at")
477526

478527
current_pos = comment.get("position")
@@ -509,10 +558,10 @@ def parse_repo_url(url_string):
509558
else:
510559
dt_str_updated = updated_at_str
511560
current_comment_activity_dt = datetime.datetime.fromisoformat(dt_str_updated)
512-
if latest_activity_timestamp_obj is None or current_comment_activity_dt > latest_activity_timestamp_obj:
513-
latest_activity_timestamp_obj = current_comment_activity_dt
561+
if latest_line_comment_activity_dt is None or current_comment_activity_dt > latest_line_comment_activity_dt: # Corrected variable name
562+
latest_line_comment_activity_dt = current_comment_activity_dt # Corrected variable name
514563
except ValueError:
515-
sys.stderr.write(f"Warning: Could not parse updated_at timestamp: {updated_at_str}\n")
564+
sys.stderr.write(f"Warning: Could not parse line comment updated_at for --since suggestion: {updated_at_str}\n")
516565

517566
user = comment.get("user", {}).get("login", "Unknown user")
518567
path = comment.get("path", "N/A")
@@ -557,10 +606,19 @@ def parse_repo_url(url_string):
557606

558607
sys.stderr.write(f"\nPrinted {processed_comments_count} comments to stdout.\n")
559608

560-
if latest_activity_timestamp_obj:
609+
# Determine the overall latest activity timestamp
610+
overall_latest_activity_dt = None
611+
if latest_overall_review_activity_dt and latest_line_comment_activity_dt:
612+
overall_latest_activity_dt = max(latest_overall_review_activity_dt, latest_line_comment_activity_dt)
613+
elif latest_overall_review_activity_dt:
614+
overall_latest_activity_dt = latest_overall_review_activity_dt
615+
elif latest_line_comment_activity_dt:
616+
overall_latest_activity_dt = latest_line_comment_activity_dt
617+
618+
if overall_latest_activity_dt:
561619
try:
562-
# Suggest next command with '--since' pointing to just after the latest comment processed.
563-
next_since_dt = latest_activity_timestamp_obj.astimezone(timezone.utc) + timedelta(seconds=2)
620+
# Suggest next command with '--since' pointing to just after the latest activity.
621+
next_since_dt = overall_latest_activity_dt.astimezone(timezone.utc) + timedelta(seconds=2)
564622
next_since_str = next_since_dt.strftime('%Y-%m-%dT%H:%M:%SZ')
565623

566624
new_cmd_args = [sys.executable, sys.argv[0]]

0 commit comments

Comments
 (0)