Skip to content

feat: add support for aws_backup_global_settings #221

feat: add support for aws_backup_global_settings

feat: add support for aws_backup_global_settings #221

name: Claude Code Review
on:
# Comment-based triggers (like Cursor's Bugbot)
issue_comment:
types: [created]
pull_request_review_comment:
types: [created]
pull_request:
types: [opened, synchronize]
# Manual triggers via GitHub CLI
workflow_dispatch:
inputs:
review_mode:
description: 'Review mode to use'
required: false
default: 'hunt'
type: choice
options:
- hunt
- analyze
- security
- performance
- review
focus:
description: 'Focus areas (comma-separated)'
required: false
default: 'bugs,security,performance'
type: string
verbose:
description: 'Enable verbose output'
required: false
default: false
type: boolean
jobs:
# Handle workflow_dispatch by creating a comment to trigger Claude
dispatch-trigger:
if: github.event_name == 'workflow_dispatch'
runs-on: ubuntu-latest
timeout-minutes: 5
permissions:
pull-requests: write
issues: write
steps:
- name: Find open PR
id: find-pr
timeout-minutes: 3
run: |
set -euo pipefail # Enhanced error handling
BRANCH_NAME="${{ github.ref_name }}"
# Validate branch name for security (allow underscores, dots, and forward slashes)
if ! [[ "$BRANCH_NAME" =~ ^[a-zA-Z0-9/_.-]+$ ]]; then
echo "Error: Invalid branch name format: $BRANCH_NAME"
exit 1
fi
echo "Searching for open PR for branch: $BRANCH_NAME"
# Find PR with error handling and validation
if ! PR_DATA=$(gh pr list --repo "${{ github.repository }}" --state open --head "$BRANCH_NAME" --json number --jq '.[0].number // empty' 2>/dev/null); then
echo "Error: Failed to query GitHub API for PRs"
exit 1
fi
if [ -z "$PR_DATA" ] || [ "$PR_DATA" = "null" ]; then
echo "No open PR found for branch $BRANCH_NAME"
exit 1
fi
# Validate PR number is numeric
if ! [[ "$PR_DATA" =~ ^[0-9]+$ ]]; then
echo "Error: Invalid PR number returned: $PR_DATA"
exit 1
fi
echo "Found PR #$PR_DATA"
echo "pr_number=$PR_DATA" >> $GITHUB_OUTPUT
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Create trigger comment
timeout-minutes: 2
run: |
set -euo pipefail # Enhanced error handling
PR_NUMBER="${{ steps.find-pr.outputs.pr_number }}"
REVIEW_MODE="${{ github.event.inputs.review_mode || 'hunt' }}"
# Validate inputs
if ! [[ "$PR_NUMBER" =~ ^[0-9]+$ ]]; then
echo "Error: Invalid PR number: $PR_NUMBER"
exit 1
fi
# Validate review mode against allowed values
case "$REVIEW_MODE" in
hunt|analyze|security|performance|review)
echo "Using review mode: $REVIEW_MODE"
;;
*)
echo "Error: Invalid review mode: $REVIEW_MODE"
exit 1
;;
esac
# Build comment body safely
COMMENT_BODY="codebot $REVIEW_MODE"
if [ "${{ github.event.inputs.verbose }}" = "true" ]; then
COMMENT_BODY="$COMMENT_BODY verbose"
fi
echo "Creating comment: $COMMENT_BODY"
# Create comment with error handling
if ! gh pr comment "$PR_NUMBER" --repo "${{ github.repository }}" --body "$COMMENT_BODY"; then
echo "Error: Failed to create PR comment"
exit 1
fi
echo "Successfully created trigger comment on PR #$PR_NUMBER"
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
claude:
# Only run on comment triggers or specific PR conditions
if: |
(github.event_name == 'issue_comment' && contains(github.event.comment.body, 'codebot')) ||
(github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, 'codebot')) ||
(github.event_name == 'pull_request' && (
github.event.pull_request.author_association == 'FIRST_TIME_CONTRIBUTOR' ||
contains(github.event.pull_request.title, '[auto-review]')
))
runs-on: ubuntu-latest
timeout-minutes: 15 # Prevent runaway executions
permissions:
contents: read
pull-requests: read
issues: read
id-token: write
steps:
- name: Get PR information for checkout
id: pr-checkout-info
if: github.event_name == 'issue_comment'
timeout-minutes: 2
run: |
set -euo pipefail
PR_NUMBER="${{ github.event.issue.number }}"
# Validate PR number
if ! [[ "$PR_NUMBER" =~ ^[0-9]+$ ]]; then
echo "Error: Invalid PR number: $PR_NUMBER"
exit 1
fi
echo "Fetching PR #$PR_NUMBER details for checkout"
# Get PR head ref with retry logic
for attempt in {1..3}; do
if PR_DATA=$(curl -sS --max-time 30 --retry 2 \
-H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
-H "Accept: application/vnd.github.v3+json" \
"https://api.github.com/repos/${{ github.repository }}/pulls/$PR_NUMBER"); then
if echo "$PR_DATA" | jq empty 2>/dev/null; then
HEAD_REF=$(echo "$PR_DATA" | jq -r '.head.ref // empty')
HEAD_SHA=$(echo "$PR_DATA" | jq -r '.head.sha // empty')
if [ -n "$HEAD_REF" ] && [ "$HEAD_REF" != "null" ] && [ -n "$HEAD_SHA" ] && [ "$HEAD_SHA" != "null" ]; then
echo "pr_head_ref=$HEAD_REF" >> $GITHUB_OUTPUT
echo "pr_head_sha=$HEAD_SHA" >> $GITHUB_OUTPUT
echo "Found PR branch: $HEAD_REF ($HEAD_SHA)"
break
fi
fi
fi
if [ $attempt -eq 3 ]; then
echo "Error: Failed to fetch PR data for checkout"
exit 1
fi
echo "Retrying in $((2 ** attempt)) seconds..."
sleep $((2 ** attempt))
done
- name: Checkout repository
uses: actions/checkout@v5
with:
fetch-depth: 0 # Full history for reliable diff comparisons
token: ${{ secrets.GITHUB_TOKEN }}
# For issue_comment events, checkout the PR branch
ref: ${{ github.event_name == 'issue_comment' && steps.pr-checkout-info.outputs.pr_head_ref || github.ref }}
- name: Refresh git state
id: git-refresh
timeout-minutes: 3
run: |
set -euo pipefail
echo "🔄 Refreshing git state to ensure latest changes are analyzed"
# Get current branch name
CURRENT_BRANCH=$(git branch --show-current || echo "")
CURRENT_SHA=$(git rev-parse HEAD)
echo "Current branch: $CURRENT_BRANCH"
echo "Current SHA: $CURRENT_SHA"
# Fetch all remote references to ensure we have the latest state
echo "Fetching all remote references..."
git fetch --all --prune
# For issue_comment events, ensure we're on the latest commit of the PR branch
if [ "${{ github.event_name }}" = "issue_comment" ]; then
EXPECTED_SHA="${{ steps.pr-checkout-info.outputs.pr_head_sha }}"
echo "Expected SHA from PR: $EXPECTED_SHA"
# Fetch the specific PR branch to get latest changes
PR_HEAD_REF="${{ steps.pr-checkout-info.outputs.pr_head_ref }}"
if [ -n "$PR_HEAD_REF" ]; then
echo "Fetching latest changes for PR branch: $PR_HEAD_REF"
git fetch origin "$PR_HEAD_REF:$PR_HEAD_REF" 2>/dev/null || true
# Reset to the latest commit on the PR branch
echo "Resetting to latest commit on $PR_HEAD_REF"
git reset --hard "origin/$PR_HEAD_REF"
NEW_SHA=$(git rev-parse HEAD)
echo "Updated to SHA: $NEW_SHA"
if [ "$NEW_SHA" != "$CURRENT_SHA" ]; then
echo "⚠️ SHA changed from $CURRENT_SHA to $NEW_SHA - analyzing latest changes"
else
echo "✅ SHA unchanged - no new commits since checkout"
fi
fi
else
# For PR events, ensure we have the latest changes
if [ -n "$CURRENT_BRANCH" ] && [ "$CURRENT_BRANCH" != "HEAD" ]; then
echo "Ensuring latest changes for branch: $CURRENT_BRANCH"
git fetch origin "$CURRENT_BRANCH" 2>/dev/null || true
git reset --hard "origin/$CURRENT_BRANCH" 2>/dev/null || git reset --hard HEAD
NEW_SHA=$(git rev-parse HEAD)
if [ "$NEW_SHA" != "$CURRENT_SHA" ]; then
echo "⚠️ SHA updated from $CURRENT_SHA to $NEW_SHA"
fi
fi
fi
# Final verification
FINAL_SHA=$(git rev-parse HEAD)
FINAL_BRANCH=$(git branch --show-current || echo "detached")
echo "✅ Git state refreshed successfully"
echo "Final branch: $FINAL_BRANCH"
echo "Final SHA: $FINAL_SHA"
# Output for use in subsequent steps
echo "current_sha=$FINAL_SHA" >> $GITHUB_OUTPUT
echo "current_branch=$FINAL_BRANCH" >> $GITHUB_OUTPUT
- name: Parse comment command
id: parse-command
timeout-minutes: 2
env:
COMMENT_BODY: ${{ github.event.comment.body }}
run: |
set -euo pipefail # Enhanced error handling
# Input validation and sanitization
if [ ${#COMMENT_BODY} -gt 1000 ]; then
echo "Error: Comment body too long (max 1000 characters)"
exit 1
fi
# Sanitize comment body - remove potentially dangerous characters
SAFE_COMMENT=$(echo "$COMMENT_BODY" | tr -d '`$(){}[]|;&<>' | head -c 500)
# Default values
echo "mode=review" >> $GITHUB_OUTPUT
echo "focus=code-quality,security,performance" >> $GITHUB_OUTPUT
echo "verbose=false" >> $GITHUB_OUTPUT
echo "include_tests=true" >> $GITHUB_OUTPUT
echo "full_analysis=false" >> $GITHUB_OUTPUT
# Parse comment content for commands (using safe variable)
if [ "${{ github.event_name }}" == "issue_comment" ] || [ "${{ github.event_name }}" == "pull_request_review_comment" ]; then
# Use grep with fixed strings where possible for security
if echo "$SAFE_COMMENT" | grep -qiF "codebot hunt"; then
echo "mode=hunt" >> $GITHUB_OUTPUT
echo "focus=bugs,security,performance" >> $GITHUB_OUTPUT
echo "verbose=false" >> $GITHUB_OUTPUT
elif echo "$SAFE_COMMENT" | grep -qiF "codebot analyze"; then
echo "mode=analyze" >> $GITHUB_OUTPUT
echo "focus=architecture,patterns,complexity" >> $GITHUB_OUTPUT
echo "verbose=true" >> $GITHUB_OUTPUT
elif echo "$SAFE_COMMENT" | grep -qiF "codebot security"; then
echo "mode=security" >> $GITHUB_OUTPUT
echo "focus=security,vulnerabilities,compliance" >> $GITHUB_OUTPUT
echo "verbose=true" >> $GITHUB_OUTPUT
elif echo "$SAFE_COMMENT" | grep -qiF "codebot performance"; then
echo "mode=performance" >> $GITHUB_OUTPUT
echo "focus=performance,optimization,bottlenecks" >> $GITHUB_OUTPUT
echo "verbose=true" >> $GITHUB_OUTPUT
elif echo "$SAFE_COMMENT" | grep -qiF "codebot review"; then
echo "mode=review" >> $GITHUB_OUTPUT
echo "focus=code-quality,security,performance" >> $GITHUB_OUTPUT
echo "verbose=true" >> $GITHUB_OUTPUT
elif echo "$SAFE_COMMENT" | grep -qiF "codebot"; then
# Default to hunt mode for simple "codebot" command
echo "mode=hunt" >> $GITHUB_OUTPUT
echo "focus=bugs,security,performance" >> $GITHUB_OUTPUT
echo "verbose=false" >> $GITHUB_OUTPUT
fi
# Check for verbose flag (using fixed strings for security)
if echo "$SAFE_COMMENT" | grep -qiF "verbose" || echo "$SAFE_COMMENT" | grep -qiF "detailed"; then
echo "verbose=true" >> $GITHUB_OUTPUT
fi
# Check for specific focus areas
if echo "$SAFE_COMMENT" | grep -qiF "security"; then
echo "focus=security,vulnerabilities,compliance" >> $GITHUB_OUTPUT
elif echo "$SAFE_COMMENT" | grep -qiF "performance"; then
echo "focus=performance,optimization,bottlenecks" >> $GITHUB_OUTPUT
elif echo "$SAFE_COMMENT" | grep -qiF "tests"; then
echo "focus=test-coverage,test-quality" >> $GITHUB_OUTPUT
fi
# Check for --full flag (analyze entire codebase)
if echo "$SAFE_COMMENT" | grep -qiF -- "--full"; then
echo "full_analysis=true" >> $GITHUB_OUTPUT
else
echo "full_analysis=false" >> $GITHUB_OUTPUT
fi
fi
echo "Security: Input validation and sanitization completed"
- name: Get PR information
id: pr-info
timeout-minutes: 3
run: |
set -euo pipefail # Enhanced error handling
# Initialize variables
PR_NUMBER=""
BASE_REF=""
# Handle different trigger types with validation
if [ "${{ github.event_name }}" = "pull_request" ]; then
PR_NUMBER="${{ github.event.pull_request.number }}"
BASE_REF="${{ github.event.pull_request.base.ref }}"
elif [ "${{ github.event_name }}" = "issue_comment" ]; then
PR_NUMBER="${{ github.event.issue.number }}"
# Validate PR number is numeric
if ! [[ "$PR_NUMBER" =~ ^[0-9]+$ ]]; then
echo "Error: Invalid PR number: $PR_NUMBER"
exit 1
fi
# Fetch PR data with retry logic and timeout
for attempt in {1..3}; do
echo "Attempt $attempt: Fetching PR data for PR #$PR_NUMBER"
if PR_DATA=$(curl -sS --max-time 30 --retry 2 \
-H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
-H "Accept: application/vnd.github.v3+json" \
"https://api.github.com/repos/${{ github.repository }}/pulls/$PR_NUMBER"); then
# Validate JSON response
if echo "$PR_DATA" | jq empty 2>/dev/null; then
BASE_REF=$(echo "$PR_DATA" | jq -r '.base.ref // empty')
if [ -n "$BASE_REF" ] && [ "$BASE_REF" != "null" ]; then
echo "Successfully retrieved base ref: $BASE_REF"
break
fi
fi
fi
if [ $attempt -eq 3 ]; then
echo "Error: Failed to fetch PR data after 3 attempts"
exit 1
fi
echo "Retrying in $((2 ** attempt)) seconds..."
sleep $((2 ** attempt))
done
elif [ "${{ github.event_name }}" = "pull_request_review_comment" ]; then
PR_NUMBER="${{ github.event.pull_request.number }}"
BASE_REF="${{ github.event.pull_request.base.ref }}"
else
echo "Error: Unsupported event type: ${{ github.event_name }}"
exit 1
fi
# Validate required variables
if [ -z "$PR_NUMBER" ] || [ -z "$BASE_REF" ]; then
echo "Error: Missing required PR information"
echo "PR_NUMBER: $PR_NUMBER, BASE_REF: $BASE_REF"
exit 1
fi
# Sanitize branch name for security (allow underscores, dots, and forward slashes)
if ! [[ "$BASE_REF" =~ ^[a-zA-Z0-9/_.-]+$ ]]; then
echo "Error: Invalid base ref format: $BASE_REF"
exit 1
fi
echo "pr_number=$PR_NUMBER" >> $GITHUB_OUTPUT
echo "base_ref=$BASE_REF" >> $GITHUB_OUTPUT
echo "Security: PR information validated and sanitized"
- name: Get changed files
id: changes
if: steps.parse-command.outputs.full_analysis == 'false'
run: |
set -euo pipefail
BASE_REF="${{ steps.pr-info.outputs.base_ref }}"
CURRENT_SHA="${{ steps.git-refresh.outputs.current_sha }}"
CURRENT_BRANCH="${{ steps.git-refresh.outputs.current_branch }}"
echo "🔍 Detecting changed files for analysis"
echo "Base branch: $BASE_REF"
echo "Current SHA: $CURRENT_SHA"
echo "Current branch: $CURRENT_BRANCH"
# Ensure we have the base branch reference
echo "Fetching base branch: $BASE_REF"
git fetch origin "$BASE_REF" 2>/dev/null || {
echo "⚠️ Failed to fetch $BASE_REF, trying fallback methods"
git fetch origin 2>/dev/null || true
}
# Multiple fallback strategies for getting changed files
CHANGED_FILES=""
DIFF_SUCCESS=false
# Strategy 1: Standard three-dot diff (preferred)
if [ "$DIFF_SUCCESS" = false ]; then
echo "Trying three-dot diff: origin/$BASE_REF...HEAD"
if CHANGED_FILES=$(git diff --name-only "origin/$BASE_REF...HEAD" 2>/dev/null); then
echo "✅ Three-dot diff successful"
DIFF_SUCCESS=true
else
echo "❌ Three-dot diff failed"
fi
fi
# Strategy 2: Two-dot diff fallback
if [ "$DIFF_SUCCESS" = false ]; then
echo "Trying two-dot diff: origin/$BASE_REF..HEAD"
if CHANGED_FILES=$(git diff --name-only "origin/$BASE_REF..HEAD" 2>/dev/null); then
echo "✅ Two-dot diff successful"
DIFF_SUCCESS=true
else
echo "❌ Two-dot diff failed"
fi
fi
# Strategy 3: Direct branch comparison
if [ "$DIFF_SUCCESS" = false ]; then
echo "Trying direct comparison: origin/$BASE_REF HEAD"
if CHANGED_FILES=$(git diff --name-only "origin/$BASE_REF" HEAD 2>/dev/null); then
echo "✅ Direct comparison successful"
DIFF_SUCCESS=true
else
echo "❌ Direct comparison failed"
fi
fi
# Strategy 4: Last resort - use merge-base
if [ "$DIFF_SUCCESS" = false ]; then
echo "Trying merge-base approach"
if MERGE_BASE=$(git merge-base "origin/$BASE_REF" HEAD 2>/dev/null); then
if CHANGED_FILES=$(git diff --name-only "$MERGE_BASE" HEAD 2>/dev/null); then
echo "✅ Merge-base diff successful"
DIFF_SUCCESS=true
fi
fi
fi
# Validate and process results
if [ "$DIFF_SUCCESS" = false ]; then
echo "❌ All diff strategies failed - will analyze full codebase"
CHANGED_FILES=""
CHANGED_COUNT=0
CHANGED_FILES_STR="Unable to determine changed files - will analyze full codebase"
else
# Filter out empty lines and count
CHANGED_FILES=$(echo "$CHANGED_FILES" | grep -v '^$' || echo "")
CHANGED_COUNT=$(echo "$CHANGED_FILES" | grep -c . 2>/dev/null || echo "0")
if [ "$CHANGED_COUNT" -eq 0 ]; then
CHANGED_FILES_STR="No files changed"
echo "⚠️ No changed files detected - this might indicate an issue"
else
CHANGED_FILES_STR=$(echo "$CHANGED_FILES" | tr '\n' ' ' | sed 's/[[:space:]]*$//')
echo "✅ Found $CHANGED_COUNT changed files"
fi
fi
# Debug output
echo "📋 Changed files summary:"
echo " Count: $CHANGED_COUNT"
echo " Files: $CHANGED_FILES_STR"
if [ "$CHANGED_COUNT" -gt 0 ]; then
echo "📄 Individual files:"
echo "$CHANGED_FILES" | while IFS= read -r file; do
[ -n "$file" ] && echo " - $file"
done
fi
# Output for next steps
echo "changed_files=$CHANGED_FILES_STR" >> $GITHUB_OUTPUT
echo "changed_count=$CHANGED_COUNT" >> $GITHUB_OUTPUT
echo "diff_successful=$DIFF_SUCCESS" >> $GITHUB_OUTPUT
- name: Verify commit SHA and git state
id: verify-state
timeout-minutes: 2
run: |
set -euo pipefail
echo "🔍 Verifying git state before analysis"
CURRENT_SHA="${{ steps.git-refresh.outputs.current_sha }}"
ACTUAL_SHA=$(git rev-parse HEAD)
CURRENT_BRANCH="${{ steps.git-refresh.outputs.current_branch }}"
# Verify SHA consistency
if [ "$CURRENT_SHA" != "$ACTUAL_SHA" ]; then
echo "⚠️ SHA mismatch detected!"
echo " Expected: $CURRENT_SHA"
echo " Actual: $ACTUAL_SHA"
echo " This indicates a git state issue - attempting to resolve..."
# Update the SHA for consistency
CURRENT_SHA="$ACTUAL_SHA"
echo "current_sha=$ACTUAL_SHA" >> $GITHUB_OUTPUT
else
echo "✅ SHA verification passed: $CURRENT_SHA"
echo "current_sha=$CURRENT_SHA" >> $GITHUB_OUTPUT
fi
# Get additional context for debugging
echo "📊 Git state summary:"
echo " Commit SHA: $CURRENT_SHA"
echo " Branch: $CURRENT_BRANCH"
echo " Repository: ${{ github.repository }}"
echo " Event: ${{ github.event_name }}"
# Get commit info for better context
COMMIT_MSG=$(git log -1 --pretty=format:"%s" 2>/dev/null || echo "Unable to get commit message")
COMMIT_AUTHOR=$(git log -1 --pretty=format:"%an" 2>/dev/null || echo "Unknown")
COMMIT_DATE=$(git log -1 --pretty=format:"%ci" 2>/dev/null || echo "Unknown")
echo " Commit message: $COMMIT_MSG"
echo " Author: $COMMIT_AUTHOR"
echo " Date: $COMMIT_DATE"
# Create unique identifier for cache invalidation
REVIEW_ID="${CURRENT_SHA:0:8}-${{ github.event_name }}-$(date +%s)"
echo " Review ID: $REVIEW_ID"
# Output additional context
echo "commit_message=$COMMIT_MSG" >> $GITHUB_OUTPUT
echo "commit_author=$COMMIT_AUTHOR" >> $GITHUB_OUTPUT
echo "commit_date=$COMMIT_DATE" >> $GITHUB_OUTPUT
echo "review_id=$REVIEW_ID" >> $GITHUB_OUTPUT
- name: Run Claude Code Review
id: claude
timeout-minutes: 10
uses: anthropics/claude-code-action@beta
with:
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
# Allow Bash permissions for pre-commit hooks and documentation updates
allowed_tools: "Bash(pre-commit run --files),Bash(terraform fmt),Bash(terraform validate),Bash(terraform-docs)"
# Dynamic prompt based on review mode
direct_prompt: |
🔄 **COMMIT ANALYSIS CONTEXT**
- **Commit SHA**: `${{ steps.verify-state.outputs.current_sha }}`
- **Review ID**: `${{ steps.verify-state.outputs.review_id }}`
- **Branch**: `${{ steps.git-refresh.outputs.current_branch }}`
- **Last Commit**: "${{ steps.verify-state.outputs.commit_message }}" by ${{ steps.verify-state.outputs.commit_author }}
- **Date**: ${{ steps.verify-state.outputs.commit_date }}
---
${{ steps.parse-command.outputs.full_analysis == 'false' && format('
**IMPORTANT: Focus ONLY on the following changed files in this pull request:**
Files changed: {0}
Total files changed: {1}
Diff detection: {2}
DO NOT review or comment on files outside this list unless they are directly impacted by changes in these files.
', steps.changes.outputs.changed_files || 'Unable to determine changed files', steps.changes.outputs.changed_count || '0', steps.changes.outputs.diff_successful == 'true' && 'Successful' || 'Failed - analyzing full codebase') || '' }}
${{ steps.parse-command.outputs.mode == 'hunt' && format('
🕵️ BUG HUNT MODE - Find potential issues quickly:
- Focus on critical bugs, security vulnerabilities, and performance issues
- Prioritize high-impact problems over style suggestions
- Be concise and actionable
- Provide clear, actionable feedback
') || '' }}
${{ steps.parse-command.outputs.mode == 'analyze' && format('
📊 ANALYSIS MODE - Deep technical analysis:
- Analyze architecture, patterns, and design decisions
- Evaluate code complexity and maintainability
- Assess test coverage and quality
- Provide strategic recommendations
- Consider long-term implications and scalability
') || '' }}
${{ steps.parse-command.outputs.mode == 'security' && format('
🔒 SECURITY MODE - Security-focused review:
- Identify security vulnerabilities and compliance issues
- Check for proper authentication and authorization
- Validate input sanitization and output encoding
- Review encryption and key management
- Assess data protection and privacy concerns
') || '' }}
${{ steps.parse-command.outputs.mode == 'performance' && format('
⚡ PERFORMANCE MODE - Performance optimization review:
- Identify performance bottlenecks and optimization opportunities
- Analyze resource usage and efficiency
- Check for memory leaks and scalability issues
- Review caching strategies and database queries
- Consider load testing and monitoring needs
') || '' }}
${{ steps.parse-command.outputs.mode == 'review' && format('
📝 STANDARD REVIEW MODE - Comprehensive code review:
- Code quality and best practices
- Potential bugs or issues
- Performance considerations
- Security concerns
- Test coverage and quality
Focus areas: {0}
Verbose output: {1}
Be constructive and helpful.
', steps.parse-command.outputs.focus, steps.parse-command.outputs.verbose) || '' }}
# Use sticky comments with commit-specific cache invalidation
use_sticky_comment: true
# Note: The commit SHA and review ID in the prompt help ensure fresh analysis
- name: Workflow Summary
if: always()
timeout-minutes: 2
run: |
set -euo pipefail # Enhanced error handling
echo "## 🤖 Claude Code Review Summary" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
# Security Status
echo "### 🔐 Security Status" >> $GITHUB_STEP_SUMMARY
echo "- ✅ Input validation and sanitization enabled" >> $GITHUB_STEP_SUMMARY
echo "- ✅ Command injection protection active" >> $GITHUB_STEP_SUMMARY
echo "- ✅ Error handling and retry logic implemented" >> $GITHUB_STEP_SUMMARY
echo "- ✅ Timeout protection for all operations" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
# Review Configuration
echo "### ⚙️ Review Configuration" >> $GITHUB_STEP_SUMMARY
echo "**Review Mode:** \`${{ steps.parse-command.outputs.mode }}\`" >> $GITHUB_STEP_SUMMARY
echo "**Focus Areas:** \`${{ steps.parse-command.outputs.focus }}\`" >> $GITHUB_STEP_SUMMARY
echo "**Verbose Output:** \`${{ steps.parse-command.outputs.verbose }}\`" >> $GITHUB_STEP_SUMMARY
echo "**Full Analysis:** \`${{ steps.parse-command.outputs.full_analysis || 'false' }}\`" >> $GITHUB_STEP_SUMMARY
if [ "${{ steps.parse-command.outputs.full_analysis }}" != "true" ]; then
echo "**Changed Files:** \`${{ steps.changes.outputs.changed_count || '0' }}\` files" >> $GITHUB_STEP_SUMMARY
echo "**Diff Detection:** \`${{ steps.changes.outputs.diff_successful == 'true' && 'Successful' || 'Failed' }}\`" >> $GITHUB_STEP_SUMMARY
fi
echo "**PR Number:** \`${{ steps.pr-info.outputs.pr_number || 'N/A' }}\`" >> $GITHUB_STEP_SUMMARY
echo "**Base Branch:** \`${{ steps.pr-info.outputs.base_ref || 'N/A' }}\`" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
# Git State Information
echo "### 📊 Git State Analysis" >> $GITHUB_STEP_SUMMARY
echo "**Commit SHA:** \`${{ steps.verify-state.outputs.current_sha || steps.git-refresh.outputs.current_sha || 'Unknown' }}\`" >> $GITHUB_STEP_SUMMARY
echo "**Review ID:** \`${{ steps.verify-state.outputs.review_id || 'N/A' }}\`" >> $GITHUB_STEP_SUMMARY
echo "**Current Branch:** \`${{ steps.git-refresh.outputs.current_branch || 'Unknown' }}\`" >> $GITHUB_STEP_SUMMARY
echo "**Last Commit:** \"${{ steps.verify-state.outputs.commit_message || 'Unknown' }}\"" >> $GITHUB_STEP_SUMMARY
echo "**Author:** \`${{ steps.verify-state.outputs.commit_author || 'Unknown' }}\`" >> $GITHUB_STEP_SUMMARY
echo "**Date:** \`${{ steps.verify-state.outputs.commit_date || 'Unknown' }}\`" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
# Analysis Scope Details
if [ "${{ steps.parse-command.outputs.full_analysis }}" != "true" ] && [ "${{ steps.changes.outputs.changed_count || '0' }}" -gt "0" ]; then
echo "### 📄 Files Being Analyzed" >> $GITHUB_STEP_SUMMARY
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
echo "${{ steps.changes.outputs.changed_files }}" | tr ' ' '\n' | grep -v '^$' | head -20 >> $GITHUB_STEP_SUMMARY
if [ "${{ steps.changes.outputs.changed_count }}" -gt "20" ]; then
echo "... and $((${{ steps.changes.outputs.changed_count }} - 20)) more files" >> $GITHUB_STEP_SUMMARY
fi
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
fi
# Available Commands
echo "### 📝 Available Commands" >> $GITHUB_STEP_SUMMARY
echo "Comment any of these in PRs to trigger specific review types:" >> $GITHUB_STEP_SUMMARY
echo "- \`codebot hunt\` - Quick bug detection (like Bugbot) on PR changes" >> $GITHUB_STEP_SUMMARY
echo "- \`codebot analyze\` - Deep technical analysis on PR changes" >> $GITHUB_STEP_SUMMARY
echo "- \`codebot security\` - Security-focused review on PR changes" >> $GITHUB_STEP_SUMMARY
echo "- \`codebot performance\` - Performance optimization review on PR changes" >> $GITHUB_STEP_SUMMARY
echo "- \`codebot review\` - Comprehensive review on PR changes" >> $GITHUB_STEP_SUMMARY
echo "- \`codebot\` - Defaults to hunt mode on PR changes" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
# Scope Options
echo "### 🔍 Scope Options" >> $GITHUB_STEP_SUMMARY
echo "- Add \`--full\` to any command to analyze the entire codebase" >> $GITHUB_STEP_SUMMARY
echo "- Example: \`codebot hunt --full\` - Hunt for bugs in the entire codebase" >> $GITHUB_STEP_SUMMARY
echo "- Default behavior (without --full) focuses only on changed files in the PR" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
# Manual Triggers
echo "### 🚀 Manual Triggers" >> $GITHUB_STEP_SUMMARY
echo "Run via GitHub CLI:" >> $GITHUB_STEP_SUMMARY
echo "\`\`\`bash" >> $GITHUB_STEP_SUMMARY
echo "gh workflow run claude-code-review.yml -f review_mode=hunt" >> $GITHUB_STEP_SUMMARY
echo "gh workflow run claude-code-review.yml -f review_mode=security -f verbose=true" >> $GITHUB_STEP_SUMMARY
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
# Performance & Reliability Info
echo "" >> $GITHUB_STEP_SUMMARY
echo "### ⚡ Performance & Reliability" >> $GITHUB_STEP_SUMMARY
echo "- 🚀 Full git history fetch for reliable diff comparisons" >> $GITHUB_STEP_SUMMARY
echo "- 🔄 Automatic git state refresh and commit SHA verification" >> $GITHUB_STEP_SUMMARY
echo "- 🎯 Multiple fallback strategies for change detection" >> $GITHUB_STEP_SUMMARY
echo "- ⏱️ Timeout protection prevents runaway executions" >> $GITHUB_STEP_SUMMARY
echo "- 🛡️ Comprehensive error handling and validation" >> $GITHUB_STEP_SUMMARY
echo "- 📊 Enhanced logging and debug information" >> $GITHUB_STEP_SUMMARY
echo "- 🔐 Cache invalidation via commit-specific review IDs" >> $GITHUB_STEP_SUMMARY
# Troubleshooting section
echo "" >> $GITHUB_STEP_SUMMARY
echo "### 🔧 Troubleshooting" >> $GITHUB_STEP_SUMMARY
echo "If the review doesn't detect recent changes:" >> $GITHUB_STEP_SUMMARY
echo "1. Check the commit SHA matches your latest changes" >> $GITHUB_STEP_SUMMARY
echo "2. Verify the diff detection was successful" >> $GITHUB_STEP_SUMMARY
echo "3. Review the git state analysis above" >> $GITHUB_STEP_SUMMARY
echo "4. Try \`codebot hunt --full\` to analyze the entire codebase" >> $GITHUB_STEP_SUMMARY