Skip to content

ci: post Claude reviews from execution_file; fix general_review filter#145

Merged
loothero merged 3 commits into
mainfrom
ci/fix-claude-comment-posting
May 3, 2026
Merged

ci: post Claude reviews from execution_file; fix general_review filter#145
loothero merged 3 commits into
mainfrom
ci/fix-claude-comment-posting

Conversation

@loothero
Copy link
Copy Markdown
Member

@loothero loothero commented May 3, 2026

Summary

Two CI workflow fixes uncovered while testing PR #144 (run 25278577961).

Fix 1 — Claude jobs ran but never posted comments

In claude-code-action v1, prompt: (automation) mode does not auto-post a PR comment the way the beta direct_prompt: did. Each of our four Claude review jobs ran cleanly (is_error: false, --model claude-opus-4-7 confirmed), produced a review, then the polling step timed out for 60s and failed the job because no comment ever appeared.

Replace the comment-polling pattern (gh api … | jq with 6×10s retries and 2–4 fallback queries) with the capture-extract-post-check sequence already used by the Codex jobs:

  1. id: claude on the action step exposes execution_file (Claude Code stream-JSON).
  2. New Extract review output step pulls the final result.result text (or falls back to assistant text) into /tmp/review.txt.
  3. New Post review comment step writes ## Claude Review - … + body to the PR via gh pr comment.
  4. Check for blocking findings greps the local file for [CRITICAL]/[HIGH].

Net: review comments appear immediately, blocking-check is deterministic, and the 4 Claude jobs now mirror the 4 Codex jobs structurally.

Fix 2 — general_review triggered on scoped-only changes

PR #144 changed only api/README.md, client/README.md, contracts/README.md — all inside excluded scopes — yet claude-review-general and codex-review-general ran. dorny/paths-filter v3's OR-list semantics don't reliably honor ! negations against a leading ** glob.

Replace:

general_review:
  - "**"
  - "!contracts/**"
  - "!client/**"
  - "!indexer/**"
  - "!api/**"

with a shell step that computes general_review from gh pr diff --name-only — true iff the PR touches a file outside contracts/, client/, indexer/, or api/. The four scoped filters (contracts_review, client_review, indexer_api_review) continue to use paths-filter (no negations there).

Test plan

  • CI green on this PR (modifies pr-ci.yml, so AI reviews are gated off via review_automation_modified — only the deterministic jobs run)
  • After merge, retest by re-running PR test: trigger Claude reviews across api/client/contracts scopes #144 (or push a synchronize commit). Expected: 4 Claude comments + 4 Codex comments, no *-general jobs run, pr-ci passes.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Chores
    • Updated code review workflow automation to improve review extraction and processing efficiency.

Note: This is an internal infrastructure change with no direct impact on end-user functionality.

…lter

Two fixes after observing PR #144 CI run (run 25278577961):

1. Claude review jobs ran successfully but never posted PR comments. In
   claude-code-action v1, `prompt:` automation mode does not auto-post a
   comment the way the beta `direct_prompt:` did — that behavior is gone.
   Replace the comment-polling step with capture-extract-post-check using
   the action's `execution_file` output (Claude Code stream-JSON), mirroring
   the existing Codex flow. Removes 6×10s sleep loop and 4-fallback gh-api
   queries; review now appears immediately and the blocking-findings check
   greps a local file.

2. `claude-review-general` and `codex-review-general` triggered on PR #144
   despite all changed files being inside excluded scopes. dorny/paths-filter
   v3 OR-list semantics don't reliably honor `!` negations against a leading
   `**` glob. Replace the negation-based filter with a shell step that
   computes `general_review` from `gh pr diff --name-only`, true iff at
   least one file lives outside contracts/, client/, indexer/, api/.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings May 3, 2026 12:14
@gemini-code-assist
Copy link
Copy Markdown

Note

Gemini is unable to generate a review for this pull request due to the file types involved not being currently supported.

@vercel
Copy link
Copy Markdown

vercel Bot commented May 3, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
summit Ready Ready Preview, Comment May 3, 2026 0:26am

Request Review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 3, 2026

Caution

Review failed

Pull request was closed or merged during review

📝 Walkthrough

Walkthrough

GitHub Actions workflow for AI-based code reviews is refactored. The general_review detection switches from exclude-pattern paths-filter to gh pr diff command. All Claude review jobs now extract review text directly from the action's execution_file via jq into /tmp/review.txt, post that comment, and check for critical findings in the file instead of polling prior PR comments.

Changes

AI Review Workflow Refactor

