Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
ci: add Claude PR review action
Drops in the same claude-code-action setup used on the ShedOS repo.
Triggers on PR open/synchronize and on comments mentioning @claude.
Posts the review as a top-level PR comment via 'gh pr comment'.

Standards live in .github/CODE_REVIEW.md; per-repo specifics get
picked up from CLAUDE.md at the repo root if present.

Before merging, add the secret:

  gh secret set CLAUDE_CODE_OAUTH_TOKEN --repo fdsimoes-git/fitness-monitor-and-assistant \
    <<<"$CLAUDE_CODE_OAUTH_TOKEN"
  • Loading branch information
Felipe Simoes committed May 21, 2026
commit 7f3510df39a453c131f6b5361e1c9474f8b0c736
41 changes: 41 additions & 0 deletions .github/CODE_REVIEW.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Code Review Standards

You are reviewing a pull request. Be a senior engineer, not a linter.

## What to flag (in priority order)

1. **Correctness bugs** — logic errors, off-by-one, race conditions,
null/undefined paths, incorrect error handling, broken invariants.
2. **Security** — injection (SQL, command, prompt, shell), auth/authz
bypasses, secrets in code, unsafe deserialization, SSRF, missing
input validation on anything crossing a trust boundary.
3. **Breaking changes** — API/signature changes without callsite
updates, schema migrations without a rollback path, removed public
exports.
4. **Missing tests** — new branching logic or error paths without test
coverage. Don't ask for tests on pure refactors or trivial changes.
5. **Performance cliffs** — N+1 queries, unbounded loops over user
input, sync I/O in hot paths. Skip micro-optimizations.

## What NOT to flag

- Style/formatting (the linter handles it)
- Naming preferences unless genuinely misleading
- "Consider adding a comment here" unless the logic is non-obvious
- Speculative concerns ("this *could* break if...") without a concrete
path
- Anything you'd phrase as "nit:"

## How to comment

- One issue per comment, on the exact line
- State the problem, then the fix, in under 4 lines
- If you're not sure it's a real bug, say so explicitly or stay silent
- End with a summary comment listing only blocking issues, or
"No blocking issues."

## Project context

This repo's specific conventions and architecture live in `CLAUDE.md`
at the repo root (if present) — read that first and apply its rules
on top of the standards above.
81 changes: 81 additions & 0 deletions .github/workflows/claude-review.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
name: Claude PR Review

on:
pull_request:
types: [opened, synchronize]
# Comment events fire on every comment — the job's `if:` clause below
# filters to @claude mentions only so we don't spin up a fresh review
# (~$0.50-1.50 each) for every CodeQL / Copilot / bot comment.
issue_comment:
types: [created]
pull_request_review_comment:
types: [created]

permissions:
contents: read
pull-requests: write
issues: write
id-token: write

jobs:
review:
runs-on: ubuntu-latest
timeout-minutes: 15
if: |
github.event_name == 'pull_request' ||
(github.event_name == 'issue_comment' &&
github.event.issue.pull_request != null &&
contains(github.event.comment.body, '@claude')) ||
(github.event_name == 'pull_request_review_comment' &&
contains(github.event.comment.body, '@claude'))
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0

- uses: anthropics/claude-code-action@v1
env:
# Auth for the `gh pr comment` call Claude makes via the Bash
# tool. The action's own posting paths (use_sticky_comment,
# MCP inline-comment buffer) both completed `success` but
# posted nothing visible across multiple iterations — see
# PRs #8 / #9 / #10 — so we shell out to `gh` instead.
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
# Reveal Claude's tool calls in the run log. Without this the
# SDK hides everything and silent failures are invisible.
show_full_output: true
prompt: |
Review PR #${{ github.event.pull_request.number }} of
${{ github.repository }}. Read CLAUDE.md and
.github/CODE_REVIEW.md if present and follow their
standards. Focus on: correctness bugs, security issues,
missing error handling, missing tests, and breaking
changes for callers. Be specific and terse.

POST the review by running this exact command via the Bash
tool (no other path will reach the PR — the action's
built-in posting mechanism does not work for us):

cat <<'REVIEW_EOF' > /tmp/review.md
<YOUR MARKDOWN REVIEW HERE>
REVIEW_EOF
gh pr comment ${{ github.event.pull_request.number }} \
--body-file /tmp/review.md
Comment on lines +50 to +65

Format the review body as either:
- "## Blocking issues" followed by a bulleted list:
`path:line` — the problem, the fix (one bullet per
issue, under 4 lines each), OR
- "No blocking issues." on its own line.
Then a one-paragraph summary of what the PR does plus
any non-blocking observations.

Always post the comment, even when there are no blocking
issues — silence is not acceptable; the PR author needs
to see that the review ran.
claude_args: |
--model claude-opus-4-7
--max-turns 30
--allowedTools Read,Grep,Glob,Bash
Loading