name: Code Review
on:
pull_request:
types: [opened, synchronize, reopened, ready_for_review]
permissions:
pull-requests: write
contents: read
issues: write
jobs:
code-review:
runs-on: ubuntu-latest
# Пропускай автоматический код‑ревью для черновых PR
if: github.event.pull_request.draft == false
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
ref: ${{ github.event.pull_request.head.sha }}
- name: Install Cursor CLI
run: |
curl https://cursor.com/install -fsS | bash
echo "$HOME/.cursor/bin" >> $GITHUB_PATH
- name: Configure git identity
run: |
git config user.name "Cursor Agent"
git config user.email "cursoragent@cursor.com"
- name: Perform automated code review
env:
CURSOR_API_KEY: ${{ secrets.CURSOR_API_KEY }}
MODEL: gpt-5
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
BLOCKING_REVIEW: ${{ vars.BLOCKING_REVIEW || 'false' }}
run: |
cursor-agent --force --model "$MODEL" --output-format=text --print 'Ты работаешь в раннере GitHub Actions и выполняешь автоматическое код‑ревью. gh CLI доступен и аутентифицирован через GH_TOKEN. Можно комментировать pull request’ы.
Context:
- Repo: ${{ github.repository }}
- PR Number: ${{ github.event.pull_request.number }}
- PR Head SHA: ${{ github.event.pull_request.head.sha }}
- PR Base SHA: ${{ github.event.pull_request.base.sha }}
- Blocking Review: ${{ env.BLOCKING_REVIEW }}
Objectives:
1) Перепроверь существующие комментарии к обзору и ответь resolved, когда они учтены.
2) Просмотри текущий diff PR и отмечай только очевидные, критичные проблемы.
3) Оставляй очень короткие инлайн‑комментарии (1–2 предложения) только на изменённых строках и короткое резюме в конце.
Procedure:
- Получить существующие комментарии: gh pr view --json comments
- Получить diff: gh pr diff
- Получить изменённые файлы с патчами для вычисления инлайн‑позиций: gh api repos/${{ github.repository }}/pulls/${{ github.event.pull_request.number }}/files --paginate --jq '.[] | {filename,patch}'
- Вычисли точные инлайн‑якоря для каждой проблемы (путь к файлу + позиция в diff). Комментарии ДОЛЖНЫ быть размещены инлайн на изменённой строке в diff, а не как верхнеуровневые.
- Найди предыдущие верхнеуровневые комментарии в стиле «нет проблем», созданные этим ботом (совпадение по тексту типа: "✅ no issues", "No issues found", "LGTM").
- Если текущий запуск находит проблемы и существуют предыдущие комментарии «нет проблем»:
- Предпочти удалить их, чтобы избежать путаницы:
- Попробуй удалить верхнеуровневые комментарии через: gh api -X DELETE repos/${{ github.repository }}/issues/comments/<comment_id>
- Если удалить нельзя, сверни их через GraphQL (minimizeComment) или отредактируй, добавив префикс "[Superseded by new findings]".
- Если ни удалить, ни свернуть нельзя, ответь на тот комментарий: "⚠️ Superseded: issues were found in newer commits".
- Если ранее сообщённая проблема выглядит исправленной недавними изменениями, ответь: ✅ This issue appears to be resolved by the recent changes
- Анализируй ТОЛЬКО:
- Разыменование null/undefined
- Утечки ресурсов (незакрытые файлы или соединения)
- Инъекции (SQL/XSS)
- Проблемы конкурентности/гонки
- Отсутствие обработки ошибок для критических операций
- Очевидные логические ошибки с некорректным поведением
- Явные анти‑паттерны производительности с измеримым влиянием
- Однозначные уязвимости безопасности
- Избегай дублей: пропускай, если похожая обратная связь уже есть на тех же или соседних строках.
Commenting rules:
- Максимум 10 инлайн‑комментариев всего; приоритизируй самые критичные проблемы
- Одна проблема на комментарий; размещай на точной изменённой строке
- Все комментарии по проблемам ДОЛЖНЫ быть инлайн (привязанными к файлу и строке/позиции в diff PR)
- Естественный тон, конкретно и по делу; не упоминай автоматизацию или «высокую уверенность»
- Используй эмодзи: 🚨 Critical 🔒 Security ⚡ Performance ⚠️ Logic ✅ Resolved ✨ Improvement
Submission:
- Если НЕТ проблем для отчёта и уже есть верхнеуровневый комментарий «нет проблем» (например, "✅ no issues", "No issues found", "LGTM"), НЕ отправляй ещё один комментарий. Пропусти отправку, чтобы избежать повторов.
- Если НЕТ проблем для отчёта и НЕТ предыдущего комментария «нет проблем», отправь один короткий сводный комментарий, что проблем нет.
- Если ЕСТЬ проблемы для отчёта и существует предыдущий комментарий «нет проблем», убедись, что тот комментарий удалён/свёрнут/помечен как устаревший перед отправкой нового ревью.
- Если ЕСТЬ проблемы для отчёта, отправь ОДНО ревью, содержащее ТОЛЬКО инлайн‑комментарии плюс опциональное короткое сводное тело. Используй GitHub Reviews API, чтобы гарантировать, что комментарии инлайн:
- Построй JSON‑массив комментариев вида: [{ "path": "<file>", "position": <diff_position>, "body": "..." }]
- Отправь через: gh api repos/${{ github.repository }}/pulls/${{ github.event.pull_request.number }}/reviews -f event=COMMENT -f body="$SUMMARY" -f comments='[$COMMENTS_JSON]'
- НЕ используй: gh pr review --approve или --request-changes
Blocking behavior:
- Если BLOCKING_REVIEW = true и были опубликованы какие‑либо 🚨 или 🔒 проблемы: echo "CRITICAL_ISSUES_FOUND=true" >> $GITHUB_ENV
- Иначе: echo "CRITICAL_ISSUES_FOUND=false" >> $GITHUB_ENV
- Всегда устанавливай CRITICAL_ISSUES_FOUND в конце
'
- name: Check blocking review results
if: env.BLOCKING_REVIEW == 'true'
run: |
echo "Проверяем наличие критических проблем..."
echo "CRITICAL_ISSUES_FOUND: ${CRITICAL_ISSUES_FOUND:-unset}"
if [ "${CRITICAL_ISSUES_FOUND:-false}" = "true" ]; then
echo "❌ Обнаружены критические проблемы, и блокирующий обзор включён. Завершаем workflow с ошибкой."
exit 1
else
echo "✅ Блокирующих проблем не найдено."
fi