Skills › Compound Engineering › ce-resolve-pr-feedback › reply-to-pr-thread
reply-to-pr-thread
57 lines · skills/ce-resolve-pr-feedback/scripts/reply-to-pr-thread at 3449230
1#!/usr/bin/env bash
3# Replies directly to a PR review thread's root comment. Body is read from
4# stdin to preserve Markdown quotes and newlines. The REST reply endpoint is
5# load-bearing: GraphQL addPullRequestReviewThreadReply can attach the reply to
6# a pending review and return success before the reply is submitted or visible.
8set -e
10if [ $# -lt 2 ]; then
11 echo "Usage: reply-to-pr-thread PR_NUMBER ROOT_COMMENT_ID [OWNER/REPO] < reply-body.md"
12 echo "Example: reply-to-pr-thread 123 456789 EveryInc/cora < reply-body.md"
13 exit 1
14fi
16PR_NUMBER=$1
17ROOT_COMMENT_ID=$2
18IFS= read -r -d '' BODY || true
20if [ -n "$3" ]; then
21 OWNER=$(echo "$3" | cut -d/ -f1)
22 REPO=$(echo "$3" | cut -d/ -f2)
23else
24 OWNER=$(gh repo view --json owner -q .owner.login 2>/dev/null || true)
25 REPO=$(gh repo view --json name -q .name 2>/dev/null || true)
26fi
28if [ -z "$OWNER" ] || [ -z "$REPO" ]; then
29 echo "Error: could not resolve owner/repo. Pass OWNER/REPO as the third argument." >&2
30 exit 1
31fi
33case "$PR_NUMBER" in
34 ''|*[!0-9]*) echo "Error: PR_NUMBER must be numeric." >&2; exit 1 ;;
35esac
37case "$ROOT_COMMENT_ID" in
38 ''|*[!0-9]*) echo "Error: ROOT_COMMENT_ID must be numeric." >&2; exit 1 ;;
39esac
41if [ -z "$BODY" ]; then
42 echo "Error: No body provided on stdin."
43 exit 1
44fi
46gh api --method POST \
47 "repos/$OWNER/$REPO/pulls/$PR_NUMBER/comments/$ROOT_COMMENT_ID/replies" \
48 -f body="$BODY"
50PENDING_REVIEW=$(gh api --paginate \
51 "repos/$OWNER/$REPO/pulls/$PR_NUMBER/reviews" \
52 --jq '.[] | select(.state == "PENDING") | .id')
54if [ -n "$PENDING_REVIEW" ]; then
55 echo "Error: a pending review appeared after posting. Stop without resolving the thread; do not submit or discard the review." >&2
56 exit 2
57fi