Перейти к содержанию

pr-review-agent — AI ревьюит твои PR по пайплайну

Как собрать агента-ревьювера, который на каждый pull request сам читает изменения и пишет ревью комментарием — прямо в CI. Агент = OpenCode + модель MiniMax-M3, упакованные в docker-образ; собирает и запускает его раннер лаб-Gitea.

Представь автоматического рецензента. Ты открыл pull request — предложил изменения в код. Обычно их смотрит коллега: ищет баги, дыры в безопасности, неаккуратности. Мы сделали так, что первый проход делает робот: как только PR открыт, запускается программа-агент, читает твои правки и пишет отзыв комментарием — «тут SQL-инъекция», «тут деление на ноль», «пароль в коде — так нельзя».

Из чего это собрано, простыми словами:

  • Агент — готовая программа (OpenCode), которая «думает» через языковую модель. Мы дали ей модель MiniMax и попросили: «прочитай изменения и дай ревью».
  • Образ — агент со всем нужным упакован в «коробку» (docker-образ), чтобы запускался одинаково где угодно.
  • Пайплайн — правило в git: «когда открыт PR — запусти эту коробку». Это и есть автоматизация CI.
  • Пользователь-бот — ревью пишет не от твоего имени, а от лица code-review-agent, у которого прав ровно столько, чтобы оставлять комментарии — не больше.

Тебе как ученику не нужно ничего из этого собирать вручную: образ и бот уже готовы. Твоя задача — подключить пайплайн к своему проекту и открыть PR (см. домашнее задание).

1. Архитектура

flowchart TB
    subgraph proj["Твой проект (орг labs)"]
      PR["Открыт pull request"] --> WF[".gitea/workflows/pr-review.yaml<br/>on: pull_request"]
    end
    WF --> RUN["Раннер лаб-Gitea (docker)"]
    RUN -->|"docker run pr-reviewer:latest<br/>--repo … --pr …"| AG["Контейнер-агент"]
    AG -->|"GET pulls/N.diff"| GIT["lab-Gitea API"]
    AG -->|"opencode run --model minimax/MiniMax-M3"| MM["api.minimax.io/anthropic"]
    AG -->|"POST issues/N/comments<br/>(как code-review-agent)"| GIT
    GIT --> CMT["💬 Ревью в PR"]

Готовый образ pr-reviewer:latest собирается отдельным CI (репо platform/pr-reviewer) и лежит на docker-хосте — пайплайны проектов его только запускают.

2. Образ агента (репо platform/pr-reviewer)

opencode.json — провайдер модели. MiniMax отдаёт Anthropic-совместимый эндпоинт, а у OpenCode есть родной anthropic-провайдер:

{
  "model": "minimax/MiniMax-M3",
  "provider": {
    "minimax": {
      "npm": "@ai-sdk/anthropic",
      "options": {
        "baseURL": "https://api.minimax.io/anthropic/v1",
        "apiKey": "{env:MINIMAX_API_KEY}"
      },
      "models": { "MiniMax-M3": { "name": "MiniMax M3" } }
    }
  }
}

baseURL с /v1

@ai-sdk/anthropic сам дописывает /messages, поэтому base — это …/anthropic/v1, а не …/anthropic (иначе 404 page not found).

Dockerfile (суть): OpenCode ставим install-скриптом, а не npm i -g opencode-ai (npm на glibc-образе неверно выбирает бинарь и падает notsup):

