Keep PR checks green and resolve new review comments by iterating until no new feedback remains.
Scope
Triggers
Inputs
Setup
gh repo view --json owner,name -q '.owner.login + " " + .name'
LAST_SEEN_COMMENT_ID=0, ITERATION=0.Steps
ITERATION > 120, stop and report current status.LAST_SEEN_COMMENT_ID). Update LAST_SEEN_COMMENT_ID to the highest seen ID.sleep 15) and repeat from step 1.gh run rerun --failed once per failed run. Return to step 1.trunk check, make test, or whatever the repo defines).LAST_SEEN_COMMENT_ID, non-threaded):Constraints
Safety
Examples
PR: https://github.com/org/repo/pull/123
Commands
# Derive owner and repo
eval $(gh repo view --json owner,name -q '"OWNER=\(.owner.login) REPO=\(.name)"')
# Status checks + review decision
gh pr view <PR> --json statusCheckRollup,reviewDecision
# Unresolved review threads (GraphQL)
gh api graphql -f query='
query($owner:String!,$repo:String!,$number:Int!){
repository(owner:$owner,name:$repo){
pullRequest(number:$number){
reviewThreads(first:100){
nodes{ id isResolved path line comments(first:1){ nodes{ id body author{login} } } }
}
}
}
}' -f owner="$OWNER" -f repo="$REPO" -F number=<PR_NUMBER> \
| jq '.data.repository.pullRequest.reviewThreads.nodes[] | select(.isResolved==false)'
# Resolve a review thread (GraphQL)
gh api graphql -f query='mutation($id:ID!){ resolveReviewThread(input:{threadId:$id}){ thread{isResolved} } }' \
-F id=THREAD_ID
# PR discussion comments (issue comments), sorted for tracking
gh api "repos/$OWNER/$REPO/issues/<PR_NUMBER>/comments" --jq '.[] | {id, body, user: .user.login, updated_at}'
# PR review comments (inline on diffs)
gh api "repos/$OWNER/$REPO/pulls/<PR_NUMBER>/comments" --jq '.[] | {id, body, path, line, user: .user.login}'
# Reply to a PR review comment
gh api "repos/$OWNER/$REPO/pulls/comments/COMMENT_ID/replies" -f body="<rationale>"
# Re-run failed CI checks
gh run rerun <RUN_ID> --failed