Skip to content
Merged
103 changes: 89 additions & 14 deletions .github/workflows/claude-social-review.yml
Original file line number Diff line number Diff line change
Expand Up @@ -94,22 +94,55 @@ jobs:
SERVER_URL: ${{ github.server_url }}
run: |
set -e
# "Successful" prior run = "the workflow ran without crashing on this branch."
# The PASS/FAIL verdict lives in the PR comment, not the run conclusion.
# Either way, if the social copy hasn't changed, the prior verdict still
# applies — re-running risks flapping (PASS<->FAIL on identical copy).
# The review verdict lives in the PR comment, not the run conclusion —
# if the social copy hasn't changed since the comment was last updated,
# the verdict still applies. Re-running risks flapping (PASS<->FAIL on
# identical copy) and wastes Claude calls on PRs stuck on a char-limit
# fail (where every push to the same over-limit copy would otherwise
# trigger a fresh review).
#
# Baseline preference order:
# 1. Our edit-in-place comment's footer SHA (most accurate — atomic
# with the comment write, unaffected by later step failures).
# 2. Last successful workflow run on this branch (legacy fallback
# for PRs that pre-date the marker comment).
PRIOR_SHA=""
PRIOR_RUN_ID=""
BASELINE_SOURCE=""

# (1) Try the marker comment first.
# `|| true` on the grep pipeline so a missing footer doesn't kill the
# script under `set -e` — fall through to the run-based baseline instead.
COMMENT_BODY=$(gh api "repos/$REPO/issues/$PR_NUMBER/comments" \
--jq '[.[] | select(.body | startswith("<!-- social-review -->"))] | .[-1].body // empty')
if [ -n "$COMMENT_BODY" ]; then
COMMENT_SHA=$(echo "$COMMENT_BODY" | grep -oE 'commit `[a-f0-9]{7,40}`' | head -1 | grep -oE '[a-f0-9]{7,40}' || true)
if [ -n "$COMMENT_SHA" ]; then
PRIOR_SHA="$COMMENT_SHA"
BASELINE_SOURCE="comment"
echo "Baseline: social-review comment footer SHA $PRIOR_SHA"
fi
fi

# (2) Fall back to last successful run on this branch.
# `gh run list --branch` (and the API's ?branch= query) is unreliable
# for slash-containing branch names — silently returns empty for some
# branches that do have runs. Query the workflow's runs unfiltered and
# filter by head_branch in jq client-side, which always works.
PRIOR=$(gh api \
"repos/$REPO/actions/workflows/claude-social-review.yml/runs?per_page=30" \
--jq "[.workflow_runs[] | select(.head_branch == \"$HEAD_REF\" and .event == \"pull_request\" and .conclusion == \"success\" and .id != $RUN_ID)] | .[0]")
PRIOR_SHA=$(echo "$PRIOR" | jq -r '.head_sha // ""')
PRIOR_RUN_ID=$(echo "$PRIOR" | jq -r '.id // ""')
if [ -z "$PRIOR_SHA" ]; then
PRIOR=$(gh api \
"repos/$REPO/actions/workflows/claude-social-review.yml/runs?per_page=30" \
--jq "[.workflow_runs[] | select(.head_branch == \"$HEAD_REF\" and .event == \"pull_request\" and .conclusion == \"success\" and .id != $RUN_ID)] | .[0]")
PRIOR_SHA=$(echo "$PRIOR" | jq -r '.head_sha // ""')
PRIOR_RUN_ID=$(echo "$PRIOR" | jq -r '.id // ""')
if [ -n "$PRIOR_SHA" ]; then
BASELINE_SOURCE="run"
echo "Baseline: prior successful run $PRIOR_RUN_ID at SHA $PRIOR_SHA"
fi
fi

if [ -z "$PRIOR_SHA" ]; then
echo "No prior successful run on this branch — running review."
echo "No prior baseline (no marker comment, no successful run) — running review."
echo "should_skip=false" >> "$GITHUB_OUTPUT"
exit 0
fi
Expand All @@ -134,8 +167,26 @@ jobs:

if [ "$SHOULD_SKIP" = "true" ]; then
echo "should_skip=true" >> "$GITHUB_OUTPUT"
gh pr comment "$PR_NUMBER" --repo "$REPO" --body \
"🟰 **Skipping social media review** — $REASON. The verdict from the [prior run](${SERVER_URL}/${REPO}/actions/runs/${PRIOR_RUN_ID}) still applies. Comment \`/social-review\` to force a fresh review."
# Log to the action run instead of posting a PR comment — the comment
# was noisy on active PRs (one per push that didn't touch the social
# block). Anyone wanting a fresh review can still comment `/social-review`.
if [ "$BASELINE_SOURCE" = "comment" ]; then
VERDICT_LINK="The verdict in the existing social-review PR comment still applies."
NOTICE_TAIL="The PR comment from commit $PRIOR_SHA still applies."
else
VERDICT_LINK="The verdict from the [prior run](${SERVER_URL}/${REPO}/actions/runs/${PRIOR_RUN_ID}) still applies."
NOTICE_TAIL="Prior run: ${SERVER_URL}/${REPO}/actions/runs/${PRIOR_RUN_ID}."
fi
echo "::notice::Skipping social media review — $REASON. $NOTICE_TAIL Comment /social-review to force a fresh review."
{
echo "## 🟰 Skipping social media review"
echo ""
echo "**Reason:** $REASON"
echo ""
echo "$VERDICT_LINK"
echo ""
echo "Comment \`/social-review\` on the PR to force a fresh review."
} >> "$GITHUB_STEP_SUMMARY"
else
echo "should_skip=false" >> "$GITHUB_OUTPUT"
fi
Expand Down Expand Up @@ -217,8 +268,32 @@ jobs:

IMPORTANT: Keep the review short and scannable. Use `#### Platform — PASS` or `#### Platform — FAIL` headings with bullet-pointed reasons. No analysis paragraphs, no rubric citations. A blogger should read it in 30 seconds.

Post your review as a single comment titled `## Social Media Review` via `gh pr comment #${{ steps.pr-info.outputs.number }}`.
claude_args: '--model claude-sonnet-4-6 --allowed-tools "Read,Glob,Grep,Agent,Bash(python3:*),Bash(gh pr view:*),Bash(gh pr diff:*),Bash(gh pr comment:*)"'
Write the review to `.social-review.md`. Do NOT post a PR comment — a subsequent workflow step handles that. The file's body must:

1. Start with the literal line `<!-- social-review -->` (HTML comment marker; lets future runs find this comment to update it in place).
2. Then `## Social Media Review` and the per-platform sections.
3. End with a footer line: `_Updated for commit \`${{ github.event.pull_request.head.sha || github.event.workflow_run.head_sha }}\` (short: \`$(echo "${{ github.event.pull_request.head.sha || github.event.workflow_run.head_sha }}" | cut -c1-7)\`) at $(date -u '+%Y-%m-%d %H:%M UTC')._`

Use the Write tool. Do not run `gh pr comment`.
claude_args: '--model claude-sonnet-4-6 --allowed-tools "Read,Glob,Grep,Agent,Write,Bash(python3:*),Bash(gh pr view:*),Bash(gh pr diff:*),Bash(date:*)"'

- name: Find existing social review comment
if: steps.gate.outputs.should_skip != 'true' && steps.check.outputs.needs_review == 'true'
id: find-social-comment
uses: peter-evans/find-comment@v3
with:
issue-number: ${{ steps.pr-info.outputs.number }}
body-includes: '<!-- social-review -->'
direction: last

- name: Post or update social review comment
if: steps.gate.outputs.should_skip != 'true' && steps.check.outputs.needs_review == 'true'
uses: peter-evans/create-or-update-comment@v4
with:
issue-number: ${{ steps.pr-info.outputs.number }}
comment-id: ${{ steps.find-social-comment.outputs.comment-id }}
body-path: .social-review.md
edit-mode: replace

- name: Fail if copy exceeds character limits
if: steps.gate.outputs.should_skip != 'true' && steps.check.outputs.has_errors == 'true'
Expand Down
Loading