|
| 1 | +name: Claude Code - Automated PR Review |
| 2 | + |
| 3 | +on: |
| 4 | + pull_request: |
| 5 | + types: [opened, synchronize, ready_for_review, reopened] |
| 6 | + |
| 7 | +jobs: |
| 8 | + claude-review: |
| 9 | + if: >- |
| 10 | + contains(fromJSON('["OWNER","MEMBER","COLLABORATOR"]'), |
| 11 | + github.event.pull_request.author_association) |
| 12 | +
|
| 13 | + runs-on: ubuntu-latest |
| 14 | + |
| 15 | + permissions: |
| 16 | + contents: write |
| 17 | + pull-requests: write |
| 18 | + issues: write |
| 19 | + actions: read |
| 20 | + |
| 21 | + steps: |
| 22 | + - name: Checkout repository |
| 23 | + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 |
| 24 | + with: |
| 25 | + fetch-depth: 0 |
| 26 | + |
| 27 | + - name: Check run count |
| 28 | + id: check-runs |
| 29 | + env: |
| 30 | + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
| 31 | + REPO: ${{ github.repository }} |
| 32 | + HEAD_SHA: ${{ github.event.pull_request.head.sha }} |
| 33 | + EVENT_ACTION: ${{ github.event.action }} |
| 34 | + PR_NUMBER: ${{ github.event.pull_request.number }} |
| 35 | + run: | |
| 36 | + WORKFLOW_FILE="claude-code-review.yml" |
| 37 | +
|
| 38 | + RUN_COUNT=$(gh api \ |
| 39 | + -H "Accept: application/vnd.github+json" \ |
| 40 | + -H "X-GitHub-Api-Version: 2022-11-28" \ |
| 41 | + "repos/${REPO}/actions/workflows/${WORKFLOW_FILE}/runs?head_sha=${HEAD_SHA}&status=completed" \ |
| 42 | + --jq '[.workflow_runs[] | select(.event == "pull_request")] | length' || echo "") |
| 43 | +
|
| 44 | + RUN_COUNT=${RUN_COUNT:-0} |
| 45 | + if ! echo "$RUN_COUNT" | grep -qE '^[0-9]+$'; then |
| 46 | + echo "[WARN] Invalid RUN_COUNT value ('$RUN_COUNT') from GitHub API. Defaulting to 0." |
| 47 | + RUN_COUNT=0 |
| 48 | + fi |
| 49 | +
|
| 50 | + RUN_COUNT=$((RUN_COUNT + 1)) |
| 51 | +
|
| 52 | + echo "This is run #$RUN_COUNT for this PR (event: $EVENT_ACTION)" |
| 53 | +
|
| 54 | + if [ "$RUN_COUNT" -le 3 ]; then |
| 55 | + echo "should_run=true" >> $GITHUB_OUTPUT |
| 56 | + echo "[OK] Will run Claude review (run $RUN_COUNT of 3)" |
| 57 | + else |
| 58 | + echo "should_run=false" >> $GITHUB_OUTPUT |
| 59 | + echo "[SKIP] Skipping Claude review (already ran 3 times)" |
| 60 | + fi |
| 61 | +
|
| 62 | + - name: Run Claude Code Review |
| 63 | + if: steps.check-runs.outputs.should_run == 'true' |
| 64 | + uses: anthropics/claude-code-action@f64219702d7454cf29fe32a74104be6ed43dc637 # v1 |
| 65 | + with: |
| 66 | + claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} |
| 67 | + github_token: ${{ secrets.GITHUB_TOKEN }} |
| 68 | + model: claude-opus-4-6 |
| 69 | + use_commit_signing: true |
| 70 | + |
| 71 | + - name: Comment on PR (skipped) |
| 72 | + if: steps.check-runs.outputs.should_run == 'false' |
| 73 | + env: |
| 74 | + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
| 75 | + PR_NUMBER: ${{ github.event.pull_request.number }} |
| 76 | + run: | |
| 77 | + gh pr comment "$PR_NUMBER" --body "[INFO] Claude Code review was skipped as it has already run 3 times for this PR." |
0 commit comments