Skip to content

Add a GitHub Actions workflow that reviews pull requests - #8

Merged
chucklever merged 1 commit into
testingfrom
claude-review
Nov 2, 2026
Merged

chucklever merged 1 commit into
testingfrom
claude-review

Conversation

@chucklever

Copy link
Copy Markdown
Collaborator

Opening this pull request is the workflow's first run. GitHub takes a
pull_request workflow from the pull request's merge commit, so the
review of this patch tests the setup before the workflow lands on
testing.

The allowed-tools list is a guess at what /code-review --comment uses
to post on GitHub. A missing tool shows up in the job log as a denied
call.

The job runs Claude Sonnet 5.5 and is meant to catch Python
correctness bugs. A separate reviewer for NFSv4 protocol conformance
is planned.

claude_args: >-
--model claude-sonnet-5-5
--allowedTools
"Skill,Read,Grep,Glob,Agent,Bash(git log:*),Bash(git show:*),Bash(git diff:*),Bash(git blame:*),Bash(gh pr view:*),Bash(gh pr diff:*),Bash(gh pr comment:*),Bash(gh api:*),mcp__github_inline_comment__create_inline_comment"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Bash(gh api:*) lets the model make any GitHub REST call, not just post review comments. The job's GITHUB_TOKEN has pull-requests: write, and the model reads untrusted PR content (diff, commit messages, PR text). A prompt injection there could run gh api -X PATCH/DELETE against the PR or other people's comments, or approve the PR through the reviews endpoint. Consider a narrower allowlist, such as gh api repos/*/pulls/*/comments plus the inline-comment MCP tool.

Comment thread .github/workflows/code-review.yml Outdated

on:
pull_request:
types: [opened, reopened, ready_for_review]

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

The trigger omits synchronize, so commits pushed after the PR opens are never reviewed. A follow-up push, including a buggy rewrite, gets no review. The cancel-in-progress setting also does nothing for pushes. If reviewing only the first revision is deliberate, the comment should say so.

contents: read
pull-requests: write

concurrency:

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

The concurrency group is evaluated before the job's if:. A second event for the same PR (reopened, ready_for_review) can cancel a review in progress, and if that second run's job is then skipped, nothing replaces the cancelled review.

- uses: anthropics/claude-code-action@d535f5172dec02b204866b393d6b20b9b2aaf98d # v1.0.266
id: review
with:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

The if: only excludes fork PRs. For Dependabot PRs on branches in this repo, GitHub withholds Actions secrets, so secrets.ANTHROPIC_API_KEY is empty and the action errors, leaving a red check on every dependency bump. Consider also skipping github.actor == 'dependabot[bot]', or checking that the secret is non-empty.

github_token: ${{ secrets.GITHUB_TOKEN }}
prompt: >-
Use the Skill tool to run the code-review skill with the
arguments "high --comment ${{ github.event.pull_request.number }}".

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

The workflow works around claude-code-action#1003 by asking the model to call the Skill tool. If the model skips the call or mangles the arguments, the run still exits successfully, so the review can silently post nothing. No step checks that a comment was actually created.

claude_args: >-
--model claude-sonnet-5-5
--allowedTools
"Skill,Read,Grep,Glob,Agent,Bash(git log:*),Bash(git show:*),Bash(git diff:*),Bash(git blame:*),Bash(gh pr view:*),Bash(gh pr diff:*),Bash(gh pr comment:*),Bash(gh api:*),mcp__github_inline_comment__create_inline_comment"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Bash(gh api:*) is an unrestricted gh api, so the model can make any REST call, including writes and --method overrides, with the job's pull-requests: write token. That token can approve, dismiss, or close PRs. The PR title, body, and diff are untrusted input to the model, so a prompt injection can use this. Nothing here needs more than gh pr view, gh pr diff, and the inline-comment tool. Drop gh api:*, or narrow it to the specific read-only endpoints the skill uses.

env:
EXECUTION_FILE: ${{ steps.review.outputs.execution_file }}
run: |
if ! jq -e '[.[] | select(.type == "assistant")

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

This check only confirms that a Skill tool_use block exists. It does not check that the call succeeded, that it named code-review, or that any comment was posted. If the skill is missing or the call returns an error, the job still goes green and no review appears, which is the failure this step is meant to catch. Also require a matching tool_result without is_error, and .input.skill == "code-review".

# this repository.
if: >-
github.event.pull_request.draft == false &&
github.event.pull_request.head.repo.full_name == github.repository

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

The same-repo check does not cover PRs opened by Dependabot. For those, pull_request runs get no repository secrets, so secrets.ANTHROPIC_API_KEY is empty and the job fails. Add github.actor != 'dependabot[bot]' to the condition, or skip the job when the secret is empty.

Comment thread .github/workflows/code-review.yml Outdated
# Review a pull request once, when it opens or becomes ready. A
# push to an open pull request does not start another review.
# Reopening the pull request does.
types: [opened, reopened, ready_for_review]

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Combined with cancel-in-progress: true (line 16), this means a review in progress is cancelled whenever the PR is reopened or marked ready, and nothing later re-triggers it. The run is cancelled mid-review and the check step never runs. That can leave partial or missing inline comments with no failure signal. Consider cancel-in-progress: false, or accept the cancellation explicitly. Also note that pushes never trigger a re-review, so later commits to the PR go unreviewed.

The build and knfsd workflows catch a change that breaks the build or
fails against NFSD. They do not catch a test that passes when it
should fail: a check made against the wrong delegation, a branch that
cannot be reached, a cleanup CLOSE whose status goes unread. Recent
commits on testing fix all three in existing tests.

Run Claude Code's /code-review at high effort when a pull request is
opened, reopened, marked ready for review, or updated by a push, and
post the findings as inline comments on the pull request. The job
reads the ANTHROPIC_API_KEY repository secret. GitHub withholds
secrets from a pull request opened from a fork, so the job skips a
fork's pull request. A push that arrives while a review is running
cancels the review of the previous head.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Chuck Lever <cel@kernel.org>
@chucklever chucklever changed the title Add a GitHub Actions workflow that reviews each new pull request Add a GitHub Actions workflow that reviews pull requests Nov 2, 2026
@chucklever
chucklever merged commit 4cff334 into testing Nov 2, 2026
8 of 9 checks passed
@chucklever
chucklever deleted the claude-review branch November 2, 2026 23:36
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.

1 participant