From 98c7a3e91f554b6c408f66d3fc8780cbd5eda5f1 Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Mon, 2 Nov 2026 16:48:52 -0500 Subject: [PATCH] Add a GitHub Actions workflow that reviews pull requests 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 Signed-off-by: Chuck Lever --- .github/workflows/code-review.yml | 72 +++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 .github/workflows/code-review.yml diff --git a/.github/workflows/code-review.yml b/.github/workflows/code-review.yml new file mode 100644 index 0000000..a32d4fb --- /dev/null +++ b/.github/workflows/code-review.yml @@ -0,0 +1,72 @@ +name: code-review + +on: + pull_request: + # Review a pull request when it opens or becomes ready, and again + # after each push to it. + types: [opened, reopened, ready_for_review, synchronize] + +permissions: + contents: read + pull-requests: write + +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number }} + cancel-in-progress: true + +jobs: + review: + # GitHub withholds repository secrets from pull requests opened + # from a fork, so the review runs only on branches pushed to + # this repository. + if: >- + github.event.pull_request.draft == false && + github.event.pull_request.head.repo.full_name == github.repository + runs-on: ubuntu-latest + timeout-minutes: 30 + steps: + # Full history, so the review can walk each commit in the PR. + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + # The action does not run a slash command given as its prompt + # (anthropics/claude-code-action#1003), so the prompt asks Claude + # to invoke the skill through the Skill tool instead. + - uses: anthropics/claude-code-action@d535f5172dec02b204866b393d6b20b9b2aaf98d # v1.0.266 + id: review + with: + anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} + 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 }}". + 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" + + # A run in which Claude never invokes the skill still exits + # successfully, with no review posted. Fail the job when the + # execution log holds no Skill tool call. + - name: Check that the review ran + env: + EXECUTION_FILE: ${{ steps.review.outputs.execution_file }} + run: | + if ! jq -e '[.[] | select(.type == "assistant") + | .message.content[]? + | select(.type == "tool_use" and .name == "Skill")] + | length > 0' "$EXECUTION_FILE" > /dev/null; then + echo "::error::Claude did not invoke the code-review skill" + exit 1 + fi + + # The action hides Claude's output, so a failed run otherwise + # leaves no error text. Print only the final result message. + - name: Show why the review failed + if: failure() && steps.review.outputs.execution_file != '' + env: + EXECUTION_FILE: ${{ steps.review.outputs.execution_file }} + run: | + jq -r '.[] | select(.type == "result") | .result // empty' \ + "$EXECUTION_FILE"