Skip to content

Commit bf61217

Browse files
authored
Updates
1 parent ed2c3db commit bf61217

5 files changed

Lines changed: 549 additions & 10 deletions

File tree

.github/copilot-instructions.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ Coding standards, domain knowledge, and preferences that AI should follow.
3636
- All scripts written in **Bash** following Unix/Linux best practices
3737
- Use proper error handling: `set -e`, appropriate exit codes, comprehensive error checking
3838
- Variable naming: `UPPER_CASE` for globals, `lower_case` for locals
39-
- Include shebang lines: `#!/usr/bin/env bash`
39+
- Include shebang lines: `# ! /usr/bin/env bash` (standard bash shebang)
4040
- Proper quoting to prevent word splitting and glob expansion
4141
- Function-based organization to avoid repetition
4242
- Comprehensive logging and user feedback during installation
Lines changed: 262 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,262 @@
1+
# Gemini AI-Powered Code Analysis
2+
# Analyzes code changes in PRs, pushes, and branches - FOCUSES ON CODE CHANGES
3+
4+
name: AI Code Analysis
5+
6+
on:
7+
pull_request:
8+
types: [opened, synchronize, reopened]
9+
push:
10+
branches: [main, develop, 'feature/*', 'bugfix/*']
11+
workflow_dispatch:
12+
13+
# Cancel previous workflow runs for the same context
14+
concurrency:
15+
group: ${{ github.workflow }}-${{ github.event_name }}-${{ github.event.number || github.ref }}
16+
cancel-in-progress: true
17+
18+
permissions:
19+
contents: read
20+
pull-requests: write
21+
issues: write
22+
23+
jobs:
24+
ai-analysis:
25+
name: AI Analysis & Assistant
26+
runs-on: ubuntu-latest
27+
28+
steps:
29+
- name: Checkout code
30+
uses: actions/checkout@v5
31+
with:
32+
fetch-depth: 0
33+
34+
- name: Setup Node.js for Google AI SDK
35+
uses: actions/setup-node@v5
36+
with:
37+
node-version: '20'
38+
39+
- name: Get Code Changes
40+
id: get-changes
41+
env:
42+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
43+
EVENT_NAME: ${{ github.event_name }}
44+
BASE_SHA: ${{ github.event.before || '' }}
45+
HEAD_SHA: ${{ github.sha }}
46+
REPO_FULL_NAME: ${{ github.repository }}
47+
run: |
48+
echo "📋 Collecting code changes for analysis..."
49+
echo "🔍 Debug info: BASE_SHA=$BASE_SHA, HEAD_SHA=$HEAD_SHA"
50+
51+
if [ "$EVENT_NAME" = "pull_request" ]; then
52+
# For PRs, get the diff between base and head
53+
PR_BASE_SHA="${{ github.event.pull_request.base.sha }}"
54+
PR_HEAD_SHA="${{ github.event.pull_request.head.sha }}"
55+
echo "🔍 PR Debug: BASE=$PR_BASE_SHA, HEAD=$PR_HEAD_SHA"
56+
57+
curl -s -H "Authorization: token $GITHUB_TOKEN" \
58+
-H "Accept: application/vnd.github.v3.diff" \
59+
"https://api.github.com/repos/$REPO_FULL_NAME/compare/$PR_BASE_SHA..$PR_HEAD_SHA" \
60+
> code_changes.diff
61+
62+
if [ $? -ne 0 ] || [ ! -s code_changes.diff ]; then
63+
echo "⚠️ API diff failed, using git diff..."
64+
git diff $PR_BASE_SHA..$PR_HEAD_SHA > code_changes.diff
65+
fi
66+
67+
elif [ "$EVENT_NAME" = "push" ]; then
68+
# For pushes, get the diff from the previous commit
69+
if [ -n "$BASE_SHA" ] && [ "$BASE_SHA" != "0000000000000000000000000000000000000000" ]; then
70+
echo "🔍 Push Debug: Comparing $BASE_SHA to $HEAD_SHA"
71+
72+
# Try API first with better error checking
73+
echo "🌐 Attempting GitHub API diff..."
74+
HTTP_CODE=$(curl -s -w "%{http_code}" \
75+
-H "Authorization: token $GITHUB_TOKEN" \
76+
-H "Accept: application/vnd.github.v3.diff" \
77+
"https://api.github.com/repos/$REPO_FULL_NAME/compare/$BASE_SHA..$HEAD_SHA" \
78+
-o code_changes.diff)
79+
80+
echo "🔍 API returned HTTP $HTTP_CODE"
81+
82+
# Check if API call was successful (200 status and file has content)
83+
if [ "$HTTP_CODE" != "200" ] || [ ! -s code_changes.diff ]; then
84+
echo "⚠️ API diff failed (HTTP $HTTP_CODE), using git diff..."
85+
86+
# Use git diff as fallback
87+
git diff $BASE_SHA..$HEAD_SHA > code_changes.diff
88+
89+
# If git diff also fails or is empty, use git show
90+
if [ ! -s code_changes.diff ]; then
91+
echo "⚠️ No diff available, showing recent commit changes..."
92+
git show --stat $HEAD_SHA > code_changes.diff
93+
echo "" >> code_changes.diff
94+
git show $HEAD_SHA >> code_changes.diff
95+
fi
96+
else
97+
echo "✅ GitHub API diff successful"
98+
fi
99+
else
100+
echo "📄 Initial commit or no previous commit - showing current files..."
101+
git show --name-only $HEAD_SHA | head -10 | while read file; do
102+
if [ -f "$file" ]; then
103+
echo "=== $file ===" >> code_changes.diff
104+
head -50 "$file" >> code_changes.diff
105+
echo "" >> code_changes.diff
106+
fi
107+
done
108+
fi
109+
else
110+
echo "No code changes available for this event type" > code_changes.diff
111+
fi
112+
113+
# Check if we got changes
114+
if [ -s code_changes.diff ]; then
115+
echo "✅ Code changes collected: $(wc -l < code_changes.diff) lines"
116+
echo "changes-available=true" >> $GITHUB_OUTPUT
117+
else
118+
echo "⚠️ No code changes found"
119+
echo "changes-available=false" >> $GITHUB_OUTPUT
120+
fi
121+
122+
- name: Install Google AI SDK and Create Analysis Script
123+
run: |
124+
echo "🔧 Installing Google AI SDK..."
125+
npm install @google/generative-ai
126+
127+
echo "📦 Creating Gemini analysis script..."
128+
cat > gemini-analyze.js << 'SCRIPT_EOF'
129+
const { GoogleGenerativeAI } = require('@google/generative-ai');
130+
const fs = require('fs');
131+
132+
async function analyzeCode() {
133+
try {
134+
const apiKey = process.env.GEMINI_API_KEY;
135+
if (!apiKey) {
136+
throw new Error('GEMINI_API_KEY environment variable not found');
137+
}
138+
139+
console.log('🔑 API key configured, length:', apiKey.length);
140+
console.log('🤖 Initializing Gemini AI...');
141+
142+
const genAI = new GoogleGenerativeAI(apiKey);
143+
const model = genAI.getGenerativeModel({ model: "gemini-1.5-flash" });
144+
145+
const prompt = fs.readFileSync('analysis_prompt.txt', 'utf8');
146+
console.log('📝 Prompt loaded, size:', prompt.length, 'characters');
147+
148+
console.log('🚀 Generating analysis...');
149+
const result = await model.generateContent(prompt);
150+
const response = await result.response;
151+
const text = response.text();
152+
153+
fs.writeFileSync('ai_analysis_result.txt', text);
154+
console.log('✅ Analysis completed successfully');
155+
console.log('📄 Result size:', text.length, 'characters');
156+
157+
} catch (error) {
158+
console.error('❌ Gemini analysis failed:', error.message);
159+
console.error('🔍 Full error details:', error);
160+
161+
const fallbackContent = [
162+
'## 🤖 AI Analysis Status',
163+
'',
164+
'The automated AI analysis encountered an issue: ' + error.message,
165+
'',
166+
'This may be due to:',
167+
'- API key configuration issues',
168+
'- Network connectivity problems',
169+
'- Gemini API rate limits or service issues',
170+
'- Invalid prompt format or size',
171+
'',
172+
'### Manual Review Recommended',
173+
'Please conduct a manual code review focusing on:',
174+
'- Linux security best practices',
175+
'- Bash scripting standards compliance',
176+
'- LEMP stack performance considerations',
177+
'- Server automation requirements',
178+
'- Nginx, PHP, MariaDB, Redis security configurations',
179+
'',
180+
'The PR can still be reviewed and merged based on manual inspection.'
181+
].join('\n');
182+
183+
fs.writeFileSync('ai_analysis_result.txt', fallbackContent);
184+
process.exit(1);
185+
}
186+
}
187+
188+
analyzeCode().catch(error => {
189+
console.error('Fatal error:', error);
190+
process.exit(1);
191+
});
192+
SCRIPT_EOF
193+
194+
echo "✅ Analysis script created successfully"
195+
196+
- name: Create Analysis Prompt
197+
env:
198+
PR_TITLE: ${{ github.event.pull_request.title || format('Push Analysis - {0}', github.ref_name) }}
199+
PR_AUTHOR: ${{ github.event.pull_request.user.login || github.actor }}
200+
CHANGES_AVAILABLE: ${{ steps.get-changes.outputs.changes-available }}
201+
run: |
202+
echo "📝 Creating analysis prompt..."
203+
echo "You are an expert Linux system administrator, bash scripting specialist, and LEMP stack automation consultant." > analysis_prompt.txt
204+
echo "" >> analysis_prompt.txt
205+
echo "CRITICAL INSTRUCTION: FOCUS ON THE CODE CHANGES AND PROVIDE SECURITY AND CONFIGURATION ANALYSIS." >> analysis_prompt.txt
206+
echo "Analyze what was changed, added, or removed and review those specific server automation modifications." >> analysis_prompt.txt
207+
echo "" >> analysis_prompt.txt
208+
echo "Context: $PR_TITLE by @$PR_AUTHOR" >> analysis_prompt.txt
209+
echo "" >> analysis_prompt.txt
210+
echo "Please analyze this EngineScript server automation code for:" >> analysis_prompt.txt
211+
echo "1. Security vulnerabilities in bash scripts and server configurations" >> analysis_prompt.txt
212+
echo "2. Linux system administration best practices compliance" >> analysis_prompt.txt
213+
echo "3. LEMP stack performance and security considerations" >> analysis_prompt.txt
214+
echo "4. Server automation and deployment best practice recommendations" >> analysis_prompt.txt
215+
echo "5. Nginx, PHP, MariaDB, and Redis configuration correctness" >> analysis_prompt.txt
216+
echo "6. Cloudflare integration and SSL/TLS security" >> analysis_prompt.txt
217+
echo "" >> analysis_prompt.txt
218+
echo "Provide specific, actionable feedback for server administration improvements." >> analysis_prompt.txt
219+
echo "" >> analysis_prompt.txt
220+
221+
# Add the actual code changes
222+
if [ "$CHANGES_AVAILABLE" = "true" ]; then
223+
echo "Here are the code changes to analyze:" >> analysis_prompt.txt
224+
echo "" >> analysis_prompt.txt
225+
cat code_changes.diff >> analysis_prompt.txt
226+
else
227+
echo "No code changes were detected in this commit." >> analysis_prompt.txt
228+
fi
229+
230+
- name: Run AI Analysis
231+
id: ai-analysis
232+
env:
233+
GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }}
234+
run: |
235+
echo "🤖 Starting AI analysis with official Google SDK..."
236+
echo "📝 Prompt file size: $(wc -c < analysis_prompt.txt) bytes"
237+
238+
if node gemini-analyze.js; then
239+
echo "analysis-success=true" >> $GITHUB_OUTPUT
240+
echo "✅ AI analysis completed successfully"
241+
else
242+
echo "analysis-success=false" >> $GITHUB_OUTPUT
243+
echo "❌ AI analysis failed - check logs for details"
244+
fi
245+
246+
- name: Output Analysis Results
247+
env:
248+
PR_NUMBER: ${{ github.event.number || '' }}
249+
IS_PR: ${{ github.event_name == 'pull_request' }}
250+
EVENT_NAME: ${{ github.event_name }}
251+
run: |
252+
echo "📊 Analysis Results for $EVENT_NAME event:"
253+
echo "============================================================"
254+
255+
if [ -f ai_analysis_result.txt ]; then
256+
cat ai_analysis_result.txt
257+
else
258+
echo "❌ Analysis result file not found"
259+
fi
260+
261+
echo "============================================================"
262+
echo "✅ Analysis output complete"

0 commit comments

Comments
 (0)