Amiga
Оглавление курса · урок 6 из 13

Модуль 2 · Качество · урок 6 из 13

Ворота качества: машина и человек

Когда поток изменений растёт, каждое правило, которое проверяет человек, становится дорогим. Ворота качества — это решение, какие проверки делает машина и блокирует мерж, какие делает машина и только советует, а какие остаются за человеком. Правильно поставленные ворота делают ревью короче и спокойнее. В этом уроке — как их выстроить в GitLab CI для проекта агентства.

Два вида машинных проверок

Биргитта Бёкелер в статье о harness engineering делит проверки на два типа — в оригинале computational и inferential (martinfowler.com):

  • Детерминированные — тесты, линтеры, проверка типов, структурные тесты архитектуры. Быстрые, дешёвые, дают одинаковый результат при каждом запуске. Им можно доверить блокировку мержа.
  • Вероятностные — ревью языковой моделью, оценка «LLM как судья». Видят смысл, но могут ошибаться в обе стороны. Их место — совет и подсветка, а не единственный барьер.

Отсюда первое правило: всё, что можно проверить детерминированно, проверяйте детерминированно. Правило «не конкатенировать SQL» в AGENTS.md агент может забыть, правило линтера — нет. Документация Codex прямо советует оставлять форматирование и линт CI, а не правилам ревью-агента (GitLab).

Сообщение об ошибке — тоже инструкция

Агент читает вывод проверок и исправляет код сам — если понимает, что от него хотят. Команда OpenAI пишет сообщения своих линтеров как инструкции по исправлению, чтобы они сразу попадали в контекст агента (Harness engineering). Сравните:

text
Error: forbidden dependency
text
Компонент themes/site/partials/hero.htm обращается к модели напрямую.
Шаблоны получают данные только через компонент страницы.
Перенесите запрос в plugins/site/content/components/Hero.php
и передайте результат в шаблон через $this->page['hero'].

Второе сообщение исправит и агент, и джуниор. Как писать такие проверки — в уроке «Архитектура через инварианты».

Слои проверок

Принцип «качество левее» — ловить проблему как можно раньше и дешевле:

Когда Что Блокирует?
Локально, до коммита Линтер, форматирование, быстрые юнит-тесты; агент запускает их сам по командам из AGENTS.md Да, для автора
В MR Линт, статанализ, тесты, лимит размера MR, сканирование зависимостей и SAST Да
В MR Ревью-агент Нет, совещательно
В MR Человеческое ревью по уровню риска Да
После мержа E2E-регресс на стенде, проверка релиза QA Да, для релиза

Агент в локальном цикле сильно экономит время: если в AGENTS.md записаны команды линта и тестов, он прогонит их сам и придёт в MR уже с зелёным результатом.

Пример конвейера

Ниже — рабочий минимум для PHP-проекта: статанализ с отчётом в виджет MR, юнит-тесты, лимит размера MR и совещательное ревью агентом.

yaml · .gitlab-ci.yml
stages: [check, test, review]

variables:
  MAX_CHANGED_LINES: "600"

.mr_only:
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"

phpstan:
  extends: .mr_only
  stage: check
  image: composer:2
  script:
    - composer install --no-interaction --prefer-dist
    - vendor/bin/phpstan analyse --no-progress --error-format=gitlab > phpstan.json
  artifacts:
    reports:
      codequality: phpstan.json
    when: always

mr_size:
  extends: .mr_only
  stage: check
  image:
    name: alpine/git
    entrypoint: [""]
  variables:
    GIT_DEPTH: "0"
  script:
    - >
      CHANGED=$(git diff --numstat "$CI_MERGE_REQUEST_DIFF_BASE_SHA" HEAD --
      . ':!composer.lock' ':!package-lock.json'
      | awk '{s+=$1+$2} END {print s+0}')
    - echo "Изменено строк $CHANGED, лимит $MAX_CHANGED_LINES"
    - test "$CHANGED" -le "$MAX_CHANGED_LINES"

unit:
  extends: .mr_only
  stage: test
  image: composer:2
  script:
    - composer install --no-interaction --prefer-dist
    - vendor/bin/phpunit --log-junit junit.xml
  artifacts:
    reports:
      junit: junit.xml
    when: always

