Compare commits

..

4 Commits

Author SHA1 Message Date
Ashwin Bhat
0c127307fa feat: improve PR review examples with context and tools (#504)
- Add PR repository and number to review prompts
- Note that PR branch is already checked out
- Update allowed tools to use inline comments and gh CLI
- Remove experimental review mode example in favor of standardized approach

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-authored-by: Claude <noreply@anthropic.com>
2025-08-28 09:02:27 -07:00
GitHub Actions
8a20581ed5 chore: bump Claude Code version to 1.0.96 2025-08-28 15:32:23 +00:00
GitHub Actions
a2ad6b7b4e chore: bump Claude Code version to 1.0.95 2025-08-28 01:26:35 +00:00
Ashwin Bhat
f0925925f1 fix: prevent test pollution by ensuring inputs are cloned (#499)
Always create a new object copy of defaultInputs to prevent mutations from affecting other tests.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-authored-by: Claude <noreply@anthropic.com>
2025-08-27 17:14:28 -07:00
9 changed files with 33 additions and 81 deletions

View File

@@ -157,7 +157,7 @@ runs:
# Install Claude Code if no custom executable is provided # Install Claude Code if no custom executable is provided
if [ -z "${{ inputs.path_to_claude_code_executable }}" ]; then if [ -z "${{ inputs.path_to_claude_code_executable }}" ]; then
echo "Installing Claude Code..." echo "Installing Claude Code..."
curl -fsSL https://claude.ai/install.sh | bash -s 1.0.93 curl -fsSL https://claude.ai/install.sh | bash -s 1.0.96
echo "$HOME/.local/bin" >> "$GITHUB_PATH" echo "$HOME/.local/bin" >> "$GITHUB_PATH"
else else
echo "Using custom Claude Code executable: ${{ inputs.path_to_claude_code_executable }}" echo "Using custom Claude Code executable: ${{ inputs.path_to_claude_code_executable }}"

View File

@@ -99,7 +99,7 @@ runs:
run: | run: |
if [ -z "${{ inputs.path_to_claude_code_executable }}" ]; then if [ -z "${{ inputs.path_to_claude_code_executable }}" ]; then
echo "Installing Claude Code..." echo "Installing Claude Code..."
curl -fsSL https://claude.ai/install.sh | bash -s 1.0.93 curl -fsSL https://claude.ai/install.sh | bash -s 1.0.96
else else
echo "Using custom Claude Code executable: ${{ inputs.path_to_claude_code_executable }}" echo "Using custom Claude Code executable: ${{ inputs.path_to_claude_code_executable }}"
# Add the directory containing the custom executable to PATH # Add the directory containing the custom executable to PATH

View File

@@ -22,7 +22,12 @@ jobs:
with: with:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
prompt: | prompt: |
Please review this pull request and provide comprehensive feedback. REPO: ${{ github.repository }}
PR NUMBER: ${{ github.event.pull_request.number }}
Please review this pull request.
Note: The PR branch is already checked out in the current working directory.
Focus on: Focus on:
- Code quality and best practices - Code quality and best practices
@@ -34,7 +39,10 @@ jobs:
- Verify that README.md and docs are updated for any new features or config changes - Verify that README.md and docs are updated for any new features or config changes
Provide constructive feedback with specific suggestions for improvement. Provide constructive feedback with specific suggestions for improvement.
Use inline comments to highlight specific areas of concern. Use `gh pr comment:*` for top-level comments.
Use `mcp__github_inline_comment__create_inline_comment` to highlight specific areas of concern.
Only your GitHub comments that you post will be seen, so don't submit your review as a normal message, just as comments.
If the PR has already been reviewed, or there are no noteworthy changes, don't post anything.
claude_args: | claude_args: |
--allowedTools "mcp__github__create_pending_pull_request_review,mcp__github__add_comment_to_pending_review,mcp__github__submit_pending_pull_request_review,mcp__github__get_pull_request_diff" --allowedTools "mcp__github_inline_comment__create_inline_comment,Bash(gh pr comment:*), Bash(gh pr diff:*), Bash(gh pr view:*)"

View File

@@ -1,45 +0,0 @@
name: Claude Experimental Review Mode
on:
pull_request:
types: [opened, synchronize]
issue_comment:
types: [created]
jobs:
code-review:
# Run on PR events, or when someone comments "@claude review" on a PR
if: |
github.event_name == 'pull_request' ||
(github.event_name == 'issue_comment' &&
github.event.issue.pull_request &&
contains(github.event.comment.body, '@claude review'))
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
issues: write
id-token: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0 # Full history for better diff analysis
- name: Code Review with Claude
uses: anthropics/claude-code-action@v1-dev
with:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
# github_token not needed - uses default GITHUB_TOKEN for GitHub operations
prompt: |
Review this pull request comprehensively.
Focus on:
- Code quality and maintainability
- Security vulnerabilities
- Performance issues
- Best practices and design patterns
- Test coverage gaps
Be constructive and provide specific suggestions for improvements.
Use GitHub's suggestion format when proposing code changes.

View File

@@ -28,7 +28,13 @@ jobs:
with: with:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
prompt: | prompt: |
REPO: ${{ github.repository }}
PR NUMBER: ${{ github.event.pull_request.number }}
Please review this pull request focusing on the changed files. Please review this pull request focusing on the changed files.
Note: The PR branch is already checked out in the current working directory.
Provide feedback on: Provide feedback on:
- Code quality and adherence to best practices - Code quality and adherence to best practices
- Potential bugs or edge cases - Potential bugs or edge cases
@@ -38,3 +44,6 @@ jobs:
Since this PR touches critical source code paths, please be thorough Since this PR touches critical source code paths, please be thorough
in your review and provide inline comments where appropriate. in your review and provide inline comments where appropriate.
claude_args: |
--allowedTools "mcp__github_inline_comment__create_inline_comment,Bash(gh pr comment:*), Bash(gh pr diff:*), Bash(gh pr view:*)"

View File

@@ -27,8 +27,13 @@ jobs:
with: with:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
prompt: | prompt: |
REPO: ${{ github.repository }}
PR NUMBER: ${{ github.event.pull_request.number }}
Please provide a thorough review of this pull request. Please provide a thorough review of this pull request.
Note: The PR branch is already checked out in the current working directory.
Since this is from a specific author that requires careful review, Since this is from a specific author that requires careful review,
please pay extra attention to: please pay extra attention to:
- Adherence to project coding standards - Adherence to project coding standards
@@ -38,3 +43,6 @@ jobs:
- Documentation - Documentation
Provide detailed feedback and suggestions for improvement. Provide detailed feedback and suggestions for improvement.
claude_args: |
--allowedTools "mcp__github_inline_comment__create_inline_comment,Bash(gh pr comment:*), Bash(gh pr diff:*), Bash(gh pr view:*)"

View File

@@ -12,23 +12,10 @@ import {
import type { ParsedGitHubContext } from "../context"; import type { ParsedGitHubContext } from "../context";
export function checkContainsTrigger(context: ParsedGitHubContext): boolean { export function checkContainsTrigger(context: ParsedGitHubContext): boolean {
console.log("checkContainsTrigger called with context:", {
eventName: context.eventName,
eventAction: context.eventAction,
inputs: context.inputs,
});
const { const {
inputs: { assigneeTrigger, labelTrigger, triggerPhrase, prompt }, inputs: { assigneeTrigger, labelTrigger, triggerPhrase, prompt },
} = context; } = context;
console.log("Extracted inputs:", {
assigneeTrigger,
labelTrigger,
triggerPhrase,
prompt,
});
// If prompt is provided, always trigger // If prompt is provided, always trigger
if (prompt) { if (prompt) {
console.log(`Prompt provided, triggering action`); console.log(`Prompt provided, triggering action`);
@@ -59,21 +46,15 @@ export function checkContainsTrigger(context: ParsedGitHubContext): boolean {
// Check for issue body and title trigger on issue creation // Check for issue body and title trigger on issue creation
if (isIssuesEvent(context) && context.eventAction === "opened") { if (isIssuesEvent(context) && context.eventAction === "opened") {
console.log("Checking issue opened trigger");
const issueBody = context.payload.issue.body || ""; const issueBody = context.payload.issue.body || "";
const issueTitle = context.payload.issue.title || ""; const issueTitle = context.payload.issue.title || "";
console.log("Issue content:", { issueBody, issueTitle });
// Check for exact match with word boundaries or punctuation // Check for exact match with word boundaries or punctuation
const regex = new RegExp( const regex = new RegExp(
`(^|\\s)${escapeRegExp(triggerPhrase)}([\\s.,!?;:]|$)`, `(^|\\s)${escapeRegExp(triggerPhrase)}([\\s.,!?;:]|$)`,
); );
console.log("Regex pattern:", regex.toString());
// Check in body // Check in body
const bodyMatch = regex.test(issueBody); if (regex.test(issueBody)) {
console.log("Body match result:", bodyMatch);
if (bodyMatch) {
console.log( console.log(
`Issue body contains exact trigger phrase '${triggerPhrase}'`, `Issue body contains exact trigger phrase '${triggerPhrase}'`,
); );
@@ -81,9 +62,7 @@ export function checkContainsTrigger(context: ParsedGitHubContext): boolean {
} }
// Check in title // Check in title
const titleMatch = regex.test(issueTitle); if (regex.test(issueTitle)) {
console.log("Title match result:", titleMatch);
if (titleMatch) {
console.log( console.log(
`Issue title contains exact trigger phrase '${triggerPhrase}'`, `Issue title contains exact trigger phrase '${triggerPhrase}'`,
); );
@@ -154,7 +133,6 @@ export function checkContainsTrigger(context: ParsedGitHubContext): boolean {
} }
console.log(`No trigger was met for ${triggerPhrase}`); console.log(`No trigger was met for ${triggerPhrase}`);
console.log("Returning false from checkContainsTrigger");
return false; return false;
} }

View File

@@ -24,16 +24,11 @@ export const tagMode: Mode = {
description: "Traditional implementation mode triggered by @claude mentions", description: "Traditional implementation mode triggered by @claude mentions",
shouldTrigger(context) { shouldTrigger(context) {
console.log("tagMode.shouldTrigger called");
// Tag mode only handles entity events // Tag mode only handles entity events
if (!isEntityContext(context)) { if (!isEntityContext(context)) {
console.log("Not entity context, returning false");
return false; return false;
} }
console.log("Is entity context, calling checkContainsTrigger"); return checkContainsTrigger(context);
const result = checkContainsTrigger(context);
console.log("checkContainsTrigger returned:", result);
return result;
}, },
prepareContext(context, data) { prepareContext(context, data) {

View File

@@ -23,7 +23,6 @@ describe("Tag Mode", () => {
}); });
test("shouldTrigger delegates to checkContainsTrigger", () => { test("shouldTrigger delegates to checkContainsTrigger", () => {
console.log("enter test");
const contextWithTrigger = createMockContext({ const contextWithTrigger = createMockContext({
eventName: "issue_comment", eventName: "issue_comment",
isPR: false, isPR: false,