diff --git a/.github/workflows/ai-review.yml b/.github/workflows/ai-review.yml index 471e33c1..eaac91d5 100644 --- a/.github/workflows/ai-review.yml +++ b/.github/workflows/ai-review.yml @@ -1,17 +1,15 @@ # AI Code Review Workflow -# Uses Claude Code CLI on self-hosted runner with CLIProxyAPI +# Uses anthropics/claude-code-action with CLIProxy for model flexibility # Posts as ccs-agy-reviewer[bot] via GitHub App # # Triggers: # - Automatically on PR open/update # - Manually via /review comment on PR -# -# Logs stored on runner at: /opt/actions-runner/logs/ai-review/ name: AI Code Review on: - pull_request: + pull_request_target: types: [opened, synchronize, reopened] issue_comment: types: [created] @@ -30,20 +28,32 @@ concurrency: jobs: review: name: Claude Code Review - # Only run on self-hosted runner with cliproxy access runs-on: [self-hosted, cliproxy] + permissions: + contents: read + pull-requests: write + issues: write + id-token: write # Conditions: - # - PR event: always run + # - PR event: always run (pull_request_target has secrets access for forks) # - Comment event: only if it's a PR and contains /review if: > - github.event_name == 'pull_request' || + github.event_name == 'pull_request_target' || github.event_name == 'workflow_dispatch' || (github.event_name == 'issue_comment' && github.event.issue.pull_request && contains(github.event.comment.body, '/review')) + # CLIProxy environment for model routing + env: + ANTHROPIC_BASE_URL: http://localhost:8317 + REVIEW_MODEL: gemini-claude-opus-4-5-thinking + steps: + - name: Clear Claude install locks + run: rm -rf ~/.local/state/claude/locks/* 2>/dev/null || true + - name: Generate App Token id: app-token uses: actions/create-github-app-token@v1 @@ -51,7 +61,7 @@ jobs: app-id: ${{ secrets.CCS_REVIEWER_APP_ID }} private-key: ${{ secrets.CCS_REVIEWER_PRIVATE_KEY }} - - name: Checkout PR branch + - name: Checkout repository uses: actions/checkout@v4 with: fetch-depth: 0 @@ -65,17 +75,6 @@ jobs: gh pr checkout $PR_NUM || git checkout ${{ github.event.pull_request.head.sha }} 2>/dev/null || true fi - - name: Determine PR Number - id: pr - run: | - if [ "${{ github.event_name }}" = "pull_request" ]; then - echo "number=${{ github.event.pull_request.number }}" >> $GITHUB_OUTPUT - elif [ "${{ github.event_name }}" = "workflow_dispatch" ]; then - echo "number=${{ github.event.inputs.pr_number }}" >> $GITHUB_OUTPUT - else - echo "number=${{ github.event.issue.number }}" >> $GITHUB_OUTPUT - fi - - name: Add reaction to comment if: github.event_name == 'issue_comment' run: | @@ -84,360 +83,51 @@ jobs: env: GH_TOKEN: ${{ steps.app-token.outputs.token }} - - name: Ensure Claude Code installed - run: | - # Force cleanup of any stale lock/install markers - rm -rf ~/.claude/.installing ~/.claude/downloads 2>/dev/null || true - pkill -f "claude install" 2>/dev/null || true - - if ! command -v claude &> /dev/null; then - echo "[i] Installing Claude Code..." - # Download and run install script - curl -fsSL https://claude.ai/install.sh > /tmp/claude-install.sh - chmod +x /tmp/claude-install.sh - - # Run installer; on failure, try running claude install --force directly - if ! bash /tmp/claude-install.sh; then - echo "[!] Script install failed, trying direct --force..." - BINARY=$(find ~/.claude -name "claude" -type f -executable 2>/dev/null | head -1) - if [ -n "$BINARY" ]; then - "$BINARY" install --force || true - fi - fi - echo "$HOME/.local/bin" >> $GITHUB_PATH - else - echo "[i] Claude Code already installed: $(claude --version)" - fi - - - name: Create review prompt template - run: | - cat > /tmp/review-instructions.txt << 'INSTRUCTIONS_END' - You are a senior staff engineer performing a comprehensive code review. - - ## MANDATORY: Tool Usage Requirements - Before writing your review, you MUST: - - 1. **Read each changed file in full** using the Read tool - - Don't just look at the diff - read the ENTIRE file for context - - Understand the surrounding code, imports, and dependencies - - 2. **Find related test files** using Glob tool - - Pattern: `**/*test*` or `**/*.spec.*` or `**/__tests__/**` - - Read the test files to assess coverage - - 3. **Search for usages** using Grep tool - - Find where modified functions/classes are called - - Check for breaking changes impact - - 4. **Check project structure** using Glob tool - - Understand the codebase architecture - - Verify the changes follow existing patterns - - ## Analysis Dimensions - - ### ๐Ÿ”’ Security (CRITICAL) - - Auth bypass, privilege escalation, injection (SQL, command, XSS) - - Secrets/credentials exposure, insecure defaults - - OWASP Top 10 vulnerabilities - - Input validation at trust boundaries - - ### โœ… Correctness - - Logic errors, off-by-one, null/undefined handling - - Race conditions, deadlocks, async issues - - Edge cases, boundary conditions - - Error handling completeness - - ### ๐Ÿ—๏ธ Architecture and Design - - Coupling, cohesion, separation of concerns - - Design patterns usage (appropriate or over-engineered) - - API contract changes, backward compatibility - - Single responsibility, interface segregation - - ### ๐Ÿงช Testing - - Test coverage for new/modified code - - Edge case coverage, negative tests - - Test quality (not just quantity) - - Integration vs unit test balance - - ### โšก Performance - - O(n^2) or worse algorithms, unnecessary iterations - - Memory leaks, resource cleanup - - Database query efficiency (N+1, missing indexes) - - Only flag if measurable impact - - ### ๐Ÿ“– Maintainability - - Naming clarity, self-documenting code - - Comments for "why" not "what" - - Complexity (cyclomatic, cognitive) - - Consistency with codebase patterns - - ## Output Format (Markdown) - - ## ๐Ÿ” Code Review - - **Verdict**: [Choose one: โœ… Approve | โš ๏ธ Approve with notes | โŒ Request changes] - - > ๐Ÿค– Reviewed by `MODEL_NAME` - - ### Summary - [2-3 sentences: what this PR does, the approach taken, and overall assessment] - - ### โœ… Strengths - [Specific things done well with file:line-range references] - 1. **[Category]**: Description - - `src/path/file.ts:10-25` - specific code reference - 2. ... - - ### โš ๏ธ Issues Found - | File:Line | Issue | Severity | Impact | - |-----------|-------|----------|--------| - | `src/file.ts:123-145` | Description | ๐Ÿ”ด/๐ŸŸก/๐ŸŸข | What could go wrong | - - ### ๐Ÿ” Code Quality Observations - **Positive:** - - Observation with `file.ts:line` reference - - **Concerns:** - - Concern with `file.ts:line` reference and code example: - ```typescript - // Current code (problematic): - const x = something.slice(0, 60); - - // Suggested improvement: - const x = truncateString(something, 60); - ``` - - ### ๐Ÿงช Testing - - **Coverage**: [Assessed by reading test files] - - **Test files examined**: `tests/path/file.test.ts` - - **Missing tests**: [List specific scenarios not covered] - - **Test quality**: [Observations about test implementations] - - ### ๐Ÿ”’ Security - - [Detailed security analysis or "No concerns identified"] - - ### โšก Performance - - [Performance analysis or "No concerns identified"] - - ### ๐Ÿ“ Recommendations - 1. **[Category]**: Specific recommendation - ```typescript - // Instead of: - problematicCode(); - - // Consider: - betterApproach(); - ``` - - 2. ... - - ### ๐ŸŽฏ Alignment with Project Standards - - โœ…/โŒ Follows codebase patterns (cite specific examples) - - โœ…/โŒ Consistent naming/style - - โœ…/โŒ Proper error handling - - ### Verdict: **[Final verdict with emoji]** - [One sentence final summary with key takeaway] - - --- - **Guidelines:** - - Skip empty sections - - Only โŒ Request changes for ๐Ÿ”ด High severity issues - - Include code snippets for ALL non-trivial suggestions - - Reference specific line ranges, not just file names - INSTRUCTIONS_END - - name: Run Claude Code Review - env: - ANTHROPIC_BASE_URL: http://localhost:8317 - ANTHROPIC_API_KEY: ${{ secrets.CLIPROXY_API_KEY }} - ANTHROPIC_MODEL: gemini-3-pro-preview - GH_TOKEN: ${{ steps.app-token.outputs.token }} - GITHUB_TOKEN: ${{ steps.app-token.outputs.token }} - run: | - PR_NUM="${{ steps.pr.outputs.number }}" - REPO="${{ github.repository }}" - TIMESTAMP=$(date +%Y%m%d-%H%M%S) + id: claude-review + uses: anthropics/claude-code-action@v1 + with: + anthropic_api_key: ${{ secrets.CLIPROXY_API_KEY }} + github_token: ${{ steps.app-token.outputs.token }} + path_to_claude_code_executable: /home/github-runner/.local/bin/claude + track_progress: ${{ github.event_name != 'workflow_dispatch' }} + prompt: | + ultrathink - # Setup logging directory on runner - LOG_DIR="/opt/actions-runner/logs/ai-review/pr-${PR_NUM}-${TIMESTAMP}" - mkdir -p "$LOG_DIR" + REPO: ${{ github.repository }} + PR NUMBER: ${{ github.event.pull_request.number || github.event.issue.number || github.event.inputs.pr_number }} - echo "[i] Running Claude Code review for PR #${PR_NUM}" - echo "[i] Model: ${ANTHROPIC_MODEL}" - echo "[i] Working directory: $(pwd)" - echo "[i] Log directory: ${LOG_DIR}" + Perform a comprehensive code review. Follow the repository's CLAUDE.md for project-specific guidelines. - # Get PR metadata - PR_TITLE=$(gh pr view $PR_NUM --repo $REPO --json title --jq .title) - PR_BODY=$(gh pr view $PR_NUM --repo $REPO --json body --jq .body) + ## Review Focus Areas - # Get list of changed files - CHANGED_FILES=$(gh pr diff $PR_NUM --repo $REPO --name-only) + 1. **Security** - OWASP Top 10, injection, auth bypass, secrets exposure + 2. **Correctness** - Logic errors, edge cases, error handling + 3. **Architecture** - Coupling, cohesion, API contracts, backward compatibility + 4. **Testing** - Coverage, edge cases, test quality + 5. **Performance** - Algorithm complexity, memory leaks, query efficiency + 6. **Maintainability** - Naming, complexity, consistency with codebase - # Get full diff (NO LIMIT - unlimited) - DIFF=$(gh pr diff $PR_NUM --repo $REPO) + ## Output Structure - # Replace model name in instructions - sed -i "s|MODEL_NAME|${ANTHROPIC_MODEL}|g" /tmp/review-instructions.txt + Use visual hierarchy with `---` separators between major sections: + - Summary (2-3 sentences) + - Strengths (numbered, with file:line references) + - Observations & Suggestions (with code examples) + - Security Considerations (โœ…/โŒ checklist) + - Code Quality Checklist (โœ…/โŒ format) + - Recommendations (Priority: High/Medium/Low) + - Overall Assessment (APPROVED/APPROVED WITH NOTES/CHANGES REQUESTED) - # Build the full prompt - cat > /tmp/full-prompt.txt << PROMPT_END - # Pull Request Review Task + Be thorough but concise. Skip empty sections. Include code examples for non-trivial suggestions. - ## PR Information - - **PR**: #${PR_NUM} - - **Title**: ${PR_TITLE} - - **Repository**: ${REPO} + End your review with: + > ๐Ÿค– Reviewed by `${{ env.REVIEW_MODEL }}` - ## Description - ${PR_BODY} - - ## Changed Files - ${CHANGED_FILES} - - ## Diff (for initial understanding only) - ${DIFF} - - ## Your Task - - **STEP 1 - MANDATORY EXPLORATION (before writing review):** - You MUST use tools to explore the codebase. Do not skip this step. - - a) For EACH file in "Changed Files" above: - - Use Read tool to read the FULL file (not just diff) - - Examine imports, exports, and dependencies - - b) Find test files: - - Use Glob with pattern: tests/**/*.test.* or **/*.spec.* - - Read relevant test files to assess coverage - - c) Search for usages: - - Use Grep to find where modified functions/classes are used - - Assess breaking change impact - - **STEP 2 - WRITE REVIEW:** - Only after completing Step 1, write your review following the format below. - - $(cat /tmp/review-instructions.txt) - - --- - BEGIN YOUR EXPLORATION NOW. Use Read, Glob, and Grep tools before writing your review. - PROMPT_END - - # Save prompt for debugging - cp /tmp/full-prompt.txt "$LOG_DIR/prompt.txt" - - # Save metadata - cat > "$LOG_DIR/metadata.json" << EOF - { - "pr_number": ${PR_NUM}, - "repository": "${REPO}", - "model": "${ANTHROPIC_MODEL}", - "timestamp": "${TIMESTAMP}", - "changed_files_count": $(echo "$CHANGED_FILES" | wc -l), - "diff_lines": $(echo "$DIFF" | wc -l), - "workflow_run_id": "${{ github.run_id }}" - } - EOF - - # Run Claude Code with NO LIMITS - echo "[i] Starting comprehensive review (unlimited turns)..." - START_TIME=$(date +%s) - - # Run with separate stdout/stderr capture - set +e - cat /tmp/full-prompt.txt | claude -p \ - --allowed-tools "Read,Glob,Grep" \ - > "$LOG_DIR/claude-stdout.txt" \ - 2> "$LOG_DIR/claude-stderr.txt" - EXIT_CODE=$? - set -e - - END_TIME=$(date +%s) - DURATION=$((END_TIME - START_TIME)) - - # Save timing info - cat > "$LOG_DIR/timing.txt" << EOF - Start: $(date -d @$START_TIME '+%Y-%m-%d %H:%M:%S') - End: $(date -d @$END_TIME '+%Y-%m-%d %H:%M:%S') - Duration: ${DURATION} seconds - Exit code: ${EXIT_CODE} - EOF - - echo "[i] Review completed in ${DURATION}s with exit code ${EXIT_CODE}" - - # Read the review output - REVIEW=$(cat "$LOG_DIR/claude-stdout.txt") - REVIEW_LEN=${#REVIEW} - - echo "[i] Review output: ${REVIEW_LEN} chars" - echo "[i] Stderr output: $(wc -c < "$LOG_DIR/claude-stderr.txt") chars" - - # Log stderr if non-empty (for debugging) - if [ -s "$LOG_DIR/claude-stderr.txt" ]; then - echo "[!] Claude stderr output:" - cat "$LOG_DIR/claude-stderr.txt" - fi - - # Validate review output - retry if too short - if [ -z "$REVIEW" ] || [ ${REVIEW_LEN} -lt 100 ]; then - echo "[!] Review output too short (${REVIEW_LEN} chars), retrying without tool restrictions..." - - cat /tmp/full-prompt.txt | claude -p \ - > "$LOG_DIR/claude-stdout-retry.txt" \ - 2> "$LOG_DIR/claude-stderr-retry.txt" || true - - REVIEW=$(cat "$LOG_DIR/claude-stdout-retry.txt") - REVIEW_LEN=${#REVIEW} - echo "[i] Retry output: ${REVIEW_LEN} chars" - fi - - # Final fallback with error details - if [ -z "$REVIEW" ] || [ ${REVIEW_LEN} -lt 50 ]; then - STDERR_CONTENT=$(cat "$LOG_DIR/claude-stderr.txt" 2>/dev/null | head -10 || echo "No stderr") - REVIEW="## ๐Ÿ” Code Review - - **Verdict**: โš ๏ธ Review generation failed - - > ๐Ÿค– Attempted by \`${ANTHROPIC_MODEL}\` - - The automated review encountered an issue. Details logged to runner. - - **Debug info:** - - Exit code: ${EXIT_CODE} - - Duration: ${DURATION}s - - Output length: ${REVIEW_LEN} chars - - Log path: \`${LOG_DIR}\` - - Please request a manual review or check runner logs." - fi - - # Save final review - echo "$REVIEW" > "$LOG_DIR/final-review.txt" - - # Update metadata with result - cat > "$LOG_DIR/metadata.json" << EOF - { - "pr_number": ${PR_NUM}, - "repository": "${REPO}", - "model": "${ANTHROPIC_MODEL}", - "timestamp": "${TIMESTAMP}", - "changed_files_count": $(echo "$CHANGED_FILES" | wc -l), - "diff_lines": $(echo "$DIFF" | wc -l), - "workflow_run_id": "${{ github.run_id }}", - "duration_seconds": ${DURATION}, - "exit_code": ${EXIT_CODE}, - "review_length": ${REVIEW_LEN}, - "success": $([ ${REVIEW_LEN} -ge 100 ] && echo "true" || echo "false") - } - EOF - - # Post review as comment - echo "[i] Posting review (${REVIEW_LEN} chars)..." - echo "$REVIEW" | gh pr comment $PR_NUM --repo $REPO --body-file - - echo "[OK] Review posted" - echo "[i] Logs saved to: ${LOG_DIR}" + claude_args: | + --model ${{ env.REVIEW_MODEL }} + --allowedTools "Bash(gh pr comment:*),Bash(gh pr diff:*),Bash(gh pr view:*),Read,Glob,Grep" + continue-on-error: true - name: Add success reaction if: success() && github.event_name == 'issue_comment' diff --git a/package.json b/package.json index 4f7cdf4e..b64232ac 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@kaitranntt/ccs", - "version": "7.16.0", + "version": "7.16.0-dev.5", "description": "Claude Code Switch - Instant profile switching between Claude Sonnet 4.5 and GLM 4.6", "keywords": [ "cli",