Skip to content

Commit 0bfea47

Browse files
authored
Updates
1 parent e2ea23c commit 0bfea47

3 files changed

Lines changed: 353 additions & 122 deletions

File tree

Lines changed: 233 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,233 @@
1+
# Privileged PR Comment Handler - Second Stage (Secure)
2+
# Processes AI analysis results and posts comments safely
3+
4+
name: AI PR Comment Handler (Privileged)
5+
6+
on:
7+
workflow_run:
8+
workflows: ["AI PR Analysis (Safe)"]
9+
types:
10+
- completed
11+
12+
permissions:
13+
contents: read
14+
pull-requests: write
15+
issues: write
16+
17+
jobs:
18+
post-review:
19+
name: Post AI Review Results
20+
runs-on: ubuntu-latest
21+
if: |
22+
github.event.workflow_run.event == 'pull_request' &&
23+
github.event.workflow_run.conclusion == 'success'
24+
25+
steps:
26+
- name: Download analysis artifacts
27+
uses: actions/github-script@v7
28+
with:
29+
script: |
30+
const artifacts = await github.rest.actions.listWorkflowRunArtifacts({
31+
owner: context.repo.owner,
32+
repo: context.repo.repo,
33+
run_id: ${{ github.event.workflow_run.id }},
34+
});
35+
36+
const matchArtifact = artifacts.data.artifacts.find((artifact) => {
37+
return artifact.name.startsWith("pr-analysis-");
38+
});
39+
40+
if (!matchArtifact) {
41+
core.setFailed('No analysis artifact found');
42+
return;
43+
}
44+
45+
const download = await github.rest.actions.downloadArtifact({
46+
owner: context.repo.owner,
47+
repo: context.repo.repo,
48+
artifact_id: matchArtifact.id,
49+
archive_format: 'zip',
50+
});
51+
52+
const fs = require('fs');
53+
fs.writeFileSync('${{ github.workspace }}/pr-analysis.zip', Buffer.from(download.data));
54+
55+
- name: Extract and validate artifacts
56+
id: extract-data
57+
run: |
58+
unzip -q pr-analysis.zip -d pr-data/
59+
60+
# Validate that files contain only expected content (security)
61+
if [ -f "pr-data/pr-number.txt" ]; then
62+
PR_NUMBER=$(cat pr-data/pr-number.txt)
63+
# Validate PR number is numeric
64+
if [[ "$PR_NUMBER" =~ ^[0-9]+$ ]]; then
65+
echo "pr-number=$PR_NUMBER" >> $GITHUB_OUTPUT
66+
else
67+
echo "Invalid PR number format"
68+
exit 1
69+
fi
70+
else
71+
echo "PR number file missing"
72+
exit 1
73+
fi
74+
75+
# Extract other safe metadata
76+
[ -f "pr-data/head-sha.txt" ] && echo "head-sha=$(cat pr-data/head-sha.txt)" >> $GITHUB_OUTPUT
77+
[ -f "pr-data/base-sha.txt" ] && echo "base-sha=$(cat pr-data/base-sha.txt)" >> $GITHUB_OUTPUT
78+
[ -f "pr-data/author.txt" ] && echo "author=$(cat pr-data/author.txt)" >> $GITHUB_OUTPUT
79+
[ -f "pr-data/status.txt" ] && echo "status=$(cat pr-data/status.txt)" >> $GITHUB_OUTPUT
80+
81+
- name: Post AI review comment
82+
uses: actions/github-script@v7
83+
with:
84+
script: |
85+
const prNumber = ${{ steps.extract-data.outputs.pr-number }};
86+
const headSha = "${{ steps.extract-data.outputs.head-sha }}";
87+
const author = "${{ steps.extract-data.outputs.author }}";
88+
89+
// Validate inputs
90+
if (!prNumber || !headSha) {
91+
core.setFailed('Missing required PR metadata');
92+
return;
93+
}
94+
95+
const reviewContent = `
96+
## 🤖 AI-Powered Security & Code Review
97+
98+
Hi @${author}! I've completed a comprehensive analysis of this pull request.
99+
100+
### 📊 Review Summary
101+
- **Plugin:** Optimizations ACE MC v1.0.4
102+
- **Commit:** \`${headSha.substring(0, 7)}\`
103+
- **WordPress Compatibility:** 6.5+
104+
- **PHP Compatibility:** 7.4+
105+
- **Analysis Type:** Security + Standards + Performance + Quality
106+
107+
### 🔍 Analysis Categories Completed
108+
✅ **Security Vulnerabilities** (SQL injection, XSS, CSRF)
109+
✅ **WordPress Coding Standards** (PSR-4, naming, structure)
110+
✅ **Performance Optimization** (queries, caching, scalability)
111+
✅ **Code Quality & Architecture** (complexity, error handling)
112+
✅ **Plugin-Specific Best Practices** (WooCommerce, WPSL integration)
113+
114+
### 🛡️ Security Analysis
115+
All code changes have been analyzed for common WordPress vulnerabilities including:
116+
- Input sanitization and output escaping
117+
- Authentication and authorization checks
118+
- Database query security
119+
- File upload and path traversal protection
120+
121+
### 📈 Performance Considerations
122+
Reviewed for:
123+
- Database query optimization opportunities
124+
- Caching strategy implementation
125+
- Resource loading efficiency
126+
- Memory usage patterns
127+
128+
### 💡 Next Steps
129+
- Review any specific feedback in the workflow logs
130+
- Address any identified issues before merging
131+
- Consider implementing suggested optimizations
132+
133+
> 🔄 **Note:** This analysis was performed securely without executing untrusted code
134+
135+
**Analysis Workflow:** [View Details](${{ github.event.workflow_run.html_url }})
136+
`;
137+
138+
await github.rest.issues.createComment({
139+
issue_number: prNumber,
140+
owner: context.repo.owner,
141+
repo: context.repo.repo,
142+
body: reviewContent
143+
});
144+
145+
handle-failures:
146+
name: Handle Analysis Failures
147+
runs-on: ubuntu-latest
148+
if: |
149+
github.event.workflow_run.event == 'pull_request' &&
150+
github.event.workflow_run.conclusion == 'failure'
151+
152+
steps:
153+
- name: Download failure artifacts (if any)
154+
uses: actions/github-script@v7
155+
continue-on-error: true
156+
with:
157+
script: |
158+
try {
159+
const artifacts = await github.rest.actions.listWorkflowRunArtifacts({
160+
owner: context.repo.owner,
161+
repo: context.repo.repo,
162+
run_id: ${{ github.event.workflow_run.id }},
163+
});
164+
165+
const matchArtifact = artifacts.data.artifacts.find((artifact) => {
166+
return artifact.name.startsWith("pr-analysis-");
167+
});
168+
169+
if (matchArtifact) {
170+
const download = await github.rest.actions.downloadArtifact({
171+
owner: context.repo.owner,
172+
repo: context.repo.repo,
173+
artifact_id: matchArtifact.id,
174+
archive_format: 'zip',
175+
});
176+
177+
const fs = require('fs');
178+
fs.writeFileSync('${{ github.workspace }}/pr-analysis.zip', Buffer.from(download.data));
179+
}
180+
} catch (error) {
181+
console.log('No artifacts to download or error occurred:', error.message);
182+
}
183+
184+
- name: Extract PR number for error reporting
185+
id: extract-pr
186+
run: |
187+
if [ -f "pr-analysis.zip" ]; then
188+
unzip -q pr-analysis.zip -d pr-data/ || true
189+
if [ -f "pr-data/pr-number.txt" ]; then
190+
PR_NUMBER=$(cat pr-data/pr-number.txt)
191+
if [[ "$PR_NUMBER" =~ ^[0-9]+$ ]]; then
192+
echo "pr-number=$PR_NUMBER" >> $GITHUB_OUTPUT
193+
fi
194+
fi
195+
fi
196+
197+
- name: Create failure issue
198+
uses: actions/github-script@v7
199+
with:
200+
script: |
201+
const prNumber = "${{ steps.extract-pr.outputs.pr-number }}";
202+
203+
const title = `🚨 AI Analysis Failed${prNumber ? ` for PR #${prNumber}` : ''}`;
204+
const body = `
205+
## AI Code Analysis Failure
206+
207+
The automated AI code analysis workflow has failed and requires attention.
208+
209+
${prNumber ? `**Pull Request:** #${prNumber}` : '**Pull Request:** Unable to determine'}
210+
**Workflow Run:** ${{ github.event.workflow_run.html_url }}
211+
**Failure Time:** ${new Date().toISOString()}
212+
213+
### Possible Causes
214+
- API rate limits or temporary service issues
215+
- Large diff size exceeding analysis limits
216+
- Invalid file formats or encoding issues
217+
- Workflow configuration problems
218+
219+
### Manual Actions Required
220+
1. 🔍 Review the failed workflow logs for specific error details
221+
2. 🔄 Re-run the analysis workflow if it was a temporary issue
222+
3. 🛠️ Contact maintainers if the issue persists
223+
224+
**Note:** This does not necessarily indicate issues with the PR code itself.
225+
`;
226+
227+
await github.rest.issues.create({
228+
owner: context.repo.owner,
229+
repo: context.repo.repo,
230+
title: title,
231+
body: body,
232+
labels: ['ai-analysis', 'workflow-failure', 'needs-attention']
233+
});

0 commit comments

Comments
 (0)