feat: Add GitHub Actions Codebase Agent workflow #1
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: Codebase Agent | ||
| on: | ||
| issue_comment: | ||
| types: [created] | ||
| pull_request_review_comment: | ||
| types: [created] | ||
| issues: | ||
| types: [opened, labeled] | ||
| pull_request: | ||
| types: [opened, labeled, ready_for_review] | ||
| permissions: | ||
| contents: write | ||
| pull-requests: write | ||
| issues: write | ||
| id-token: write # Required for GCP Workload Identity | ||
| jobs: | ||
| codebase-agent: | ||
| runs-on: ubuntu-latest | ||
| # Only run if: | ||
| # 1. Comment contains @cba mention, OR | ||
| # 2. Issue/PR has 'cba-review' label, OR | ||
| # 3. Issue/PR has 'cba-help' label | ||
| if: | | ||
| (github.event_name == 'issue_comment' && contains(github.event.comment.body, '@cba')) || | ||
| (github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@cba')) || | ||
| contains(github.event.issue.labels.*.name, 'cba-review') || | ||
| contains(github.event.pull_request.labels.*.name, 'cba-review') || | ||
| contains(github.event.issue.labels.*.name, 'cba-help') || | ||
| contains(github.event.pull_request.labels.*.name, 'cba-help') | ||
| steps: | ||
| - name: Checkout repository | ||
| uses: actions/checkout@v4 | ||
| with: | ||
| fetch-depth: 0 # Full history for better context | ||
| - name: Authenticate to Google Cloud | ||
| id: auth | ||
| uses: google-github-actions/auth@v2 | ||
| with: | ||
| workload_identity_provider: ${{ secrets.GCP_WORKLOAD_IDENTITY_PROVIDER }} | ||
| service_account: ${{ secrets.GCP_SERVICE_ACCOUNT }} | ||
| - name: Set up Cloud SDK | ||
| uses: google-github-actions/setup-gcloud@v2 | ||
| - name: Extract @cba command | ||
| id: parse_command | ||
| run: | | ||
| # Parse the @cba mention and extract the command | ||
| COMMENT_BODY="${{ github.event.comment.body }}" | ||
| # Extract text after @cba mention | ||
| if [[ "$COMMENT_BODY" =~ @cba[[:space:]]+(.*) ]]; then | ||
| COMMAND="${BASH_REMATCH[1]}" | ||
| echo "command=$COMMAND" >> $GITHUB_OUTPUT | ||
| echo "has_mention=true" >> $GITHUB_OUTPUT | ||
| else | ||
| # No @cba mention, triggered by label | ||
| echo "has_mention=false" >> $GITHUB_OUTPUT | ||
| # Determine action based on label | ||
| if [[ "${{ contains(github.event.issue.labels.*.name, 'cba-review') || contains(github.event.pull_request.labels.*.name, 'cba-review') }}" == "true" ]]; then | ||
| echo "command=review this PR" >> $GITHUB_OUTPUT | ||
| elif [[ "${{ contains(github.event.issue.labels.*.name, 'cba-help') || contains(github.event.pull_request.labels.*.name, 'cba-help') }}" == "true" ]]; then | ||
| echo "command=help with this issue" >> $GITHUB_OUTPUT | ||
| fi | ||
| fi | ||
| - name: Set up Python | ||
| uses: actions/setup-python@v5 | ||
| with: | ||
| python-version: '3.11' | ||
| - name: Install dependencies | ||
| run: | | ||
| pip install google-cloud-aiplatform anthropic requests | ||
| - name: Run Codebase Agent | ||
| id: run_agent | ||
| env: | ||
| COMMAND: ${{ steps.parse_command.outputs.command }} | ||
| HAS_MENTION: ${{ steps.parse_command.outputs.has_mention }} | ||
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
| ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} | ||
| GCP_PROJECT_ID: ambient-prototypes | ||
| GCP_REGION: us-central1 | ||
| run: | | ||
| python3 << 'PYTHON_SCRIPT' | ||
| import os | ||
| import json | ||
| import requests | ||
| from anthropic import Anthropic | ||
| # Get environment variables | ||
| command = os.environ.get('COMMAND', 'help') | ||
| github_token = os.environ['GITHUB_TOKEN'] | ||
| anthropic_api_key = os.environ['ANTHROPIC_API_KEY'] | ||
| # GitHub context | ||
| github_context = json.loads('''${{ toJson(github) }}''') | ||
| event_name = github_context['event_name'] | ||
| print(f"🤖 Codebase Agent activated!") | ||
| print(f"Command: {command}") | ||
| print(f"Event: {event_name}") | ||
| # Prepare context for Claude | ||
| repo_name = github_context['repository'] | ||
| if event_name in ['issue_comment', 'pull_request_review_comment']: | ||
| issue_number = github_context['event']['issue']['number'] | ||
| issue_url = github_context['event']['issue']['html_url'] | ||
| context_type = "comment" | ||
| elif 'pull_request' in github_context['event']: | ||
| issue_number = github_context['event']['pull_request']['number'] | ||
| issue_url = github_context['event']['pull_request']['html_url'] | ||
| context_type = "pull_request" | ||
| elif 'issue' in github_context['event']: | ||
| issue_number = github_context['event']['issue']['number'] | ||
| issue_url = github_context['event']['issue']['html_url'] | ||
| context_type = "issue" | ||
| # Call Claude API (using Anthropic directly for now) | ||
| # In production, this would call Vertex AI using the GCP service account | ||
| client = Anthropic(api_key=anthropic_api_key) | ||
| prompt = f"""You are the Codebase Agent (CBA) for the {repo_name} repository. | ||
| You've been invoked with the command: {command} | ||
| Context: | ||
| - Type: {context_type} | ||
| - URL: {issue_url} | ||
| - Issue/PR: #{issue_number} | ||
| Please provide a helpful, concise response that addresses the user's request. | ||
| If this is a code review, focus on: | ||
| 1. Code quality and best practices | ||
| 2. Potential bugs or edge cases | ||
| 3. Documentation and testing suggestions | ||
| 4. Security considerations | ||
| If this is a help request, provide: | ||
| 1. Clear explanation of the issue | ||
| 2. Actionable next steps | ||
| 3. Relevant documentation or examples""" | ||
| message = client.messages.create( | ||
| model="claude-3-5-sonnet-20241022", | ||
| max_tokens=2000, | ||
| messages=[{"role": "user", "content": prompt}] | ||
| ) | ||
| response_text = message.content[0].text | ||
| # Save response to file for next step | ||
| with open('cba_response.txt', 'w') as f: | ||
| f.write(response_text) | ||
| print("✅ Codebase Agent response generated") | ||
| PYTHON_SCRIPT | ||
| - name: Post response to GitHub | ||
| env: | ||
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
| run: | | ||
| # Read the response from previous step | ||
| RESPONSE=$(cat cba_response.txt) | ||
| # Determine where to post the comment | ||
| if [[ "${{ github.event_name }}" == "issue_comment" ]] || [[ "${{ github.event_name }}" == "pull_request_review_comment" ]]; then | ||
| # Reply to the comment | ||
| ISSUE_NUMBER="${{ github.event.issue.number }}" | ||
| elif [[ "${{ github.event_name }}" == "pull_request" ]]; then | ||
| ISSUE_NUMBER="${{ github.event.pull_request.number }}" | ||
| elif [[ "${{ github.event_name }}" == "issues" ]]; then | ||
| ISSUE_NUMBER="${{ github.event.issue.number }}" | ||
| fi | ||
| # Post comment using GitHub API | ||
| curl -X POST \ | ||
| -H "Authorization: token $GITHUB_TOKEN" \ | ||
| -H "Accept: application/vnd.github.v3+json" \ | ||
| "https://api.github.com/repos/${{ github.repository }}/issues/$ISSUE_NUMBER/comments" \ | ||
| -d @- << EOF | ||
| { | ||
| "body": "## 🤖 Codebase Agent Response\n\n$RESPONSE\n\n---\n*Triggered by: ${{ github.event_name }} | Powered by Vertex AI*" | ||
| } | ||
| EOF | ||
| echo "✅ Response posted to GitHub" | ||
| - name: Add reaction to triggering comment | ||
| if: github.event_name == 'issue_comment' || github.event_name == 'pull_request_review_comment' | ||
| env: | ||
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
| run: | | ||
| # Add 👀 reaction to show we're processing | ||
| curl -X POST \ | ||
| -H "Authorization: token $GITHUB_TOKEN" \ | ||
| -H "Accept: application/vnd.github.v3+json" \ | ||
| "https://api.github.com/repos/${{ github.repository }}/issues/comments/${{ github.event.comment.id }}/reactions" \ | ||
| -d '{"content":"rocket"}' | ||