Repository navigation
Add a GitHub Actions workflow that reviews pull requests - #8
Conversation
b29e3ea to
a9e003f
Compare
a9e003f to
c5ed380
Compare
a9e003f to
c5ed380
Compare
fbed011 to
c5ed380
Compare
0d77edd to
c5ed380
Compare
| 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" |
There was a problem hiding this comment.
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.
|
|
||
| on: | ||
| pull_request: | ||
| types: [opened, reopened, ready_for_review] |
There was a problem hiding this comment.
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: |
There was a problem hiding this comment.
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 }} |
There was a problem hiding this comment.
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 }}". |
There was a problem hiding this comment.
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.
c5ed380 to
d281974
Compare
| 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" |
There was a problem hiding this comment.
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") |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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.
| # 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] |
There was a problem hiding this comment.
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>
d281974 to
98c7a3e
Compare
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.