Skip to content

Commit 39d2321

Browse files
authored
chore: sync Claude workflows with latest version (#210)
- Updated claude-code-review.yml with comprehensive improvements from terraform-aws-ecr - Updated claude.yml with latest configuration and MCP server integration - Enhanced git state management and diff detection strategies - Added robust error handling and retry logic - Improved workflow summary and troubleshooting information - Added commit SHA verification and cache invalidation
1 parent d5cefb2 commit 39d2321

File tree

2 files changed

+281
-28
lines changed

2 files changed

+281
-28
lines changed

.github/workflows/claude-code-review.yml

Lines changed: 271 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -193,11 +193,81 @@ jobs:
193193
- name: Checkout repository
194194
uses: actions/checkout@v4
195195
with:
196-
fetch-depth: 50 # Optimized depth for most PR scenarios
196+
fetch-depth: 0 # Full history for reliable diff comparisons
197197
token: ${{ secrets.GITHUB_TOKEN }}
198198
# For issue_comment events, checkout the PR branch
199199
ref: ${{ github.event_name == 'issue_comment' && steps.pr-checkout-info.outputs.pr_head_ref || github.ref }}
200200

201+
- name: Refresh git state
202+
id: git-refresh
203+
timeout-minutes: 3
204+
run: |
205+
set -euo pipefail
206+
207+
echo "🔄 Refreshing git state to ensure latest changes are analyzed"
208+
209+
# Get current branch name
210+
CURRENT_BRANCH=$(git branch --show-current || echo "")
211+
CURRENT_SHA=$(git rev-parse HEAD)
212+
213+
echo "Current branch: $CURRENT_BRANCH"
214+
echo "Current SHA: $CURRENT_SHA"
215+
216+
# Fetch all remote references to ensure we have the latest state
217+
echo "Fetching all remote references..."
218+
git fetch --all --prune
219+
220+
# For issue_comment events, ensure we're on the latest commit of the PR branch
221+
if [ "${{ github.event_name }}" = "issue_comment" ]; then
222+
EXPECTED_SHA="${{ steps.pr-checkout-info.outputs.pr_head_sha }}"
223+
echo "Expected SHA from PR: $EXPECTED_SHA"
224+
225+
# Fetch the specific PR branch to get latest changes
226+
PR_HEAD_REF="${{ steps.pr-checkout-info.outputs.pr_head_ref }}"
227+
if [ -n "$PR_HEAD_REF" ]; then
228+
echo "Fetching latest changes for PR branch: $PR_HEAD_REF"
229+
git fetch origin "$PR_HEAD_REF:$PR_HEAD_REF" 2>/dev/null || true
230+
231+
# Reset to the latest commit on the PR branch
232+
echo "Resetting to latest commit on $PR_HEAD_REF"
233+
git reset --hard "origin/$PR_HEAD_REF"
234+
235+
NEW_SHA=$(git rev-parse HEAD)
236+
echo "Updated to SHA: $NEW_SHA"
237+
238+
if [ "$NEW_SHA" != "$CURRENT_SHA" ]; then
239+
echo "⚠️ SHA changed from $CURRENT_SHA to $NEW_SHA - analyzing latest changes"
240+
else
241+
echo "✅ SHA unchanged - no new commits since checkout"
242+
fi
243+
fi
244+
else
245+
# For PR events, ensure we have the latest changes
246+
if [ -n "$CURRENT_BRANCH" ] && [ "$CURRENT_BRANCH" != "HEAD" ]; then
247+
echo "Ensuring latest changes for branch: $CURRENT_BRANCH"
248+
git fetch origin "$CURRENT_BRANCH" 2>/dev/null || true
249+
git reset --hard "origin/$CURRENT_BRANCH" 2>/dev/null || git reset --hard HEAD
250+
251+
NEW_SHA=$(git rev-parse HEAD)
252+
if [ "$NEW_SHA" != "$CURRENT_SHA" ]; then
253+
echo "⚠️ SHA updated from $CURRENT_SHA to $NEW_SHA"
254+
fi
255+
fi
256+
fi
257+
258+
# Final verification
259+
FINAL_SHA=$(git rev-parse HEAD)
260+
FINAL_BRANCH=$(git branch --show-current || echo "detached")
261+
262+
echo "✅ Git state refreshed successfully"
263+
echo "Final branch: $FINAL_BRANCH"
264+
echo "Final SHA: $FINAL_SHA"
265+
266+
# Output for use in subsequent steps
267+
echo "current_sha=$FINAL_SHA" >> $GITHUB_OUTPUT
268+
echo "current_branch=$FINAL_BRANCH" >> $GITHUB_OUTPUT
269+
270+
201271
- name: Parse comment command
202272
id: parse-command
203273
timeout-minutes: 2
@@ -355,25 +425,163 @@ jobs:
355425
id: changes
356426
if: steps.parse-command.outputs.full_analysis == 'false'
357427
run: |
428+
429+
set -euo pipefail
430+
358431
BASE_REF="${{ steps.pr-info.outputs.base_ref }}"
432+
CURRENT_SHA="${{ steps.git-refresh.outputs.current_sha }}"
433+
CURRENT_BRANCH="${{ steps.git-refresh.outputs.current_branch }}"
434+
435+
echo "🔍 Detecting changed files for analysis"
436+
echo "Base branch: $BASE_REF"
437+
echo "Current SHA: $CURRENT_SHA"
438+
echo "Current branch: $CURRENT_BRANCH"
439+
440+
# Ensure we have the base branch reference
441+
echo "Fetching base branch: $BASE_REF"
442+
git fetch origin "$BASE_REF" 2>/dev/null || {
443+
echo "⚠️ Failed to fetch $BASE_REF, trying fallback methods"
444+
git fetch origin 2>/dev/null || true
445+
}
446+
447+
# Multiple fallback strategies for getting changed files
448+
CHANGED_FILES=""
449+
DIFF_SUCCESS=false
450+
451+
# Strategy 1: Standard three-dot diff (preferred)
452+
if [ "$DIFF_SUCCESS" = false ]; then
453+
echo "Trying three-dot diff: origin/$BASE_REF...HEAD"
454+
if CHANGED_FILES=$(git diff --name-only "origin/$BASE_REF...HEAD" 2>/dev/null); then
455+
echo "✅ Three-dot diff successful"
456+
DIFF_SUCCESS=true
457+
else
458+
echo "❌ Three-dot diff failed"
459+
fi
460+
fi
359461
360-
# Simple git fetch and diff
361-
git fetch origin $BASE_REF 2>/dev/null || true
362-
CHANGED_FILES=$(git diff --name-only origin/$BASE_REF...HEAD 2>/dev/null || echo "")
363-
CHANGED_COUNT=$(echo "$CHANGED_FILES" | grep -c . 2>/dev/null || echo "0")
462+
# Strategy 2: Two-dot diff fallback
463+
if [ "$DIFF_SUCCESS" = false ]; then
464+
echo "Trying two-dot diff: origin/$BASE_REF..HEAD"
465+
if CHANGED_FILES=$(git diff --name-only "origin/$BASE_REF..HEAD" 2>/dev/null); then
466+
echo "✅ Two-dot diff successful"
467+
DIFF_SUCCESS=true
468+
else
469+
echo "❌ Two-dot diff failed"
470+
fi
471+
fi
472+
473+
# Strategy 3: Direct branch comparison
474+
if [ "$DIFF_SUCCESS" = false ]; then
475+
echo "Trying direct comparison: origin/$BASE_REF HEAD"
476+
if CHANGED_FILES=$(git diff --name-only "origin/$BASE_REF" HEAD 2>/dev/null); then
477+
echo "✅ Direct comparison successful"
478+
DIFF_SUCCESS=true
479+
else
480+
echo "❌ Direct comparison failed"
481+
fi
482+
fi
364483
365-
# Simple validation
366-
if [ "$CHANGED_COUNT" -eq 0 ]; then
367-
CHANGED_FILES_STR="No files changed"
484+
# Strategy 4: Last resort - use merge-base
485+
if [ "$DIFF_SUCCESS" = false ]; then
486+
echo "Trying merge-base approach"
487+
if MERGE_BASE=$(git merge-base "origin/$BASE_REF" HEAD 2>/dev/null); then
488+
if CHANGED_FILES=$(git diff --name-only "$MERGE_BASE" HEAD 2>/dev/null); then
489+
echo "✅ Merge-base diff successful"
490+
DIFF_SUCCESS=true
491+
fi
492+
fi
493+
fi
494+
495+
# Validate and process results
496+
if [ "$DIFF_SUCCESS" = false ]; then
497+
echo "❌ All diff strategies failed - will analyze full codebase"
498+
CHANGED_FILES=""
499+
CHANGED_COUNT=0
500+
CHANGED_FILES_STR="Unable to determine changed files - will analyze full codebase"
368501
else
369-
CHANGED_FILES_STR=$(echo "$CHANGED_FILES" | tr '\n' ' ')
502+
# Filter out empty lines and count
503+
CHANGED_FILES=$(echo "$CHANGED_FILES" | grep -v '^$' || echo "")
504+
CHANGED_COUNT=$(echo "$CHANGED_FILES" | grep -c . 2>/dev/null || echo "0")
505+
506+
if [ "$CHANGED_COUNT" -eq 0 ]; then
507+
CHANGED_FILES_STR="No files changed"
508+
echo "⚠️ No changed files detected - this might indicate an issue"
509+
else
510+
CHANGED_FILES_STR=$(echo "$CHANGED_FILES" | tr '\n' ' ' | sed 's/[[:space:]]*$//')
511+
echo "✅ Found $CHANGED_COUNT changed files"
512+
fi
370513
fi
371514
372-
echo "Changed files: $CHANGED_FILES_STR"
373-
echo "Total changed files: $CHANGED_COUNT"
515+
# Debug output
516+
echo "📋 Changed files summary:"
517+
echo " Count: $CHANGED_COUNT"
518+
echo " Files: $CHANGED_FILES_STR"
519+
520+
521+
if [ "$CHANGED_COUNT" -gt 0 ]; then
522+
echo "📄 Individual files:"
523+
echo "$CHANGED_FILES" | while IFS= read -r file; do
524+
[ -n "$file" ] && echo " - $file"
525+
done
526+
fi
374527
528+
# Output for next steps
375529
echo "changed_files=$CHANGED_FILES_STR" >> $GITHUB_OUTPUT
376530
echo "changed_count=$CHANGED_COUNT" >> $GITHUB_OUTPUT
531+
echo "diff_successful=$DIFF_SUCCESS" >> $GITHUB_OUTPUT
532+
533+
- name: Verify commit SHA and git state
534+
id: verify-state
535+
timeout-minutes: 2
536+
run: |
537+
set -euo pipefail
538+
539+
echo "🔍 Verifying git state before analysis"
540+
541+
CURRENT_SHA="${{ steps.git-refresh.outputs.current_sha }}"
542+
ACTUAL_SHA=$(git rev-parse HEAD)
543+
CURRENT_BRANCH="${{ steps.git-refresh.outputs.current_branch }}"
544+
545+
# Verify SHA consistency
546+
if [ "$CURRENT_SHA" != "$ACTUAL_SHA" ]; then
547+
echo "⚠️ SHA mismatch detected!"
548+
echo " Expected: $CURRENT_SHA"
549+
echo " Actual: $ACTUAL_SHA"
550+
echo " This indicates a git state issue - attempting to resolve..."
551+
552+
# Update the SHA for consistency
553+
CURRENT_SHA="$ACTUAL_SHA"
554+
echo "current_sha=$ACTUAL_SHA" >> $GITHUB_OUTPUT
555+
else
556+
echo "✅ SHA verification passed: $CURRENT_SHA"
557+
echo "current_sha=$CURRENT_SHA" >> $GITHUB_OUTPUT
558+
fi
559+
560+
# Get additional context for debugging
561+
echo "📊 Git state summary:"
562+
echo " Commit SHA: $CURRENT_SHA"
563+
echo " Branch: $CURRENT_BRANCH"
564+
echo " Repository: ${{ github.repository }}"
565+
echo " Event: ${{ github.event_name }}"
566+
567+
# Get commit info for better context
568+
COMMIT_MSG=$(git log -1 --pretty=format:"%s" 2>/dev/null || echo "Unable to get commit message")
569+
COMMIT_AUTHOR=$(git log -1 --pretty=format:"%an" 2>/dev/null || echo "Unknown")
570+
COMMIT_DATE=$(git log -1 --pretty=format:"%ci" 2>/dev/null || echo "Unknown")
571+
572+
echo " Commit message: $COMMIT_MSG"
573+
echo " Author: $COMMIT_AUTHOR"
574+
echo " Date: $COMMIT_DATE"
575+
576+
# Create unique identifier for cache invalidation
577+
REVIEW_ID="${CURRENT_SHA:0:8}-${{ github.event_name }}-$(date +%s)"
578+
echo " Review ID: $REVIEW_ID"
579+
580+
# Output additional context
581+
echo "commit_message=$COMMIT_MSG" >> $GITHUB_OUTPUT
582+
echo "commit_author=$COMMIT_AUTHOR" >> $GITHUB_OUTPUT
583+
echo "commit_date=$COMMIT_DATE" >> $GITHUB_OUTPUT
584+
echo "review_id=$REVIEW_ID" >> $GITHUB_OUTPUT
377585
378586
- name: Run Claude Code Review
379587
id: claude
@@ -382,18 +590,28 @@ jobs:
382590
with:
383591
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
384592

385-
# Optional: Add specific tools for running tests or linting
386-
# allowed_tools: "Bash(npm run test),Bash(npm run lint),Bash(npm run typecheck)"
593+
# Allow Bash permissions for pre-commit hooks and documentation updates
594+
allowed_tools: "Bash(pre-commit run --files),Bash(terraform fmt),Bash(terraform validate),Bash(terraform-docs)"
387595

388596
# Dynamic prompt based on review mode
389597
direct_prompt: |
598+
🔄 **COMMIT ANALYSIS CONTEXT**
599+
- **Commit SHA**: `${{ steps.verify-state.outputs.current_sha }}`
600+
- **Review ID**: `${{ steps.verify-state.outputs.review_id }}`
601+
- **Branch**: `${{ steps.git-refresh.outputs.current_branch }}`
602+
- **Last Commit**: "${{ steps.verify-state.outputs.commit_message }}" by ${{ steps.verify-state.outputs.commit_author }}
603+
- **Date**: ${{ steps.verify-state.outputs.commit_date }}
604+
605+
---
606+
390607
${{ steps.parse-command.outputs.full_analysis == 'false' && format('
391608
**IMPORTANT: Focus ONLY on the following changed files in this pull request:**
392609
Files changed: {0}
393610
Total files changed: {1}
611+
Diff detection: {2}
394612
395613
DO NOT review or comment on files outside this list unless they are directly impacted by changes in these files.
396-
', steps.changes.outputs.changed_files || 'Unable to determine changed files', steps.changes.outputs.changed_count || '0') || '' }}
614+
', 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') || '' }}
397615
398616
${{ steps.parse-command.outputs.mode == 'hunt' && format('
399617
🕵️ BUG HUNT MODE - Find potential issues quickly:
@@ -444,8 +662,9 @@ jobs:
444662
Be constructive and helpful.
445663
', steps.parse-command.outputs.focus, steps.parse-command.outputs.verbose) || '' }}
446664
447-
# Use sticky comments for better UX
665+
# Use sticky comments with commit-specific cache invalidation
448666
use_sticky_comment: true
667+
# Note: The commit SHA and review ID in the prompt help ensure fresh analysis
449668

450669
- name: Workflow Summary
451670
if: always()
@@ -472,11 +691,34 @@ jobs:
472691
echo "**Full Analysis:** \`${{ steps.parse-command.outputs.full_analysis || 'false' }}\`" >> $GITHUB_STEP_SUMMARY
473692
if [ "${{ steps.parse-command.outputs.full_analysis }}" != "true" ]; then
474693
echo "**Changed Files:** \`${{ steps.changes.outputs.changed_count || '0' }}\` files" >> $GITHUB_STEP_SUMMARY
694+
echo "**Diff Detection:** \`${{ steps.changes.outputs.diff_successful == 'true' && 'Successful' || 'Failed' }}\`" >> $GITHUB_STEP_SUMMARY
475695
fi
476696
echo "**PR Number:** \`${{ steps.pr-info.outputs.pr_number || 'N/A' }}\`" >> $GITHUB_STEP_SUMMARY
477697
echo "**Base Branch:** \`${{ steps.pr-info.outputs.base_ref || 'N/A' }}\`" >> $GITHUB_STEP_SUMMARY
478698
echo "" >> $GITHUB_STEP_SUMMARY
479699
700+
# Git State Information
701+
echo "### 📊 Git State Analysis" >> $GITHUB_STEP_SUMMARY
702+
echo "**Commit SHA:** \`${{ steps.verify-state.outputs.current_sha || steps.git-refresh.outputs.current_sha || 'Unknown' }}\`" >> $GITHUB_STEP_SUMMARY
703+
echo "**Review ID:** \`${{ steps.verify-state.outputs.review_id || 'N/A' }}\`" >> $GITHUB_STEP_SUMMARY
704+
echo "**Current Branch:** \`${{ steps.git-refresh.outputs.current_branch || 'Unknown' }}\`" >> $GITHUB_STEP_SUMMARY
705+
echo "**Last Commit:** \"${{ steps.verify-state.outputs.commit_message || 'Unknown' }}\"" >> $GITHUB_STEP_SUMMARY
706+
echo "**Author:** \`${{ steps.verify-state.outputs.commit_author || 'Unknown' }}\`" >> $GITHUB_STEP_SUMMARY
707+
echo "**Date:** \`${{ steps.verify-state.outputs.commit_date || 'Unknown' }}\`" >> $GITHUB_STEP_SUMMARY
708+
echo "" >> $GITHUB_STEP_SUMMARY
709+
710+
# Analysis Scope Details
711+
if [ "${{ steps.parse-command.outputs.full_analysis }}" != "true" ] && [ "${{ steps.changes.outputs.changed_count || '0' }}" -gt "0" ]; then
712+
echo "### 📄 Files Being Analyzed" >> $GITHUB_STEP_SUMMARY
713+
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
714+
echo "${{ steps.changes.outputs.changed_files }}" | tr ' ' '\n' | grep -v '^$' | head -20 >> $GITHUB_STEP_SUMMARY
715+
if [ "${{ steps.changes.outputs.changed_count }}" -gt "20" ]; then
716+
echo "... and $((${{ steps.changes.outputs.changed_count }} - 20)) more files" >> $GITHUB_STEP_SUMMARY
717+
fi
718+
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
719+
echo "" >> $GITHUB_STEP_SUMMARY
720+
fi
721+
480722
# Available Commands
481723
echo "### 📝 Available Commands" >> $GITHUB_STEP_SUMMARY
482724
echo "Comment any of these in PRs to trigger specific review types:" >> $GITHUB_STEP_SUMMARY
@@ -506,8 +748,19 @@ jobs:
506748
# Performance & Reliability Info
507749
echo "" >> $GITHUB_STEP_SUMMARY
508750
echo "### ⚡ Performance & Reliability" >> $GITHUB_STEP_SUMMARY
509-
echo "- 🚀 Optimized git operations with configurable fetch depth" >> $GITHUB_STEP_SUMMARY
510-
echo "- 🔄 Automatic retry logic for network operations" >> $GITHUB_STEP_SUMMARY
751+
echo "- 🚀 Full git history fetch for reliable diff comparisons" >> $GITHUB_STEP_SUMMARY
752+
echo "- 🔄 Automatic git state refresh and commit SHA verification" >> $GITHUB_STEP_SUMMARY
753+
echo "- 🎯 Multiple fallback strategies for change detection" >> $GITHUB_STEP_SUMMARY
511754
echo "- ⏱️ Timeout protection prevents runaway executions" >> $GITHUB_STEP_SUMMARY
512755
echo "- 🛡️ Comprehensive error handling and validation" >> $GITHUB_STEP_SUMMARY
513-
echo "- 📊 Enhanced logging for troubleshooting" >> $GITHUB_STEP_SUMMARY
756+
echo "- 📊 Enhanced logging and debug information" >> $GITHUB_STEP_SUMMARY
757+
echo "- 🔐 Cache invalidation via commit-specific review IDs" >> $GITHUB_STEP_SUMMARY
758+
759+
# Troubleshooting section
760+
echo "" >> $GITHUB_STEP_SUMMARY
761+
echo "### 🔧 Troubleshooting" >> $GITHUB_STEP_SUMMARY
762+
echo "If the review doesn't detect recent changes:" >> $GITHUB_STEP_SUMMARY
763+
echo "1. Check the commit SHA matches your latest changes" >> $GITHUB_STEP_SUMMARY
764+
echo "2. Verify the diff detection was successful" >> $GITHUB_STEP_SUMMARY
765+
echo "3. Review the git state analysis above" >> $GITHUB_STEP_SUMMARY
766+
echo "4. Try \`codebot hunt --full\` to analyze the entire codebase" >> $GITHUB_STEP_SUMMARY

.github/workflows/claude.yml

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,15 @@ jobs:
4040
additional_permissions: |
4141
actions: read
4242
43+
# Optional: Specify model (defaults to Claude Sonnet 4, uncomment for Claude Opus 4)
44+
# model: "claude-opus-4-20250514"
45+
46+
# Optional: Customize the trigger phrase (default: @claude)
47+
# trigger_phrase: "/claude"
48+
49+
# Optional: Trigger when specific user is assigned to an issue
50+
# assignee_trigger: "claude-bot"
51+
4352
# MCP Configuration for Terraform and Context7 documentation access
4453
mcp_config: |
4554
{
@@ -64,21 +73,12 @@ jobs:
6473
# Allow Bash permissions for pre-commit hooks and documentation updates + MCP tools
6574
allowed_tools: "Bash(pre-commit run --files),Bash(terraform fmt),Bash(terraform validate),Bash(terraform-docs),mcp__terraform-server__getProviderDocs,mcp__terraform-server__resolveProviderDocID,mcp__terraform-server__searchModules,mcp__terraform-server__moduleDetails,mcp__context7__resolve-library-id,mcp__context7__get-library-docs"
6675

67-
# Optional: Specify model (defaults to Claude Sonnet 4, uncomment for Claude Opus 4)
68-
# model: "claude-opus-4-20250514"
69-
70-
# Optional: Customize the trigger phrase (default: @claude)
71-
# trigger_phrase: "/claude"
72-
73-
# Optional: Trigger when specific user is assigned to an issue
74-
# assignee_trigger: "claude-bot"
75-
7676
# Optional: Add custom instructions for Claude to customize its behavior for your project
7777
# custom_instructions: |
7878
# Follow our coding standards
7979
# Ensure all new code has tests
8080
# Use TypeScript for new files
81-
81+
8282
# Optional: Custom environment variables for Claude
8383
# claude_env: |
8484
# NODE_ENV: test

0 commit comments

Comments
 (0)