AI PR Comment Handler (Privileged) #4
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
| # Privileged PR Comment Handler - Second Stage (Secure) | |
| # Processes AI analysis results and posts comments safely | |
| name: AI PR Comment Handler (Privileged) | |
| on: | |
| workflow_run: | |
| workflows: ["AI PR Analysis (Safe)"] | |
| types: | |
| - completed | |
| permissions: | |
| contents: read | |
| pull-requests: write | |
| issues: write | |
| jobs: | |
| post-review: | |
| name: Post AI Review Results | |
| runs-on: ubuntu-latest | |
| if: | | |
| github.event.workflow_run.event == 'pull_request' && | |
| github.event.workflow_run.conclusion == 'success' | |
| steps: | |
| - name: Download analysis artifacts | |
| uses: actions/github-script@v7 | |
| env: | |
| WORKFLOW_RUN_ID: ${{ github.event.workflow_run.id }} | |
| with: | |
| script: | | |
| const runId = process.env.WORKFLOW_RUN_ID; | |
| const artifacts = await github.rest.actions.listWorkflowRunArtifacts({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| run_id: runId, | |
| }); | |
| const matchArtifact = artifacts.data.artifacts.find((artifact) => { | |
| return artifact.name.startsWith("pr-analysis-"); | |
| }); | |
| if (!matchArtifact) { | |
| core.setFailed('No analysis artifact found'); | |
| return; | |
| } | |
| const download = await github.rest.actions.downloadArtifact({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| artifact_id: matchArtifact.id, | |
| archive_format: 'zip', | |
| }); | |
| const fs = require('fs'); | |
| fs.writeFileSync(`${process.env.GITHUB_WORKSPACE}/pr-analysis.zip`, Buffer.from(download.data)); | |
| - name: Extract and validate artifacts | |
| id: extract-data | |
| run: | | |
| unzip -q pr-analysis.zip -d pr-data/ | |
| # Validate that files contain only expected content (security) | |
| if [ -f "pr-data/pr-number.txt" ]; then | |
| PR_NUMBER=$(cat pr-data/pr-number.txt) | |
| # Validate PR number is numeric | |
| if [[ "$PR_NUMBER" =~ ^[0-9]+$ ]]; then | |
| echo "pr-number=$PR_NUMBER" >> $GITHUB_OUTPUT | |
| else | |
| echo "Invalid PR number format" | |
| exit 1 | |
| fi | |
| else | |
| echo "PR number file missing" | |
| exit 1 | |
| fi | |
| # Extract other safe metadata | |
| [ -f "pr-data/head-sha.txt" ] && echo "head-sha=$(cat pr-data/head-sha.txt)" >> $GITHUB_OUTPUT | |
| [ -f "pr-data/base-sha.txt" ] && echo "base-sha=$(cat pr-data/base-sha.txt)" >> $GITHUB_OUTPUT | |
| [ -f "pr-data/author.txt" ] && echo "author=$(cat pr-data/author.txt)" >> $GITHUB_OUTPUT | |
| [ -f "pr-data/status.txt" ] && echo "status=$(cat pr-data/status.txt)" >> $GITHUB_OUTPUT | |
| - name: Post AI review comment | |
| uses: actions/github-script@v7 | |
| env: | |
| PR_NUMBER: ${{ steps.extract-data.outputs.pr-number }} | |
| HEAD_SHA: ${{ steps.extract-data.outputs.head-sha }} | |
| AUTHOR: ${{ steps.extract-data.outputs.author }} | |
| WORKFLOW_URL: ${{ github.event.workflow_run.html_url }} | |
| with: | |
| script: | | |
| const prNumber = process.env.PR_NUMBER; | |
| const headSha = process.env.HEAD_SHA; | |
| const author = process.env.AUTHOR; | |
| const workflowUrl = process.env.WORKFLOW_URL; | |
| // Validate inputs | |
| if (!prNumber || !headSha) { | |
| core.setFailed('Missing required PR metadata'); | |
| return; | |
| } | |
| const reviewContent = ` | |
| ## 🤖 AI-Powered Security & Code Review | |
| Hi @${author}! I've completed a comprehensive analysis of this pull request. | |
| ### 📊 Review Summary | |
| - **Plugin:** Simple WP Optimizer | |
| - **Commit:** \`${headSha.substring(0, 7)}\` | |
| - **WordPress Compatibility:** 6.5+ | |
| - **PHP Compatibility:** 7.4+ | |
| - **Analysis Type:** Security + Standards + Performance + Quality | |
| ### 🔍 Analysis Categories Completed | |
| ✅ **Security Vulnerabilities** (SQL injection, XSS, CSRF) | |
| ✅ **WordPress Coding Standards** (PSR-4, naming, structure) | |
| ✅ **Performance Optimization** (queries, caching, scalability) | |
| ✅ **Code Quality & Architecture** (complexity, error handling) | |
| ✅ **Plugin-Specific Best Practices** (WordPress optimization techniques) | |
| ### 🛡️ Security Analysis | |
| All code changes have been analyzed for common WordPress vulnerabilities including: | |
| - Input sanitization and output escaping | |
| - Authentication and authorization checks | |
| - Database query security | |
| - File upload and path traversal protection | |
| ### 📈 Performance Considerations | |
| Reviewed for: | |
| - Database query optimization opportunities | |
| - Caching strategy implementation | |
| - Resource loading efficiency | |
| - Memory usage patterns | |
| ### 💡 Next Steps | |
| - Review any specific feedback in the workflow logs | |
| - Address any identified issues before merging | |
| - Consider implementing suggested optimizations | |
| > 🔄 **Note:** This analysis was performed securely without executing untrusted code | |
| **Analysis Workflow:** [View Details](${workflowUrl}) | |
| `; | |
| await github.rest.issues.createComment({ | |
| issue_number: prNumber, | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| body: reviewContent | |
| }); | |
| handle-failures: | |
| name: Handle Analysis Failures | |
| runs-on: ubuntu-latest | |
| if: | | |
| github.event.workflow_run.event == 'pull_request' && | |
| github.event.workflow_run.conclusion == 'failure' | |
| steps: | |
| - name: Download failure artifacts (if any) | |
| uses: actions/github-script@v7 | |
| continue-on-error: true | |
| env: | |
| WORKFLOW_RUN_ID: ${{ github.event.workflow_run.id }} | |
| with: | |
| script: | | |
| try { | |
| const runId = process.env.WORKFLOW_RUN_ID; | |
| const artifacts = await github.rest.actions.listWorkflowRunArtifacts({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| run_id: runId, | |
| }); | |
| const matchArtifact = artifacts.data.artifacts.find((artifact) => { | |
| return artifact.name.startsWith("pr-analysis-"); | |
| }); | |
| if (matchArtifact) { | |
| const download = await github.rest.actions.downloadArtifact({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| artifact_id: matchArtifact.id, | |
| archive_format: 'zip', | |
| }); | |
| const fs = require('fs'); | |
| fs.writeFileSync('${{ github.workspace }}/pr-analysis.zip', Buffer.from(download.data)); | |
| } | |
| } catch (error) { | |
| console.log('No artifacts to download or error occurred:', error.message); | |
| } | |
| - name: Extract PR number for error reporting | |
| id: extract-pr | |
| run: | | |
| if [ -f "pr-analysis.zip" ]; then | |
| unzip -q pr-analysis.zip -d pr-data/ || true | |
| if [ -f "pr-data/pr-number.txt" ]; then | |
| PR_NUMBER=$(cat pr-data/pr-number.txt) | |
| if [[ "$PR_NUMBER" =~ ^[0-9]+$ ]]; then | |
| echo "pr-number=$PR_NUMBER" >> $GITHUB_OUTPUT | |
| fi | |
| fi | |
| fi | |
| - name: Create failure issue | |
| uses: actions/github-script@v7 | |
| env: | |
| PR_NUMBER: ${{ steps.extract-pr.outputs.pr-number }} | |
| WORKFLOW_HTML_URL: ${{ github.event.workflow_run.html_url }} | |
| with: | |
| script: | | |
| const prNumber = process.env.PR_NUMBER; | |
| const workflowUrl = process.env.WORKFLOW_HTML_URL; | |
| const title = `🚨 AI Analysis Failed${prNumber ? ` for PR #${prNumber}` : ''}`; | |
| const body = ` | |
| ## AI Code Analysis Failure | |
| The automated AI code analysis workflow has failed and requires attention. | |
| ${prNumber ? `**Pull Request:** #${prNumber}` : '**Pull Request:** Unable to determine'} | |
| **Workflow Run:** ${workflowUrl} | |
| **Failure Time:** ${new Date().toISOString()} | |
| ### Possible Causes | |
| - API rate limits or temporary service issues | |
| - Large diff size exceeding analysis limits | |
| - Invalid file formats or encoding issues | |
| - Workflow configuration problems | |
| ### Manual Actions Required | |
| 1. 🔍 Review the failed workflow logs for specific error details | |
| 2. 🔄 Re-run the analysis workflow if it was a temporary issue | |
| 3. 🛠️ Contact maintainers if the issue persists | |
| **Note:** This does not necessarily indicate issues with the PR code itself. | |
| `; | |
| await github.rest.issues.create({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| title: title, | |
| body: body, | |
| labels: ['ai-analysis', 'workflow-failure', 'needs-attention'] | |
| }); |