Skip to content
Merged
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
47 changes: 47 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ Based on the original work from [anthropics/claude-code-security-review](https:/

## Quick Start

### Basic Setup (Default GitHub Token)

Add this to your repository's `.github/workflows/code-review.yml`:

```yaml
Expand Down Expand Up @@ -51,6 +53,50 @@ jobs:
require-label: 'READY TO REVIEW' # If this isn't set, the action will trigger any time *any* label is applied
```

### GitHub App Setup (Recommended for Organizations)

For custom bot name/avatar and better mention detection:

```yaml
name: Code Review

permissions:
pull-requests: write
contents: read

on:
pull_request:
types: [opened, synchronize, reopened, labeled, review_requested]
issue_comment:
types: [created]

jobs:
review:
runs-on: ubuntu-latest
if: github.event_name == 'pull_request' || (github.event_name == 'issue_comment' && github.event.issue.pull_request)
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha || github.sha }}
fetch-depth: 2

- name: Generate App Token
id: app-token
uses: actions/create-github-app-token@v1.9.0
with:
app-id: ${{ secrets.CODE_REVIEW_APP_ID }}
private-key: ${{ secrets.CODE_REVIEW_APP_PRIVATE_KEY }}

- uses: PSPDFKit-labs/nutrient-code-review@main
with:
claude-api-key: ${{ secrets.CLAUDE_API_KEY }}
app-slug: ${{ steps.app-token.outputs.app-slug }}
env:
GITHUB_TOKEN: ${{ steps.app-token.outputs.token }}
```

**Note**: The `app-slug` parameter enables the bot to detect when it's mentioned in PR comments (e.g., `@my-code-review-app`). Requires `actions/create-github-app-token@v1.9.0` or later.

## Security Considerations

This action is not hardened against prompt injection attacks and should only be used to review trusted PRs. We recommend [configuring your repository](https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/enabling-features-for-your-repository/managing-github-actions-settings-for-a-repository#controlling-changes-from-forks-to-workflows-in-public-repositories) to use the "Require approval for all external contributors" option to ensure workflows only run after a maintainer has reviewed the PR.
Expand Down Expand Up @@ -79,6 +125,7 @@ This action is not hardened against prompt injection attacks and should only be
| `custom-security-scan-instructions` | Path to custom security scan instructions text file to append to the security section | None | No |
| `dismiss-stale-reviews` | Dismiss previous bot reviews when posting a new review (useful for follow-up commits) | `true` | No |
| `skip-draft-prs` | Skip code review on draft pull requests | `true` | No |
| `app-slug` | GitHub App slug for bot mention detection. If using `actions/create-github-app-token@v1.9.0+`, pass `${{ steps.app-token.outputs.app-slug }}`. Otherwise defaults to `github-actions`. | `github-actions` | No |
| `require-label` | Only run review if this label is present. Leave empty to review all PRs. Add `labeled` to your workflow `pull_request` types to trigger on label addition. | None | No |

### Action Outputs
Expand Down
54 changes: 10 additions & 44 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,11 @@ inputs:
required: false
default: 'true'

app-slug:
description: 'GitHub App slug for bot mentions (e.g., "my-code-review-app"). Defaults to "github-actions".'
required: false
default: 'github-actions'

require-label:
description: 'Only run review if this label is present on the PR. Leave empty to review all PRs. To trigger on label addition, add "labeled" to your workflow pull_request types.'
required: false
Expand Down Expand Up @@ -196,53 +201,14 @@ runs:
restore-keys: |
claudecode-${{ github.repository_id }}-pr-${{ github.event.pull_request.number || steps.pr-info.outputs.pr_number }}-

- name: Detect bot identity
id: bot-identity
shell: bash
env:
GH_TOKEN: ${{ env.GITHUB_TOKEN || github.token }}
GITHUB_REPOSITORY: ${{ github.repository }}
run: |
# Get authenticated user (the bot making API calls)
# Note: /user endpoint doesn't work with GitHub App tokens, so we try multiple methods
BOT_LOGIN=""

# Method 1: Try /user endpoint (works for PATs, not GitHub App tokens)
if [ -z "$BOT_LOGIN" ]; then
if BOT_LOGIN_TMP=$(gh api user --jq '.login' 2>/dev/null); then
BOT_LOGIN="$BOT_LOGIN_TMP"
echo "Detected bot via /user endpoint: $BOT_LOGIN"
fi
fi

# Method 2: Try /app endpoint (works for GitHub App tokens)
if [ -z "$BOT_LOGIN" ]; then
if APP_DATA=$(gh api app 2>/dev/null); then
APP_SLUG=$(echo "$APP_DATA" | jq -r '.slug // empty' 2>/dev/null)
if [ -n "$APP_SLUG" ] && [ "$APP_SLUG" != "null" ]; then
BOT_LOGIN="${APP_SLUG}[bot]"
echo "Detected bot via /app endpoint: $BOT_LOGIN"
fi
fi
fi

# Method 3: Fallback to default
if [ -z "$BOT_LOGIN" ]; then
BOT_LOGIN="github-actions"
echo "Using default bot identity: $BOT_LOGIN"
fi

echo "bot_login=$BOT_LOGIN" >> $GITHUB_OUTPUT
echo "Detected bot identity: $BOT_LOGIN"

- name: Detect trigger type
id: trigger-detection
shell: bash
env:
EVENT_NAME: ${{ github.event_name }}
EVENT_ACTION: ${{ github.event.action }}
COMMENT_BODY: ${{ github.event.comment.body }}
BOT_LOGIN: ${{ steps.bot-identity.outputs.bot_login }}
APP_SLUG: ${{ inputs.app-slug }}
run: |
TRIGGER_TYPE="unknown"

Expand All @@ -264,11 +230,11 @@ runs:
elif [ "$EVENT_NAME" == "issue_comment" ]; then
# Check if comment mentions this specific bot
# Escape special regex characters in bot login to prevent regex injection
if [ -n "$BOT_LOGIN" ]; then
ESCAPED_BOT=$(printf '%s\n' "$BOT_LOGIN" | sed 's/[]\/$*.^[]/\\&/g')
if [ -n "$APP_SLUG" ]; then
ESCAPED_BOT=$(printf '%s\n' "$APP_SLUG" | sed 's/[]\/$*.^[]/\\&/g')
if echo "$COMMENT_BODY" | grep -qE "@${ESCAPED_BOT}\\b"; then
TRIGGER_TYPE="mention"
echo "Detected mention of @$BOT_LOGIN in comment"
echo "Detected mention of @$APP_SLUG in comment"
fi
fi
fi
Expand Down Expand Up @@ -543,7 +509,7 @@ runs:
GH_TOKEN: ${{ env.GITHUB_TOKEN || github.token }}
GITHUB_REPOSITORY: ${{ github.repository }}
PR_NUMBER: ${{ github.event.pull_request.number || steps.pr-info.outputs.pr_number }}
BOT_LOGIN: ${{ steps.bot-identity.outputs.bot_login }}
BOT_LOGIN: ${{ inputs.app-slug }}[bot]
run: |
# Request the bot as a reviewer to make it appear in the PR's reviewer list
# This is optional and will fail silently if the bot is already a reviewer or doesn't have permissions
Expand Down