dev-inf: add GitHub Actions workflows for issue auto-solving #4
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: PR Comment Addresser | ||
| on: | ||
| pull_request_review_comment: | ||
| types: [created] | ||
| concurrency: | ||
| group: autosolve-pr-${{ github.event.pull_request.number }} | ||
| cancel-in-progress: true | ||
| jobs: | ||
| address-review-comments: | ||
| runs-on: ubuntu-latest | ||
| timeout-minutes: 60 | ||
| # Only trigger for: | ||
| # - PRs with 'o-autosolver' label | ||
| # - Comments NOT from the bot itself | ||
| # - Comments NOT containing our response marker (prevents loops) | ||
| if: | | ||
| contains(github.event.pull_request.labels.*.name, 'o-autosolver') && | ||
| github.actor != 'github-actions[bot]' && | ||
| github.actor != 'crdb-autosolver' && | ||
| !contains(github.event.comment.body, '[autosolve-response]') | ||
| permissions: | ||
| contents: write | ||
| pull-requests: write | ||
| id-token: write | ||
| steps: | ||
| - name: Checkout PR branch from fork | ||
| uses: actions/checkout@v5 | ||
| with: | ||
| repository: ${{ github.event.pull_request.head.repo.full_name }} | ||
| ref: ${{ github.event.pull_request.head.ref }} | ||
| fetch-depth: 0 | ||
| token: ${{ secrets.AUTOSOLVER_PAT }} | ||
| - name: Authenticate to Google Cloud | ||
| uses: 'google-github-actions/auth@v3' | ||
| with: | ||
| project_id: 'vertex-model-runners' | ||
| service_account: '[email protected]' | ||
| workload_identity_provider: 'projects/72497726731/locations/global/workloadIdentityPools/ai-review/providers/ai-review' | ||
| - name: Fetch all review comments | ||
| id: fetch_comments | ||
| env: | ||
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
| run: | | ||
| # Get all review comments on this PR | ||
| COMMENTS=$(gh api repos/${{ github.repository }}/pulls/${{ github.event.pull_request.number }}/comments) | ||
| { | ||
| echo 'comments<<EOF' | ||
| echo "$COMMENTS" | ||
| echo 'EOF' | ||
| } >> "$GITHUB_OUTPUT" | ||
| - name: Address review comments | ||
| id: address | ||
| uses: cockroachdb/claude-code-action@v1 | ||
| env: | ||
| ANTHROPIC_VERTEX_PROJECT_ID: vertex-model-runners | ||
| CLOUD_ML_REGION: us-east5 | ||
| # Pass user-controlled content via env vars to prevent prompt injection | ||
| COMMENT_USER: ${{ github.event.comment.user.login }} | ||
| COMMENT_PATH: ${{ github.event.comment.path }} | ||
| COMMENT_LINE: ${{ github.event.comment.line }} | ||
| COMMENT_BODY: ${{ github.event.comment.body }} | ||
| ALL_COMMENTS: ${{ steps.fetch_comments.outputs.comments }} | ||
| with: | ||
| github_token: ${{ secrets.GITHUB_TOKEN }} | ||
| use_vertex: "true" | ||
| claude_args: | | ||
| --model claude-opus-4-5@20251101 | ||
| --allowedTools "Read,Write,Edit,Grep,Glob,Bash(./dev test:*),Bash(./dev testlogic:*),Bash(./dev build:*),Bash(./dev generate:*),Bash(git:*)" | ||
| prompt: | | ||
| PR #${{ github.event.pull_request.number }} has received review comments. | ||
| The review comment details are provided in environment variables: | ||
| - COMMENT_USER: The username of the commenter | ||
| - COMMENT_PATH: The file path the comment is on | ||
| - COMMENT_LINE: The line number | ||
| - COMMENT_BODY: The comment text | ||
| - ALL_COMMENTS: JSON array of all review comments on this PR | ||
| Instructions: | ||
| 1. Read CLAUDE.md for project conventions | ||
| 2. Read the environment variables to understand the review feedback | ||
| 3. Address the review feedback by making code changes | ||
| 4. Run relevant tests to verify changes | ||
| 5. Stage all changes with git add | ||
| When formatting commits, follow the guidelines in CLAUDE.md. | ||
| Respond with a concise summary of changes made to address each comment. | ||
| - name: Extract Claude Result | ||
| id: claude_result | ||
| if: steps.address.conclusion == 'success' | ||
| run: | | ||
| if [ ! -f "${{ steps.address.outputs.execution_file }}" ]; then | ||
| echo "::error::Execution file not found: ${{ steps.address.outputs.execution_file }}" | ||
| exit 1 | ||
| fi | ||
| RESULT=$(jq -r '.[] | select(.type == "result") | .result' "${{ steps.address.outputs.execution_file }}") || { | ||
| echo "::error::Failed to parse execution file with jq" | ||
| exit 1 | ||
| } | ||
| if [ -z "$RESULT" ]; then | ||
| echo "::error::No result found in execution file" | ||
| exit 1 | ||
| fi | ||
| { | ||
| echo 'result<<EOF' | ||
| echo "$RESULT" | ||
| echo 'EOF' | ||
| } >> "$GITHUB_OUTPUT" | ||
| - name: Commit and push changes | ||
| id: commit | ||
| env: | ||
| AUTOSOLVER_PAT: ${{ secrets.AUTOSOLVER_PAT }} | ||
| run: | | ||
| git config user.name "crdb-autosolver" | ||
| git config user.email "[email protected]" | ||
| # Check if there are staged changes (Claude should have staged them) | ||
| # If no staged changes, also check for unstaged changes that need staging | ||
| if git diff --quiet --cached; then | ||
| # No staged changes - check if Claude made changes but forgot to stage | ||
| if ! git diff --quiet; then | ||
| echo "::warning::Changes detected but not staged. Staging all changes." | ||
| git add -A | ||
| else | ||
| echo "No staged changes to commit" | ||
| echo "pushed=false" >> "$GITHUB_OUTPUT" | ||
| exit 0 | ||
| fi | ||
| fi | ||
| # Check authorship before amending - only amend if we authored the commit | ||
| AUTHOR_EMAIL=$(git log -1 --format='%ae') | ||
| if [ "$AUTHOR_EMAIL" = "[email protected]" ]; then | ||
| # Check if staged changes differ from HEAD before amending | ||
| if git diff --cached --quiet HEAD; then | ||
| echo "Staged changes are identical to HEAD, nothing to amend" | ||
| echo "pushed=false" >> "$GITHUB_OUTPUT" | ||
| exit 0 | ||
| fi | ||
| # Amend the existing commit with the new changes | ||
| git commit --amend --no-edit | ||
| else | ||
| # Create a new commit if we didn't author the original | ||
| git commit -m "Address review comments | ||
| Generated by Claude Code Auto-Solver | ||
| Co-Authored-By: Claude <[email protected]>" | ||
| fi | ||
| # Force push to the fork | ||
| # NOTE: This is safe because this workflow only runs on PRs with 'o-autosolver' label, | ||
| # which are bot-owned branches. We never force push to branches owned by humans. | ||
| git push --force origin ${{ github.event.pull_request.head.ref }} | ||
| echo "pushed=true" >> "$GITHUB_OUTPUT" | ||
| - name: Post summary comment | ||
| if: steps.commit.outputs.pushed == 'true' | ||
| env: | ||
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
| run: | | ||
| # Create comment with marker to prevent infinite loops | ||
| gh pr comment ${{ github.event.pull_request.number }} --body "[autosolve-response] | ||
| I've addressed the review comments and pushed updates. | ||
| **Changes made:** | ||
| ${{ steps.claude_result.outputs.result }} | ||
| Please review the updated code." | ||
| - name: Post no-changes comment | ||
| if: steps.commit.outputs.pushed == 'false' && steps.address.conclusion == 'success' | ||
| env: | ||
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
| run: | | ||
| gh pr comment ${{ github.event.pull_request.number }} --body "[autosolve-response] | ||
| I reviewed the comments but no code changes were necessary. | ||
| **Analysis:** | ||
| ${{ steps.claude_result.outputs.result }}" | ||