ci: sync Antigravity reviewer to the fixed comment-selection version - #259
Conversation
Bring the agy PR reviewer up to the version already on RustySNES main (via
its #270 template-hardening sync + #273 comment-selection fix),
superseding the stale sync PR, which carried an earlier version with a
real self-deletion bug that agy flagged.
What this version adds over the prior sync:
- The just-posted review comment's id now comes from the POST itself
(`gh pr comment` prints the new comment's URL; its trailing
`#issuecomment-<id>` is authoritative), NOT from re-querying the
comment list. The re-query raced GitHub's read replication -- right
after posting, the list could still omit the new comment, so the
"delete all but the newest" exclusion matched nothing and the run
deleted the review it had just published (publish-before-delete
turning into publish-then-destroy).
- SELECT_STALE_JQ: the delete-selection jq filter is now a named,
readonly constant (author + id-exclusion selects), exercised directly
by a new offline self-test.
- scripts/agy-review-selftest.sh: a network-free, gh-free test of that
filter against fixtures (the filter has been wrong twice, both times
invisibly -- the review still posted, so nothing observed it). Six
checks, all passing.
- Fail-closed flock (exit rather than run two agy processes
unserialized) plus an empty-AGY_LOCK guard.
- Keeps the URL-only OAuth-leak guard (oauth_url_present) unchanged.
Byte-identical with RustySNES main and the shared reviewer template.
bash -n clean; the self-test passes all six checks.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
📝 WalkthroughSummary by CodeRabbit
WalkthroughThe review script now enforces locking, validates generated comments, publishes before cleanup, and safely selects older bot comments. A new offline self-test validates the jq filter and API argument handling. ChangesReview comment replacement hardening
Estimated code review effort: 3 (Moderate) | ~25 minutes Possibly related PRs
Suggested reviewers: Sequence Diagram(s)sequenceDiagram
participant ReviewScript
participant GitHubAPI
participant JQ
ReviewScript->>GitHubAPI: publish new review comment
GitHubAPI-->>ReviewScript: return new comment ID
ReviewScript->>GitHubAPI: list review comments
GitHubAPI-->>ReviewScript: return comment data
ReviewScript->>JQ: select older matching bot comments
JQ-->>ReviewScript: return stale comment IDs
ReviewScript->>GitHubAPI: delete selected comments
🚥 Pre-merge checks | ✅ 8 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (8 passed)
Comment |
Antigravity review (Gemini via Ultra)This PR refactors Blocking issuesNone found. Suggestions
Nitpicks
Automated first-pass review by |
There was a problem hiding this comment.
Pull request overview
Updates the Antigravity (agy) GitHub PR reviewer script to the fixed “post-then-delete” implementation that avoids self-deleting the freshly posted review comment, and adds an offline self-test to keep the deletion-selection logic correct over time.
Changes:
- Introduces a named, readonly
SELECT_STALE_JQfilter and uses the posted comment’s ID fromgh pr commentoutput to safely exclude the new comment from deletion. - Hardens serialization around
agyexecution by requiringflockand failing closed if locking can’t be established. - Adds
scripts/agy-review-selftest.shto validate the jq deletion-selection logic offline against fixtures and to prevent regressions around--arg/--argjsonusage.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| scripts/agy-review.sh | Fixes comment replacement ordering and ID selection to prevent deleting the newly posted review; hardens locking behavior; factors deletion selection into SELECT_STALE_JQ. |
| scripts/agy-review-selftest.sh | Adds a network-free regression test for the jq-based stale-comment selection logic and the gh api/jq flag split. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@scripts/agy-review.sh`:
- Around line 576-614: Pin the GitHub CLI version used by scripts/agy-review.sh,
or add an explicit version assertion before the comment-posting flow that parses
post_output and new_comment_id. Ensure the workflow fails or stops safely when
the installed gh version is unsupported, preserving deterministic extraction of
the created comment URL.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: a546d1b1-8911-4691-a168-83ce68629473
📒 Files selected for processing (2)
scripts/agy-review-selftest.shscripts/agy-review.sh
| new_comment_id="$(printf '%s\n' "$post_output" | sed -n 's/.*#issuecomment-\([0-9][0-9]*\).*/\1/p' | tail -n 1)" | ||
|
|
||
| # A failed delete is logged, not swallowed: silently ignoring it would let a transient API/perms | ||
| # error leave the old comment in place alongside the new one, so runs accumulate duplicates. | ||
| # The author filter is load-bearing, not cosmetic: without it, ANY user could put the | ||
| # marker (an HTML comment) in a PR comment and have this bot delete arbitrary comments on | ||
| # the next run. Only ever delete OUR OWN bot's prior review comments -- and only ones from | ||
| # BEFORE this run (the just-posted comment's own id is excluded so it can never delete itself). | ||
| if [ -z "$new_comment_id" ]; then | ||
| # FAIL CLOSED. Without a known id there is no way to tell the new comment from the old ones, | ||
| # and the safe direction is unambiguous: a leftover duplicate is noise, deleting the review | ||
| # that was just posted is data loss. | ||
| log "warning: could not determine the posted comment id; leaving prior review comments in place" | ||
| else | ||
| # `--arg`/`--argjson` rather than shell interpolation into the filter: the marker is an HTML | ||
| # comment today, but a quote or a backslash in it would otherwise break the jq program itself | ||
| # rather than simply not matching. | ||
| # | ||
| # Those are JQ flags, so the JSON is fetched raw and piped into a real `jq` — `gh api` has no | ||
| # `--arg`/`--argjson` of its own and rejects them. Handing them to `gh api --jq` made it exit | ||
| # non-zero on every run; with the old `2>/dev/null` swallowing the message and `set -o pipefail` | ||
| # in force, the script then died *after* posting, so the stale comments were never deleted and | ||
| # the job went red for a reason nothing printed. stderr is kept this time for exactly that | ||
| # reason. (`--paginate` without `--jq` emits one JSON array per page; `jq` reads that stream | ||
| # fine, applying `.[]` to each.) | ||
| stale_ids="$( | ||
| gh api "repos/${REPO}/issues/${PR}/comments" --paginate \ | ||
| | jq -r --arg marker "$MARKER" --argjson new_id "$new_comment_id" "$SELECT_STALE_JQ" | ||
| )" || { | ||
| log "warning: could not list prior review comments; leaving them in place" | ||
| stale_ids="" | ||
| } | ||
| while read -r cid; do | ||
| [ -n "$cid" ] || continue | ||
| if ! gh api -X DELETE "repos/${REPO}/issues/comments/${cid}" >/dev/null 2>&1; then | ||
| log "warning: could not delete prior review comment ${cid}; a duplicate may result" | ||
| fi | ||
| done <<< "$stale_ids" | ||
| fi |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win
🧩 Analysis chain
🌐 Web query:
Does gh pr commentprint the new comment's URL (with#issuecomment-<id>) to stdout on success?
💡 Result:
No, the gh pr comment command does not print the URL of the newly created comment to stdout upon success [1][2]. While gh pr comment is designed to add a comment to a pull request, the official GitHub CLI documentation and manual pages do not list the output of a comment URL as part of its standard behavior [1][2]. In many cases, the command executes silently on success, or may provide minimal feedback depending on the terminal environment, but it does not return the structured URL (such as ...#issuecomment-<id>) that some users might expect for automation or scripting purposes [1][2]. If you require the URL of a newly created comment, you may need to use an alternative approach, such as: 1. Using gh api to perform the request directly, which allows you to inspect the full JSON response containing the html_url field [3][4]. 2. Listing the comments after the command has executed to retrieve the most recent one [5][6]. For programmatic workflows where the URL is needed, leveraging the gh api command with the appropriate REST API endpoint (typically /repos/{owner}/{repo}/issues/{pull_number}/comments) is the recommended way to retrieve the created comment's metadata, including its URL [3][7][8].
Citations:
- 1: https://manpages.opensuse.org/Tumbleweed/gh/gh-pr-comment.1.en.html
- 2: https://cli.github.com/manual/gh_pr_comment
- 3: https://stackoverflow.com/questions/78064829/use-cli-to-write-a-comment-pinned-to-a-file-and-line-number-on-a-github-pull-req
- 4: https://gist.github.com/mcfredrick/8a5fad0e718b2c48e91f20d9f8b3ff13
- 5: https://pkg.go.dev/github.com/silouanwright/gh-comment
- 6: https://github.com/STRRL/gh-pr-comments
- 7: https://docs.github.com/en/rest/guides/working-with-comments
- 8: https://docs.github.com/en/enterprise-server@3.18/rest/pulls/comments
🏁 Script executed:
#!/bin/bash
set -eu
printf '%s\n' '--- workflow references ---'
rg -n -C 3 'gh |gh-version|GH_VERSION|setup-gh|cli/cli|antigravity-review' .github/workflows/antigravity-review.yml .github 2>/dev/null || true
printf '%s\n' '--- script context ---'
sed -n '520,630p' scripts/agy-review.sh
printf '%s\n' '--- comment-posting calls ---'
rg -n -C 4 'gh pr comment|post_output|new_comment_id|SELECT_STALE_JQ' scripts/agy-review.shRepository: doublegate/RustyN64
Length of output: 18075
🏁 Script executed:
#!/bin/bash
set -eu
printf '%s\n' '--- complete review workflow ---'
cat -n .github/workflows/antigravity-review.yml | sed -n '1,110p'
printf '%s\n' '--- local gh availability ---'
if command -v gh >/dev/null 2>&1; then
gh --version
else
printf '%s\n' 'gh is not installed in the verifier sandbox'
fi
printf '%s\n' '--- repository references to gh versioning ---'
rg -n -i 'gh([ _-]?cli)?|github[ /]cli|cli/cli' \
.github/workflows scripts README.md .tool-versions .github 2>/dev/null || trueRepository: doublegate/RustyN64
Length of output: 18191
🌐 Web query:
site:github.com/cli/cli gh pr comment source output URL NewComment
💡 Result:
The gh pr comment command does not natively output the URL of a newly created comment to standard output in a simple, direct format by default [1]. However, you can obtain the URL of a newly created comment by using the command in combination with shell utilities or by capturing its output if the specific version of gh you are using supports it [2]. 1. Capture the output: Recent updates to gh have improved the behavior of command output. When running gh pr comment, you can often pipe or capture the output to verify the URL [2]. For example, in automated environments, you might see the URL printed to stdout if the command is executed successfully [2]. 2. Alternative Approach (Manual Retrieval): If the command does not provide the URL directly in your environment, you can retrieve it by querying the pull request's comments immediately after creation using gh pr view combined with jq [3][4]. Example using jq to find the most recent comment: gh pr view --json comments --jq '.comments[-1].url' 3. Best Practice for Automation: If you are working in CI/CD or scripts, the most reliable way to get the URL is to use the gh JSON output capabilities to inspect the PR state or to use the GitHub API directly via gh api to create the comment, which returns the full comment object including the html_url [3][5][1]. If you find that the command is not outputting the URL as expected, it is recommended to check your version of the GitHub CLI (gh --version) and use the gh pr view method for deterministic results in scripts [3][4].
Citations:
- 1: https://github.com/cli/cli/blob/c14cbaa2/skills/gh/SKILL.md
- 2: [
gh issue/pr comment] Add--create-if-noneand prompts to create a comment if no comment already exists cli/cli#10427 - 3: Edit comment - Minimize specific comment with reason cli/cli#8409
- 4:
gh pr/issue commentallow editing selected comments cli/cli#10865 - 5: Feature Request: Add inline comment support to gh pr comment cli/cli#12396
🌐 Web query:
site:cli.github.com/manual/gh_pr_comment "URL" output
💡 Result:
gh pr comment accepts a pull-request URL as its argument:
gh pr comment https://github.com/OWNER/REPO/pull/123 --body "Comment text"The command’s output behavior is not documented as returning a URL; it adds, edits, or deletes a comment. (cli.github.com)
Citations:
🏁 Script executed:
#!/bin/bash
set -eu
printf '%s\n' '--- gh 2.96.0 command help ---'
gh pr comment --help | sed -n '1,120p'
printf '%s\n' '--- gh 2.96.0 source references ---'
for path in \
pkg/cmd/pr/comment/comment.go \
pkg/cmd/pr/comment/comment_test.go
do
url="https://raw.githubusercontent.com/cli/cli/v2.96.0/${path}"
printf '%s\n' "--- ${url} ---"
curl -fsSL "$url" | rg -n -C 5 'Print|URL|html_url|NewComment|comment' | sed -n '1,180p' || true
doneRepository: doublegate/RustyN64
Length of output: 10533
Pin or assert the GitHub CLI version
gh v2.96.0 prints the created comment URL on stdout. The workflow does not pin gh, so this output format is not guaranteed on the self-hosted runner. Pin or assert the CLI version to preserve determinism.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@scripts/agy-review.sh` around lines 576 - 614, Pin the GitHub CLI version
used by scripts/agy-review.sh, or add an explicit version assertion before the
comment-posting flow that parses post_output and new_comment_id. Ensure the
workflow fails or stops safely when the installed gh version is unsupported,
preserving deterministic extraction of the created comment URL.
Summary
Brings the
agyPR reviewer up to the fixed version already on RustySNES main (via its #270 template-hardening sync + #273 comment-selection fix + a self-test), superseding the stale sync PR in this repo — which carried an earlier version with a real self-deletion bug agy flagged.Fix over the prior sync
gh pr commentprints the new comment's URL (…#issuecomment-<id>); that id is used directly. The old approach re-queried the comment list to find "the newest with our marker", which raced GitHub's read replication — right after posting, the list could still omit the new comment, so the "delete all but the newest" exclusion matched nothing and the run deleted the review it had just published (publish-before-delete turning into publish-then-destroy).SELECT_STALE_JQ— the delete-selection jq filter is now a namedreadonlyconstant (the author + id-exclusionselects), exercised directly by a new offline test.scripts/agy-review-selftest.sh— a network-free,gh-free test of that filter against fixtures (it has been wrong twice, both times invisibly — the review still posted, so nothing observed it). 6 checks, all passing.AGY_LOCKguard; the URL-only OAuth-leak guard (oauth_url_present) is unchanged.Verification
eabd2571…) with RustySNES main and the shared reviewer template.bash -nclean;bash scripts/agy-review-selftest.sh→ all 6 checks pass.🤖 Generated with Claude Code