CI для кода от ИИ: минимальный конвейер, который ловит то, что пропускает нейросеть

Команда стартапа «Орбита» состоит из четырёх человек и нескольких ИИ-агентов. Агенты пишут большую часть кода, люди ставят задачи и читают результат. Скорость фантастическая: в день рождается десяток изменений. В пятницу в 18:40 одно из них смёрджили без тщательной проверки, потому что все торопились домой. В понедельник выяснилось, что оплата не работала весь уикенд.
Баг был глупый: агент «навёл порядок» в функции и случайно переименовал поле. Человек, читавший изменения вечером в пятницу, пробежал глазами и не заметил. Автоматическая проверка заметила бы за минуту, но её не было.
Эта статья про то, почему при работе с ИИ автоматические проверки стали не «хорошей практикой», а условием выживания, и как собрать минимальный набор, который не тормозит команду.
Почему узкое место сместилось
Раньше разработчик писал код медленнее, чем человек успевал его читать. Ревью справлялось. Теперь агент генерирует изменения быстрее, чем их способен проверять человек. Если ничего не менять, получается так: изменений много, проверяют их всё менее внимательно, а ошибок становится больше.
Выход не в том, чтобы замедлить агента. Выход в том, чтобы поручить механическую часть проверок машинам: они не устают, не торопятся домой и работают одинаково в пятницу вечером и в понедельник утром. Человек остаётся для того, что машина не может: оценки смысла и решений. Весь путь изменения выглядит так:
Обратите внимание на порядок: сначала быстрые и дешёвые проверки, потом медленные и дорогие, а человек в самом конце. Принцип называют «fail fast» (падай быстро): чем раньше обнаружена ошибка, тем дешевле её исправить. Если упал линтер, не нужно ждать пятнадцать минут E2E.
Кто что ловит
Проверок много, и новичку легко решить, что нужна «какая-нибудь одна, самая главная». Но они специализируются, и ни одна не закрывает всё. Вот карта: чем ярче клетка, тем чаще проверка находит этот тип багов. Наведите курсор на клетки.
Посмотрите на пробелы. Линтер и типы почти не видят уязвимостей. Сканер безопасности почти не замечает ошибки логики. E2E ловит сломанные связки, но стоит дорого. Именно поэтому конвейер собирают из нескольких проверок, закрывающих разные участки.
Шесть проверок подробнее
Все шесть не нужны всем. Внутренний скрипт на пятерых пользователей обойдётся линтером и типами. Продукт с деньгами и персональными данными требует всех шести. Поэтому главный вопрос выбора: какова цена ошибки?
Тренажёр: соберите конвейер в бюджет по времени
Теперь соберите свой. В релизе двадцать четыре бага разной тяжести: от опечатки до уязвимости. Пайплайн должен укладываться в 35 минут, иначе разработчики начнут его обходить. Включайте проверки и запускайте релиз: баги побегут по конвейеру, а те, что проскочат, попадут в продакшен.
Что стоит заметить. Дешёвые проверки окупаются первыми: линтер и типы за три минуты снимают заметную долю мелочи. Дорогая проверка нужна там, где у вас дорогая цена ошибки. Уязвимость весит больше, чем несколько опечаток, и поэтому сканер безопасности стоит в конвейере почти всегда. И последнее: идеального набора нет, потому что бюджет времени ограничен. Вы выбираете, какой риск готовы нести.
Почему длинный пайплайн хуже короткого
Это не интуитивно, но важно. Длинный пайплайн не просто «чуть менее удобен». Он ломает поведение людей.
Когда проверки идут час, разработчик перестаёт ждать результата и переключается на другую задачу. Потом возвращается, вспоминает контекст и чинит. На это уходит время. Когда запусков много, начинается самое плохое: пайплайн обходят, отключают «мешающие» проверки или мерджат при красном. Конвейер превращается в декорацию. Поэтому быстрый и уважаемый пайплайн лучше полного и игнорируемого.
Сколько каких тестов писать
Скорость конвейера во многом определяется структурой тестов. Распространённый ориентир называют тестовой пирамидой: много быстрых тестов у основания и мало медленных на вершине.
Причина простая: юнит-тест проверяет функцию за миллисекунды, E2E-тест открывает браузер и проходит сценарий за десятки секунд. Если перевернуть пирамиду и построить всё на E2E, пайплайн станет медленным и хрупким: любая мелочь в интерфейсе роняет сотню тестов.
Что запускать и когда
Как подружить агента с конвейером
Конвейер полезен вдвойне, когда его результатами пользуется сам агент. Хороший порядок такой: агент вносит изменение, сам запускает быстрые проверки локально, смотрит на результат и исправляет, и только потом отправляет код на общий конвейер. Чтобы он это делал, ему нужно знать команды. Поэтому в файле правил проекта (о нём мы говорили в статье про окно контекста) прямо прописывают: «перед завершением задачи запусти линтер, проверку типов и тесты; не считай задачу выполненной, пока всё зелёное».
Это превращает проверки в обратную связь для агента. Он получает сообщение «тест упал, вот почему» и чинит, не дожидаясь человека. Такой цикл самый дешёвый из возможных: исправление происходит за секунды, а не через сутки после замечания на ревью.
Помогают и «хуки» на уровне репозитория: например, быстрая проверка запускается автоматически перед каждым коммитом и не пускает код с очевидными ошибками (или секретом) дальше машины автора. Это страховка на случай, когда про команды забыли.
Откат и безопасные релизы
Как бы вы ни старались, ошибка иногда доберётся до пользователей. Поэтому вторая половина конвейера не про проверки, а про возможность быстро всё отменить.
- Версионирование релизов. Каждый релиз имеет метку и может быть восстановлен. Откат возвращает предыдущую версию одним действием.
- Окружение для просмотра на каждое изменение. Для каждого pull request поднимается временная копия продукта, где можно посмотреть и потыкать до слияния. Многие ошибки интерфейса видны только глазами.
- Флаги функций. Новая возможность включается не для всех сразу, а для малой доли пользователей или только для вас. Если что-то идёт не так, её выключают без нового релиза.
- Мониторинг после релиза. Простые сигналы (рост ошибок, падение числа заказов) должны оповещать команду раньше, чем напишут клиенты.
Цель этих мер в том, чтобы «пятница, 18:40» стала не катастрофой, а неприятным, но решаемым за десять минут эпизодом.
Ловушки, о которых стоит знать
Агент «чинит» тест, а не код. Если поручить агенту «сделай, чтобы тесты проходили», он может выбрать кратчайший путь: изменить ожидание в тесте или обойти проверку. Поэтому изменения в самих тестах читают особенно внимательно. Хорошее правило: тесты и код меняет не один и тот же проход без ревью.
Тесты, которые ничего не проверяют. Бывает, что тест формально зелёный, но проверяет пустоту: вызвал функцию и не сравнил результат. Метрика покрытия кода при этом показывает отличные цифры. Покрытие говорит о том, какие строки выполнялись, а не о том, что проверялось. Для критичной логики полезны тесты на «плохие» значения и на то, что при ошибке система реально падает.
«У нас же есть тесты». Тесты пишут и для того, и против того, что вы считаете важным. Если ключевой сценарий (оплата, вход, права) не покрыт, зелёный пайплайн создаёт ложное чувство безопасности. Начните с сценариев, где ошибка стоит денег.
Секреты и зависимости. Сканер секретов и проверка уязвимых библиотек автоматизируются целиком и выдают результат без участия человека. Это самые выгодные по соотношению усилий и пользы проверки, и их стоит включить в первую очередь.
Что проверить у подрядчика
Если разработку делает подрядчик, наличие конвейера проверяется без чтения кода. Попросите показать четыре вещи.
- Зелёный пайплайн на последнем изменении. Запись с результатами проверок. Если её нет, значит, и проверок нет.
- Историю красных прогонов. Если за три месяца конвейер ни разу не падал, он, скорее всего, ничего не проверяет. Живой конвейер время от времени краснеет и ловит ошибки.
- Список критичных сценариев под тестами. Вход, оплата, права, расчёты. Если «тестировали руками», это вопрос.
- Порядок отката. Как вернуть предыдущую версию и сколько это займёт. Правильный ответ звучит как «одно действие, минуты».
Отсутствие внятных ответов не значит, что код плохой. Оно значит, что при первой же проблеме разбор начнётся с нуля, а вам придётся в это время платить.
Что сделать на этой неделе
- На каждый коммит включите линтер, проверку типов и сканер секретов. Это занимает полдня и сразу снимает основную массу мелочи.
- Для критичной логики (деньги, права, расчёты) напишите тесты на плохие значения.
- Добавьте один E2E-сценарий на самое важное: вход и главное действие продукта.
- Следите за временем пайплайна. Если он перевалил за 10–15 минут на коммит, ищите, что можно вынести или распараллелить.
- Запретите мердж при красных проверках и договоритесь, что «зелёного пайплайна нет» значит «не мерджим».
Тренировку ревью, которое дополняет автоматику, мы разбирали в статье про семь ошибок кода от ИИ. Если вы принимаете работу у подрядчика, возьмите чек-лист приёмки. А что бывает без таких проверок, показано в разборе технического долга. Про то, как собирать контекст для агента, чтобы он реже ошибался, читайте здесь.
Источники и что почитать
- Martin Fowler: The Test Pyramid — классическое объяснение пирамиды тестов.
- Google Testing Blog: Just Say No to More End-to-End Tests — почему E2E-тестов должно быть мало.
- Playwright — инструмент для E2E-тестов в браузере.
- GitHub Actions — один из распространённых способов запускать CI.
Пишу из практики студии MKDGRUPP: в каждом проекте настраиваем CI/CD, автотесты и проверку безопасности, а код каждого PR проходит ревью сеньора. Подробнее: mkdgrupp.ru/uslugi/web.
Частые вопросы
- Какие проверки обязательны для проекта, написанного с ИИ?
- Минимум: линтер и проверка типов на каждый коммит, юнит-тесты для критичной логики, сканер секретов и зависимостей. E2E-тесты на ключевые сценарии добавляют, когда продукт обрастает деньгами и пользователями.
- Почему нельзя просто сделать все проверки?
- Длинный пайплайн замедляет команду, и его начинают обходить. Проверки ранжируют по цене и пользе: дешёвые запускают на каждый коммит, дорогие реже или на важных ветках.
- Заменяет ли CI ревью сеньора?
- Нет, они дополняют друг друга. Автоматика ловит механические и повторяющиеся ошибки, человек ловит архитектурные, логические и контекстные.



