feat(agent): add automated-pr-review script (agent)

Co-authored-by: PR0M3TH3AN <[email protected]>
This commit is contained in:
google-labs-jules[bot]andPR0M3TH3AN committed 2026-01-26 23:38:15 +00:00
1 parent a58c31e2ab
commit 63dec7551d
1 file changed
+127
+127
View File
@@ -0,0 +1,127 @@
import { spawnSync, execSync } from 'child_process';
import fs from 'fs';
import path from 'path';
const REPORT_FILE = 'PR_REVIEW.md';
const APPLY_FIXES = process.argv.includes('--apply-fixes');
function run(command, args, opts = {}) {
console.log(`> ${command} ${args.join(' ')}`);
return spawnSync(command, args, { encoding: 'utf-8', stdio: 'pipe', ...opts });
}
function getDiffFiles() {
try {
// Try to compare against origin/main, fallback to HEAD~1 or just check current changes if no upstream
// Since this runs on a checkout, we want to see what this branch touches compared to main.
// If origin/main is not available, we might fail.
const hasMain = run('git', ['rev-parse', '--verify', 'origin/main']).status === 0;
const base = hasMain ? 'origin/main' : 'HEAD';
// Check if we are on main? No, we are on a PR branch usually.
// We want the diff of the *current* code vs main.
const res = run('git', ['diff', '--name-only', base, 'HEAD']);
if (res.error || res.status !== 0) return [];
return res.stdout.trim().split('\n').filter(Boolean);
} catch (e) {
console.error("Error getting diff:", e);
return [];
}
}
function main() {
const report = [];
report.push('# Automated PR Review');
report.push(`Date: ${new Date().toISOString()}`);
report.push('');
// 1. npm ci
console.log('Running npm ci...');
const ci = run('npm', ['ci']);
if (ci.status !== 0) {
report.push('## 🚨 Dependency Install Failed');
report.push('```');
report.push(ci.stderr || ci.stdout);
report.push('```');
// If ci fails, we probably can't run other scripts, but we try.
} else {
report.push('## ✅ Dependencies Installed');
}
// 2. Format
console.log('Running npm run format...');
run('npm', ['run', 'format']); // This modifies files
const status = run('git', ['status', '--porcelain']).stdout;
const formattedFiles = status.split('\n').filter(l => l.trim()).map(l => l.slice(3));
if (formattedFiles.length > 0) {
report.push('## ⚠️ Formatting Changes');
report.push('The following files were reformatted:');
report.push(formattedFiles.map(f => `- ${f}`).join('\n'));
if (APPLY_FIXES) {
console.log('Applying formatting fixes...');
run('git', ['add', '.']);
run('git', ['commit', '-m', 'fix(ai): automated formatting (agent)']);
report.push('\n**Changes have been automatically committed.**');
} else {
report.push('\n**Run `npm run format` to fix these issues.**');
}
} else {
report.push('## ✅ Formatting Passed');
}
// 3. Lint
console.log('Running npm run lint...');
const lint = run('npm', ['run', 'lint']);
if (lint.status !== 0) {
report.push('## ⚠️ Lint Warnings/Errors');
report.push('<details><summary>Show Lint Output</summary>');
report.push('');
report.push('```');
report.push(lint.stdout + '\n' + lint.stderr);
report.push('```');
report.push('</details>');
} else {
report.push('## ✅ Lint Passed');
}
// 4. Unit Tests
console.log('Running npm run test:unit...');
const test = run('npm', ['run', 'test:unit']);
if (test.status !== 0) {
report.push('## ❌ Unit Tests Failed');
report.push('<details><summary>Show Test Output</summary>');
report.push('');
report.push('```');
report.push(test.stdout + '\n' + test.stderr);
report.push('```');
report.push('</details>');
} else {
report.push('## ✅ Unit Tests Passed');
}
// 5. Guardrails
const diffFiles = getDiffFiles();
const sensitivePatterns = [
/^js\/nostr\//,
/^js\/services\/storageService/,
/^js\/services\/r2Service/,
/crypto/i
];
const sensitiveChanges = diffFiles.filter(f => sensitivePatterns.some(p => p.test(f)));
if (sensitiveChanges.length > 0) {
report.push('## 🛡️ Security & Protocol Review Required');
report.push('The following sensitive files were modified:');
report.push(sensitiveChanges.map(f => `- ${f}`).join('\n'));
report.push('\n**Flags:** `requires-security-review`, `requires-protocol-review`');
}
fs.writeFileSync(REPORT_FILE, report.join('\n'));
console.log(`Report generated at ${REPORT_FILE}`);
}
main();