Layer / File(s) Summary
Review Detection Logic
.github/workflows/pr-ci.yml (lines 41–82)
general_review output changed from paths-filter exclude patterns (!contracts/**, !client/**, !indexer/**, !api/**) to gh pr diff --name-only | grep check that sets general_review=true when files exist outside those four directories.
Claude Output Extraction
.github/workflows/pr-ci.yml (lines 487–547, 731–791, 975–1035, 1223–1283)
All four Claude review jobs (claude-review-contracts, claude-review-client, claude-review-indexer-api, claude-review-general) now extract review text from the anthropics/claude-code-action execution_file using jq and write to /tmp/review.txt, replacing prior ad-hoc output handling.
Review Comment Posting
.github/workflows/pr-ci.yml (lines 487–547, 731–791, 975–1035, 1223–1283)
Each Claude job posts a comment from /tmp/review.txt (or displays "No review output…" if the file is empty), simplifying prior comment-creation logic.
Blocking Findings Detection
.github/workflows/pr-ci.yml (lines 487–547, 731–791, 975–1035, 1223–1283)
All four review jobs replace the prior API-based PR comment fetching/pagination/marker logic with a direct grep check: job fails if /tmp/review.txt is missing or contains [(CRITICAL|HIGH)] patterns.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Possibly related PRs

Poem

🐰 Hops through the CI with glee,
jq extracts the review from /tmp so free,
No more comment-chasing through the API night,
Direct posting and grep checks—clean and tight!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Description check ❓ Inconclusive The description provides comprehensive details (Fix 1 and Fix 2) with technical implementation steps and a test plan, but omits the required template structure including Scope, Change Type, Validation commands, Risk level, and other sections. Complete the missing template sections: mark Scope (Other/chore/infra), Change Type (fix + chore), provide validation commands, specify Risk level (Low), and fill in Assumptions and Exceptions as applicable.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately and concisely summarizes the main changes: fixing Claude review posting from execution_file and correcting the general_review filter logic.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch ci/fix-claude-comment-posting

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
Review rate limit: 0/1 reviews remaining, refill in 60 minutes.

Comment @coderabbitai help to get the list of available commands and usage tips.

@railway-app
Copy link
Copy Markdown

railway-app Bot commented May 3, 2026

🚅 Deployed to the summit-pr-145 environment in Summit

3 services not affected by this PR
  • summit-db
  • summit-indexer
  • summit-api

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 310433e28e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread .github/workflows/pr-ci.yml Outdated
Comment on lines +511 to +513
if [ -z "$EXECUTION_FILE" ] || [ ! -f "$EXECUTION_FILE" ]; then
echo "Claude action did not produce an execution file." > /tmp/review.txt
exit 0
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Fail when Claude execution output is unavailable

If steps.claude.outputs.execution_file is missing or unreadable, this step writes a placeholder message to /tmp/review.txt and exits successfully, and the later gate only checks that the file is non-empty. In that scenario the Claude review job can pass without any real model output, so PRs may merge with review enforcement silently bypassed across all claude-review-* jobs that use this pattern.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Accepted — real bug. The placeholder strings made /tmp/review.txt non-empty, so the [ ! -s … ] blocking-check passed and the job could merge with no real review.

Fixed in c3a2acb: both fallback branches (missing/unreadable execution_file, empty extracted text) now emit ::error::, leave /tmp/review.txt empty, and exit 1. The Post review comment step (if: always()) still runs so reviewers see the "No review output was produced." fallback comment on the PR, and the blocking-check then fails on the empty file.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Updates the PR CI workflow to (1) reliably post Claude review comments by extracting text from the Claude action execution_file, and (2) fix general_review detection so “general” AI review jobs don’t run on scoped-only changes.

Changes:

  • Replace Claude review “poll for comment” logic with an extract → post-comment → local blocking-grep flow.
  • Compute general_review explicitly via gh pr diff --name-only instead of paths-filter negations.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

| jq -r --arg run_token "run=${{ github.run_id }}" --arg sha_token "sha=${{ github.event.pull_request.head.sha }}" \
'[.[] | select((.user.login // "") == "claude" and ((.body // "") | contains($run_token) and contains($sha_token) and contains("scope=indexer-api")))] | last | .body // ""')
fi
REVIEW=$(jq -r 'select(.type == "result") | .result // empty' "$EXECUTION_FILE" 2>/dev/null | tail -1)
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Going to pass on this one — the comment Copilot is paraphrasing isn't actually in the file. The block comment didn't say result.result, and it was removed in f09ca84 anyway.

On the substance: Claude Code stream-JSON's terminal message is {"type":"result","is_error":false,"result":"<final assistant text>",...} where .result is a string holding the model's final output. Verified empirically against PR #144 run 25278577961. result.result would resolve to null. The fallback over type:"assistant" text content already covers any future envelope-shape change, and the silent-pass fix in c3a2acb ensures unparseable output now fails the job rather than passing it.

Comment thread .github/workflows/pr-ci.yml Outdated
Comment on lines +1245 to +1246
echo "Claude action did not produce an execution file." > /tmp/review.txt
exit 0
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Accepted — real bug. The placeholder strings made /tmp/review.txt non-empty, so the [ ! -s … ] blocking-check passed and the job could merge with no real review.

Fixed in c3a2acb: both fallback branches (missing/unreadable execution_file, empty extracted text) now emit ::error::, leave /tmp/review.txt empty, and exit 1. The Post review comment step (if: always()) still runs so reviewers see the "No review output was produced." fallback comment on the PR, and the blocking-check then fails on the empty file.

echo "Found Claude review comment on attempt $i"
break
fi
REVIEW=$(jq -r 'select(.type == "result") | .result // empty' "$EXECUTION_FILE" 2>/dev/null | tail -1)
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Going to pass on this one — the comment Copilot is paraphrasing isn't actually in the file. The block comment didn't say result.result, and it was removed in f09ca84 anyway.

On the substance: Claude Code stream-JSON's terminal message is {"type":"result","is_error":false,"result":"<final assistant text>",...} where .result is a string holding the model's final output. Verified empirically against PR #144 run 25278577961. result.result would resolve to null. The fallback over type:"assistant" text content already covers any future envelope-shape change, and the silent-pass fix in c3a2acb ensures unparseable output now fails the job rather than passing it.

Comment thread .github/workflows/pr-ci.yml Outdated
Comment on lines +512 to +513
echo "Claude action did not produce an execution file." > /tmp/review.txt
exit 0
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Accepted — real bug. The placeholder strings made /tmp/review.txt non-empty, so the [ ! -s … ] blocking-check passed and the job could merge with no real review.

Fixed in c3a2acb: both fallback branches (missing/unreadable execution_file, empty extracted text) now emit ::error::, leave /tmp/review.txt empty, and exit 1. The Post review comment step (if: always()) still runs so reviewers see the "No review output was produced." fallback comment on the PR, and the blocking-check then fails on the empty file.

echo "Found Claude review comment on attempt $i"
break
fi
REVIEW=$(jq -r 'select(.type == "result") | .result // empty' "$EXECUTION_FILE" 2>/dev/null | tail -1)
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Going to pass on this one — the comment Copilot is paraphrasing isn't actually in the file. The block comment didn't say result.result, and it was removed in f09ca84 anyway.

On the substance: Claude Code stream-JSON's terminal message is {"type":"result","is_error":false,"result":"<final assistant text>",...} where .result is a string holding the model's final output. Verified empirically against PR #144 run 25278577961. result.result would resolve to null. The fallback over type:"assistant" text content already covers any future envelope-shape change, and the silent-pass fix in c3a2acb ensures unparseable output now fails the job rather than passing it.

Comment thread .github/workflows/pr-ci.yml Outdated
Comment on lines +756 to +757
echo "Claude action did not produce an execution file." > /tmp/review.txt
exit 0
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Accepted — real bug. The placeholder strings made /tmp/review.txt non-empty, so the [ ! -s … ] blocking-check passed and the job could merge with no real review.

Fixed in c3a2acb: both fallback branches (missing/unreadable execution_file, empty extracted text) now emit ::error::, leave /tmp/review.txt empty, and exit 1. The Post review comment step (if: always()) still runs so reviewers see the "No review output was produced." fallback comment on the PR, and the blocking-check then fails on the empty file.

echo "Found Claude review comment on attempt $i"
break
fi
REVIEW=$(jq -r 'select(.type == "result") | .result // empty' "$EXECUTION_FILE" 2>/dev/null | tail -1)
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Going to pass on this one — the comment Copilot is paraphrasing isn't actually in the file. The block comment didn't say result.result, and it was removed in f09ca84 anyway.

On the substance: Claude Code stream-JSON's terminal message is {"type":"result","is_error":false,"result":"<final assistant text>",...} where .result is a string holding the model's final output. Verified empirically against PR #144 run 25278577961. result.result would resolve to null. The fallback over type:"assistant" text content already covers any future envelope-shape change, and the silent-pass fix in c3a2acb ensures unparseable output now fails the job rather than passing it.

Comment thread .github/workflows/pr-ci.yml Outdated
Comment on lines +1000 to +1001
echo "Claude action did not produce an execution file." > /tmp/review.txt
exit 0
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Accepted — real bug. The placeholder strings made /tmp/review.txt non-empty, so the [ ! -s … ] blocking-check passed and the job could merge with no real review.

Fixed in c3a2acb: both fallback branches (missing/unreadable execution_file, empty extracted text) now emit ::error::, leave /tmp/review.txt empty, and exit 1. The Post review comment step (if: always()) still runs so reviewers see the "No review output was produced." fallback comment on the PR, and the blocking-check then fails on the empty file.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Previously the Extract review output step wrote a non-empty placeholder
("Claude action did not produce an execution file." / "Claude review did
not produce output.") to /tmp/review.txt and exited 0 when the action
produced no usable output. The downstream Check for blocking findings
gate uses `[ ! -s /tmp/review.txt ]`, so the placeholder satisfied it
and the job could pass without a real review — silently bypassing the
[CRITICAL]/[HIGH] enforcement that's the whole point of the gate.

Both branches now emit `::error::`, leave /tmp/review.txt empty, and
exit 1. The Post review comment step (if: always()) still runs and
posts the existing "No review output was produced." fallback so
reviewers see the failure on the PR.

Addresses Codex P1 + Copilot review findings on PR #145.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@loothero loothero merged commit 293c367 into main May 3, 2026
19 of 20 checks passed
@loothero loothero deleted the ci/fix-claude-comment-posting branch May 3, 2026 12:26
@railway-app railway-app Bot temporarily deployed to Summit / summit-pr-145 May 3, 2026 12:26 Destroyed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants