В современных пайплайнах Continuous Integration (CI) линтеры (ESLint, PHP_CodeSniffer) решают проблему синтаксиса и статических контрактов, но не способны понять бизнес-логику, архитектурные дефекты и уязвимости нулевого дня. Ручное ревью (Code Review) отнимает часы времени Senior-разработчиков и подвержено человеческому фактору.
Внедрение автономного AI-ревьюера на базе LLM в GitHub Actions позволяет создать "умный" Quality Gate. Агент анализирует diff, проверяет соответствие внутренним стандартам (например, AGENTS.md), выявляет классические уязвимости (SQLi, CSRF, XSS) и оставляет точечные комментарии (inline comments) к проблемным строкам кода до того, как PR дойдет до живого разработчика.
Агент функционирует как событийно-ориентированный микросервис в инфраструктуре GitHub.
[ Разработчик ] -> (Push & PR) -> [ GitHub Event (pull_request) ]
|
v
[ GitHub Actions Runner ] -> (Fetch Diff) -> [ Сборка контекста (Diff + AGENTS.md) ]
|
v
[ LLM API (Claude/GPT-4) ] <- (Анализ логики)
|
v
[ GitHub REST API ] -> (Post Inline Comments) -> [ Pull Request Interface ]+) и удаленных (-) строк.
Webhook pull_request инициирует GitHub Action. Выгружается контекст.
Получение измененных файлов, фильтрация lock-файлов и медиа.
Оценка измененных строк через призму стандартов безопасности (AGENTS.md).
Интеграция инлайн-комментариев в интерфейс Pull Request.
Каким образом автономный AI-ревьюер интегрируется в процесс Pull Request для предоставления обратной связи до живого ревьюера?
*.test.ts для измененной функции, агент предлагает готовый блок юнит-теста прямо в комментарии к PR.Пример реализации AI-ревьюера на Node.js, запускаемого внутри кастомного GitHub Action. Скрипт получает diff, отправляет его в LLM и постит комментарии.
import * as core from '@actions/core';
import * as github from '@actions/github';
import { OpenAI } from 'openai';
async function run() {
try {
const token = core.getInput('github-token', { required: true });
const openaiKey = core.getInput('openai-key', { required: true });
const octokit = github.getOctokit(token);
const openai = new OpenAI({ apiKey: openaiKey });
const context = github.context;
if (!context.payload.pull_request) {
core.setFailed('This action runs only on pull_request events.');
return;
}
const prNumber = context.payload.pull_request.number;
const repo = context.repo;
// 1. Получаем список измененных файлов и их diff
const { data: files } = await octokit.rest.pulls.listFiles({
...repo,
pull_number: prNumber,
});
for (const file of files) {
if (file.status === 'removed' || !file.patch) continue;
// 2. Формируем промпт для LLM
const prompt = `
Review the following code diff for the file ${file.filename}.
Focus on:
1. Security vulnerabilities (SQLi, XSS).
2. Best practices and solid principles.
3. Typescript/PHP strictness.
Respond in JSON array format:
[{ "line": <line_number>, "body": "<comment_text>" }]
If the code looks good, return an empty array [].
Diff:
${file.patch}
`;
const completion = await openai.chat.completions.create({
model: 'gpt-4o',
messages: [{ role: 'user', content: prompt }],
response_format: { type: 'json_object' } // Принудительный JSON
});
const content = completion.choices[0].message.content || '{"reviews":[]}';
const { reviews } = JSON.parse(content);
// 3. Публикуем комментарии к конкретным строкам (Inline comments)
for (const review of reviews) {
await octokit.rest.pulls.createReviewComment({
...repo,
pull_number: prNumber,
commit_id: context.payload.pull_request.head.sha,
path: file.filename,
body: `🤖 **AI Reviewer:**\n${review.body}`,
line: review.line,
side: 'RIGHT'
});
}
}
} catch (error: any) {
core.setFailed(error.message);
}
}
run();И интеграция в .github/workflows/ai-review.yml:
name: AI Code Review
on: [pull_request]
jobs:
review:
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
steps:
- uses: actions/checkout@v4
- name: Run AI Reviewer
uses: ./path-to-custom-action
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
openai-key: ${{ secrets.OPENAI_API_KEY }}Почему при отправке git diff в LLM возникает риск ошибки '422 Unprocessable Entity' от GitHub API при публикации инлайн-комментария?
Проблема: LLM оставляет десятки бесполезных комментариев о пропущенных запятых, отступах или стиле переменных. Разработчики начинают игнорировать бота ("усталость от ревью"). Решение: Строго инструктировать LLM в System Prompt игнорировать стилистику и форматирование. Оставить эти задачи линтерам и Prettier. Фокусироваться только на багах, безопасности и архитектуре.
Проблема: Diff от GitHub содержит относительные номера строк. LLM часто путается и возвращает номер строки, которой нет в file.patch, из-за чего API GitHub возвращает ошибку 422 Unprocessable Entity.
Решение: Передавать в LLM Diff с предварительно размеченными номерами строк или использовать агентов, которые извлекают весь файл из репозитория, а не только патч.
Проблема: Если PR содержит хардкодные ключи API (что само по себе плохо), они отправляются в сторонний LLM API, что нарушает политики безопасности. Решение: Перед отправкой Diff в LLM пропускать его через регулярные выражения для маскировки энтропийных строк (секретов). Использовать локальные/приватные модели (через VPC) в Enterprise сегменте.