FROM node:22-slim
RUN apt-get update && apt-get install -y --no-install-recommends \
    git curl jq ca-certificates bash unzip && rm -rf /var/lib/apt/lists/*
RUN curl -fsSL https://opencode.ai/install | bash
ENV PATH="/root/.opencode/bin:${PATH}"
RUN opencode --version          # build-time проверка: битая установка валит сборку сразу
COPY opencode.json /root/.config/opencode/opencode.json
COPY review-pr.sh /usr/local/bin/review-pr
ENTRYPOINT ["review-pr"]

review-pr.sh (суть): GET …/pulls/N.diff → собрать промпт с диффом → opencode run --model minimax/MiniMax-M3 "$PROMPT"POST …/issues/N/comments.

3. Пайплайн, личность, секреты

В проекте-ученике — .gitea/workflows/pr-review.yaml:

name: pr-review
on:
  pull_request:
    types: [opened, synchronize, reopened]
jobs:
  review:
    runs-on: mac-x64
    steps:
      - name: AI-ревью PR
        run: |
          docker run --rm \
            -e GITEA_TOKEN=${{ secrets.PR_AGENT_TOKEN }} \
            -e MINIMAX_API_KEY=${{ secrets.MINIMAX_API_KEY }} \
            pr-reviewer:latest \
            --repo ${{ github.repository }} \
            --pr ${{ github.event.number }}
  • Личность. Ревью пишет code-review-agent — отдельный пользователь с токеном ровно на write:issue + read:repository. Он в команде labs/reviewers (доступ ко всем репо орги), поэтому добавлять его в проект вручную не нужно.
  • Секреты — на уровне орги labs (наследуются всеми репо): MINIMAX_API_KEY (ключ модели), PR_AGENT_TOKEN (токен агента). Значения живут только в секретах Gitea, не в git.
  • Два лица: провижининг делает админ, а рантайм — узкий code-review-agent. Токен агента ограничен так, что даже при ошибке он может только комментировать, а не менять код.

4. Как выглядит живое ревью

На тестовый app.py (SQL-инъекция + захардкоженный пароль + деление на ноль) MiniMax-M3 ответил так (фрагмент):

### 🔴 Безопасность
- app.py:3 — Хардкод пароля DB_PASSWORD = "admin123" — нужен секрет-менеджер.
- app.py:6 — SQL-инъекция: используй параметризованный запрос
  db.execute("SELECT * FROM users WHERE id = ?", (user_id,)).

### 🐛 Баги / крайние случаи
- app.py:10 — average([]) падает ZeroDivisionError — проверь пустой список.

### Итого
PR нельзя мержить: SQL-инъекция и захардкоженный секрет — блокеры.

Домашнее задание

Собрать свой проект и пройти ревью агентом.

  1. Создай репозиторий в орге labs (например labs/<твой-ник>-hw), с любым мини-проектом на любом языке.
  2. Добавь пайплайн — положи в репо файл .gitea/workflows/pr-review.yaml (скопируй из раздела 3 выше, менять ничего не нужно).
  3. Сделай ветку и внеси изменения, в которых есть что поревьюить: специально оставь пару проблем (небезопасный ввод, необработанный крайний случай, «магическое число», отсутствие проверки ошибки).
  4. Открой pull request из ветки в main.
  5. Дождись ревью — через ~30–60 сек code-review-agent напишет комментарий. Если долго — глянь вкладку Actions: ран pr-review должен быть зелёным.
  6. Почини блокеры, запушь в ту же ветку (событие synchronize перезапустит ревью) и добейся, чтобы агент больше не находил критичного.

Критерии сдачи

  • В репо есть рабочий pr-review.yaml, ран pr-review — зелёный.
  • На PR есть комментарий-ревью от code-review-agent.
  • В первом ревью агент нашёл хотя бы одну реальную проблему.
  • После правок повторное ревью не содержит блокеров.

Со звёздочкой ⭐

  • Поправь промпт ревью в review-pr.sh (например, попроси оценку по 10-балльной шкале или строгий шаблон ответа) и пересобери образ.
  • Пусть агент не только комментирует, а ставит формальный PR review со статусом REQUEST_CHANGES при блокерах (эндпоинт POST …/pulls/N/reviews).
  • Прогони агента на чистом PR (без проблем) и проверь, что он не выдумывает замечания.

Связанные страницы