agent_review:
  stage: review
  image: node:22
  rules:
    # только MR из веток этого проекта, не из форков
    - if: $CI_PIPELINE_SOURCE == "merge_request_event" && $CI_MERGE_REQUEST_SOURCE_PROJECT_ID == $CI_PROJECT_ID
  allow_failure: true
  environment:
    name: agent-review   # к этому окружению привязана переменная с ключом
    action: prepare      # без создания деплоя
  variables:
    GIT_DEPTH: "0"
  script:
    # версию закрепляем, чтобы поведение не менялось само
    - npm install -g @openai/codex@0.163.0
    - >
      git diff "$CI_MERGE_REQUEST_DIFF_BASE_SHA" HEAD
      | CODEX_API_KEY="$CODEX_REVIEW_KEY"
      codex exec --sandbox read-only --ephemeral -o agent-review.md
      "Это дифф merge request. Проведи ревью по разделу
      Code Review Rules из AGENTS.md. Пиши только о серьёзных
      проблемах: файл, строка, почему это ошибка, как исправить.
      Если проблем нет, ответь одной строкой: замечаний нет."
  artifacts:
    paths: [agent-review.md]
    when: always

Что здесь важно:

  • allow_failure: true у ревью агентом: его находки — совет, они не блокируют мерж и не заменяют человека.
  • Ключ хранится в маскированной переменной CI под отдельным именем (CODEX_REVIEW_KEY) и подставляется в CODEX_API_KEY только для вызова codex exec. Задание с ключом не запускает код репозитория и не работает на MR из форков: в официальной документации прямо предупреждают не выставлять ключ на уровне задачи, где выгружается или выполняется код проекта (non-interactive mode). Переменные GitLab по умолчанию видны всем задачам пайплайна, включая composer install и тесты, — ограничьте переменную областью окружения (environment scope) и укажите это окружение только у задачи ревью.
  • Дифф подаётся агенту через stdin, песочница только на чтение.
  • Лимит в 600 строк — пример, подберите свой по истории проекта.

Полноценные варианты — с отчётом ревью прямо в виджете MR, разбором находок SAST и патчами — есть в кукбуке OpenAI Secure quality with GitLab и в уроке «Codex в GitLab CI». Вопросы безопасности таких заданий — в «Безопасность автоматизации».

Что остаётся человеку

Машина не ответит на вопросы, которые составляют суть ревью:

  • Решает ли изменение ту задачу, которую ставил клиент, а не ту, что понял агент?
  • Не стало ли решение сложнее, чем нужно? Нет ли в проекте уже готового способа?
  • Проверяют ли тесты поведение, или они просто повторяют реализацию? Тесты, написанные тем же агентом, что и код, требуют отдельного внимания — см. «Как проверять тесты, написанные агентом».
  • Как изменение выглядит и ощущается: вёрстка, анимации, тексты, поведение на телефоне.
  • Безопасность в контексте: какие данные клиента затронуты, кто имеет доступ.

Чем больше рутины забрали ворота, тем больше внимания остаётся на эти вопросы.

Защита веток — не трогать

Ворота работают, только если их нельзя обойти. Защищённая ветка main, мерж только через MR, обязательный зелёный конвейер и одобрение человека — это база, которую не меняют ради скорости. Правила ревью-агента её не заменяют: об этом прямо написано в документации Codex.

Попробуйте сами

10–15 мин на рабочем месте
  1. Выпишите правила из AGENTS.md и ревью-чек-листа команды. Отметьте, какие можно превратить в линтер или тест. Возьмите одно и сделайте.
  2. Добавьте в свой .gitlab-ci.yml задание mr_size с лимитом, который не нарушали 80% MR за последний месяц.
  3. Перепишите сообщение одной своей проверки так, чтобы из него было понятно, как исправить ошибку.

Коротко

  • Детерминированные проверки блокируют мерж, вероятностные — советуют.
  • Всё, что можно проверить линтером или тестом, не должно жить только в тексте правил.
  • Сообщения об ошибках пишутся как инструкции по исправлению — для агента и для людей.
  • Ревью агентом в CI — совещательный этап с закреплённой версией и без доступа форков к ключу.
  • Человек проверяет смысл, сложность, тесты, ощущение и безопасность в контексте; защиту веток не ослабляют.
Отметка хранится только в вашем браузере
Хотите связаться с владельцем
компании напрямую?
Дмитрий Тарасов
Дмитрий Тарасов
СЕО

НАПИСАТЬ

Написать в MAX