Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
139 changes: 139 additions & 0 deletions .github/workflows/ai-code-review.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
name: AI Code Review

on:
pull_request:
types: [opened, synchronize]
paths:
- '**.js'
- '**.jsx'
- '**.ts'
- '**.tsx'

jobs:
ai-review:
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write

steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Get changed files
id: changed-files
run: |
CHANGED_FILES=$(git diff --name-only --diff-filter=AM ${{ github.event.pull_request.base.sha }} ${{ github.sha }} | grep -E '\.(js|jsx|ts|tsx)$' | head -3)
echo "files<<EOF" >> $GITHUB_OUTPUT
echo "$CHANGED_FILES" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT

- name: Setup Node.js
if: steps.changed-files.outputs.files != ''
uses: actions/setup-node@v4
with:
node-version: '22'

- name: AI Code Review
if: steps.changed-files.outputs.files != ''
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
run: |
npm install openai

cat > ai-review.mjs << 'SCRIPT_EOF'
import OpenAI from 'openai';
import { readFileSync } from 'fs';

const openai = new OpenAI({
apiKey: process.env.OPENAI_API_KEY
});

const files = process.env.CHANGED_FILES.split('\n').filter(f => f.trim());

console.log('Reviewing files:', files);

let allReviews = '';

for (const file of files) {
try {
const content = readFileSync(file, 'utf8');

console.log('Reviewing ' + file + '...');

const response = await openai.chat.completions.create({
model: 'gpt-3.5-turbo',
messages: [{
role: 'system',
content: 'You are an expert code reviewer. For each issue found, provide: 1) Issue description, 2) Why it matters, 3) Specific code fix with BEFORE and AFTER examples. Format each issue clearly with the file line reference if possible. Focus on: bugs, security, performance, best practices, accessibility, and React-specific issues.'
}, {
role: 'user',
content: 'Review this code from ' + file + ' and provide specific fixes:\n\n```javascript\n' + content.slice(0, 3000) + '\n```\n\nFor each issue, show:\n- Issue: [description]\n- Why: [explanation]\n- Fix: [before/after code example]'
}],
max_tokens: 1000,
temperature: 0.3
});

const review = response.choices[0].message.content;
allReviews += '\n## File: ' + file + '\n\n' + review + '\n\n---\n';

} catch (error) {
console.error('Error reviewing ' + file + ':', error.message);
allReviews += '\n## File: ' + file + '\n\nCould not review this file.\n\n---\n';
}
}

const fs = await import('fs');
fs.writeFileSync('ai-review-output.txt', allReviews);

SCRIPT_EOF

export CHANGED_FILES="${{ steps.changed-files.outputs.files }}"
node ai-review.mjs

- name: Post AI Review Comment
if: steps.changed-files.outputs.files != ''
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');

let reviewContent = '';
try {
reviewContent = fs.readFileSync('ai-review-output.txt', 'utf8');
} catch (error) {
reviewContent = 'No review content generated.';
}

const header = '## AI Code Review\n\n';
const footer = '\n\n---\n*Powered by OpenAI GPT-3.5 | Automated Code Review*';
const comment = header + reviewContent + footer;

const { data: comments } = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
});

const botComment = comments.find(comment =>
comment.user.type === 'Bot' &&
comment.body.includes('AI Code Review')
);

if (botComment) {
await github.rest.issues.updateComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: botComment.id,
body: comment
});
} else {
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: comment
});
}
89 changes: 89 additions & 0 deletions .github/workflows/scheduled-health-check.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
name: Daily Health Check

on:
schedule:
# Runs every day at 9 AM UTC
- cron: '0 9 1 * *' # 1st day of every month at 9 AM UTC
workflow_dispatch: # Allow manual trigger for testing

jobs:
health-check:
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '22'
cache: 'npm'

- name: Install dependencies
run: npm ci

- name: Run tests
id: tests
run: npm test -- --passWithNoTests --watchAll=false
continue-on-error: true

- name: Check build
id: build
run: npm run build
continue-on-error: true
env:
CI: false

- name: Verify build output
run: |
if [ ! -d "build" ]; then
echo "Build directory not found!"
exit 1
fi
BUILD_SIZE=$(du -sh build | cut -f1)
echo "Build successful! Size: $BUILD_SIZE"
echo "BUILD_SIZE=$BUILD_SIZE" >> $GITHUB_ENV

- name: Check dependencies for security issues
run: npm audit --audit-level=high || echo "Security vulnerabilities found"
continue-on-error: true

- name: Display summary
run: |
echo "## Health Check Summary"
echo "Tests: ${{ steps.tests.outcome }}"
echo "Build: ${{ steps.build.outcome }}"
echo "Build Size: $BUILD_SIZE"

- name: Create issue on failure
if: failure()
uses: actions/github-script@v7
with:
script: |
const date = new Date().toISOString().split('T')[0];
const runUrl = context.payload.repository.html_url + '/actions/runs/' + context.runId;

const title = 'Health Check Failed - ' + date;
const body = '# Health Check Failure Report\n\n' +
'**Date:** ' + date + '\n' +
'**Workflow:** Daily Health Check\n' +
'**Status:** Failed\n\n' +
'## Details\n\n' +
'The automated health check has detected issues with the repository.\n\n' +
'### Failed Steps:\n' +
'- Tests: ${{ steps.tests.outcome }}\n' +
'- Build: ${{ steps.build.outcome }}\n\n' +
'### Action Required:\n' +
'Please investigate and fix the issues.\n\n' +
'[View workflow run](' + runUrl + ')\n\n' +
'---\n' +
'*Automated by GitHub Actions*';

github.rest.issues.create({
owner: context.repo.owner,
repo: context.repo.repo,
title: title,
body: body,
labels: ['bug', 'automated', 'health-check']
});
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
/node_modules
/.pnp
.pnp.js
.env

# testing
/coverage
Expand Down
1 change: 0 additions & 1 deletion Caching Dependencies.md

This file was deleted.

Loading
Loading