Add automated PR review workflow with /review command
#3
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 Review on Command | ||
|
Check failure on line 1 in .github/workflows/pr-review-command.yml
|
||
| on: | ||
| # Trigger when an issue comment is created (includes PR comments) | ||
| issue_comment: | ||
| types: [created] | ||
| # Allow manual trigger from GitHub UI | ||
| workflow_dispatch: | ||
| inputs: | ||
| pr_number: | ||
| description: "PR number to review" | ||
| required: true | ||
| type: number | ||
| # TEMPORARY: For testing in PR - REMOVE THIS after merging to main | ||
| pull_request: | ||
| types: [opened, synchronize, reopened] | ||
| # Minimal permissions needed | ||
| permissions: | ||
| contents: read | ||
| pull-requests: write | ||
| issues: write | ||
| jobs: | ||
| # Check if the comment trigger should run the review | ||
| check-comment: | ||
| if: | | ||
| (github.event_name == 'issue_comment' && github.event.issue.pull_request && contains(github.event.comment.body, '/review')) || | ||
| github.event_name == 'pull_request' || | ||
| github.event_name == 'workflow_dispatch' | ||
| runs-on: ubuntu-latest | ||
| outputs: | ||
| should_run: ${{ steps.check.outputs.result }} | ||
| pr_number: ${{ steps.get-pr.outputs.pr_number }} | ||
| steps: | ||
| - name: Get PR number | ||
| id: get-pr | ||
| run: | | ||
| if [ "${{ github.event_name }}" == "pull_request" ]; then | ||
| echo "pr_number=${{ github.event.pull_request.number }}" >> $GITHUB_OUTPUT | ||
| elif [ "${{ github.event_name }}" == "issue_comment" ]; then | ||
| echo "pr_number=${{ github.event.issue.number }}" >> $GITHUB_OUTPUT | ||
| elif [ "${{ github.event_name }}" == "workflow_dispatch" ]; then | ||
| echo "pr_number=${{ inputs.pr_number }}" >> $GITHUB_OUTPUT | ||
| fi | ||
| - name: Check comment conditions | ||
| id: check | ||
| run: | | ||
| echo "Event: ${{ github.event_name }}" | ||
| echo "PR Number: ${{ steps.get-pr.outputs.pr_number }}" | ||
| echo "result=true" >> $GITHUB_OUTPUT | ||
| - name: Add reaction to comment | ||
| if: github.event_name == 'issue_comment' | ||
| uses: actions/github-script@v7 | ||
| with: | ||
| script: | | ||
| await github.rest.reactions.createForIssueComment({ | ||
| owner: context.repo.owner, | ||
| repo: context.repo.repo, | ||
| comment_id: context.payload.comment.id, | ||
| content: 'eyes' | ||
| }); | ||
| # Run the actual review process | ||
| run-review: | ||
| needs: [check-comment] | ||
| if: always() && needs.check-comment.outputs.should_run == 'true' | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - name: Checkout repository | ||
| uses: actions/checkout@v4 | ||
| - name: Get PR details | ||
| id: pr-details | ||
| uses: actions/github-script@v7 | ||
| with: | ||
| script: | | ||
| const prNumber = ${{ needs.check-comment.outputs.pr_number }}; | ||
| const { data: pr } = await github.rest.pulls.get({ | ||
| owner: context.repo.owner, | ||
| repo: context.repo.repo, | ||
| pull_number: prNumber | ||
| }); | ||
| const { data: files } = await github.rest.pulls.listFiles({ | ||
| owner: context.repo.owner, | ||
| repo: context.repo.repo, | ||
| pull_number: prNumber | ||
| }); | ||
| core.setOutput('pr_title', pr.title); | ||
| core.setOutput('pr_author', pr.user.login); | ||
| core.setOutput('files_changed', files.length); | ||
| console.log(`PR #${prNumber}: ${pr.title}`); | ||
| console.log(`Author: ${pr.user.login}`); | ||
| console.log(`Files changed: ${files.length}`); | ||
| - name: Check if API key is available | ||
| id: check-key | ||
| run: | | ||
| if [ -n "${{ secrets.ANTHROPIC_API_KEY }}" ]; then | ||
| echo "has_key=true" >> $GITHUB_OUTPUT | ||
| else | ||
| echo "has_key=false" >> $GITHUB_OUTPUT | ||
| fi | ||
| - name: Run PR Reviewer Agent | ||
| if: steps.check-key.outputs.has_key == 'true' | ||
| id: review | ||
| uses: docker/cagent-action@1f7ec0445e138a587639fc9c046076e22d184349 # v1.0.4 | ||
| with: | ||
| agent: agentcatalog/github-action-pr-reviewer:2.0.0 | ||
| mcp-gateway: true | ||
| anthropic-api-key: ${{ secrets.ANTHROPIC_API_KEY }} | ||
| github-token: ${{ secrets.GITHUB_TOKEN }} | ||
| env: | ||
| ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} | ||
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
| continue-on-error: true | ||
| - name: Simulated Review (No API Key) | ||
| if: steps.check-key.outputs.has_key == 'false' | ||
| id: simulated-review | ||
| run: | | ||
| echo "## 🤖 Simulated PR Review" | ||
| echo "" | ||
| echo "**Note:** This is a test run without the Anthropic API key." | ||
| echo "" | ||
| echo "### PR Details" | ||
| echo "- **Title:** ${{ steps.pr-details.outputs.pr_title }}" | ||
| echo "- **Author:** @${{ steps.pr-details.outputs.pr_author }}" | ||
| echo "- **Files Changed:** ${{ steps.pr-details.outputs.files_changed }}" | ||
| echo "" | ||
| echo "### Workflow Status" | ||
| echo "✅ Workflow triggered successfully" | ||
| echo "✅ PR details retrieved" | ||
| echo "✅ Permissions verified" | ||
| echo "" | ||
| echo "**To enable AI review:** Add \`ANTHROPIC_API_KEY\` to repository secrets" | ||
| - name: Post review comment | ||
| uses: actions/github-script@v7 | ||
| with: | ||
| script: | | ||
| const hasKey = '${{ steps.check-key.outputs.has_key }}' === 'true'; | ||
| const prNumber = ${{ needs.check-comment.outputs.pr_number }}; | ||
| let body; | ||
| if (hasKey) { | ||
| body = `## 🤖 AI PR Review Complete | ||
| The automated PR review has been completed by the AI agent. | ||
| **Triggered by:** ${{ github.event_name === 'workflow_dispatch' ? 'Manual trigger' : github.event_name === 'pull_request' ? 'PR update' : '@' + github.event.comment.user.login }} | ||
| **Workflow Run:** [View Details](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}) | ||
| `; | ||
| } else { | ||
| body = `## 🤖 PR Review Test (Simulated) | ||
| ✅ **Workflow Test Successful!** | ||
| ### PR Details | ||
| - **Title:** ${{ steps.pr-details.outputs.pr_title }} | ||
| - **Author:** @${{ steps.pr-details.outputs.pr_author }} | ||
| - **Files Changed:** ${{ steps.pr-details.outputs.files_changed }} | ||
| ### Status | ||
| ✅ Workflow triggered correctly | ||
| ✅ PR details retrieved successfully | ||
| ✅ Permissions verified | ||
| **Triggered by:** ${{ github.event_name === 'workflow_dispatch' ? 'Manual trigger' : github.event_name === 'pull_request' ? 'PR update' : '@' + github.event.comment.user.login }} | ||
| **Workflow Run:** [View Details](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}) | ||
| --- | ||
| ⚠️ **Note:** To enable full AI-powered reviews, add \`ANTHROPIC_API_KEY\` to repository secrets. | ||
| `; | ||
| } | ||
| await github.rest.issues.createComment({ | ||
| owner: context.repo.owner, | ||
| repo: context.repo.repo, | ||
| issue_number: prNumber, | ||
| body: body | ||
| }); | ||
| - name: Add success reaction | ||
| if: success() && github.event_name == 'issue_comment' | ||
| uses: actions/github-script@v7 | ||
| with: | ||
| script: | | ||
| await github.rest.reactions.createForIssueComment({ | ||
| owner: context.repo.owner, | ||
| repo: context.repo.repo, | ||
| comment_id: context.payload.comment.id, | ||
| content: 'rocket' | ||
| }); | ||
| - name: Add failure reaction | ||
| if: failure() && github.event_name == 'issue_comment' | ||
| uses: actions/github-script@v7 | ||
| with: | ||
| script: | | ||
| await github.rest.reactions.createForIssueComment({ | ||
| owner: context.repo.owner, | ||
| repo: context.repo.repo, | ||
| comment_id: context.payload.comment.id, | ||
| content: 'confused' | ||
| }); | ||