Рынок сейчас охвачен одной светлой надеждой: купить подписку на нейросеть и наутро обнаружить, что команда стала работать вдвое быстрее. Надежда понятная. Примерно с той же надеждой покупают абонемент в спортзал.
Сначала честное предупреждение. Опытные команды с сильным техническим руководством, скорее всего, не найдут здесь ничего нового. Уникального тут нет: всё описанное давно известно и много где работает. Эта статья для тех, кто полноценный процесс разработки в своей компании или команде ещё не отстроил. Я делюсь практическим опытом, на котором у нас держится перевод команды разработки на AI-driven development — разработку, где код пишут AI-агенты под руководством разработчиков.
Нельзя внедрять автопилот там, где не отстроены дороги. Это как будто совершенно очевидная мысль, но почему-то в гонке за переходом на разработку кода AI-агентами про это часто забывают. Поэтому статья не про AI. Она про скучную часть: контроль версий, тесты, сборку, выкатку, бэклог. Тезис простой, как и в прочих материалах моего небольшого канала про AIDD: если технологического процесса нет, агент ускорит разработку ровно до первой ручной выкатки в пятницу вечером. Без конвейера нейросеть похожа на спорткар в утренней пробке: под капотом триста лошадей, а до офиса он доезжает одновременно с соседней малолитражкой.
Ниже — полный цикл на живом примере: от мысли «а хорошо бы…» до момента, когда изменение уже работает у пользователей, а они этого даже не заметили. Для выкатки это лучшая похвала.
Полный цикл: от идеи до пользователя
Что за зверь
Речь про внутренний сервис компании, хотя аналогичный подход применяется и в клиентских проектах. Сервис вырос, как это водится, из небольшой утилиты и сейчас держит на себе изрядный кусок жизни: управление проектами (проекты же для бизнеса это не только про разработку, верно?), финансовый учёт, управление клиентскими лицензиями Битрикс24, отчётность сотрудников и далее по списку, который удлиняется каждую неделю.
Отдельная и, пожалуй, главная его часть — агентский API. Через него рядовые сотрудники, включая разработчиков, по сути, и работают с Битрикс24: не руками в интерфейсе, а через своих AI-агентов, которым сервис открывает ровно то, что разрешено. Это тема для отдельной статьи, и она вовсе не техническая — она про то, как меняется сама работа людей. Здесь достаточно одного вывода: сервис давно перестал быть игрушкой. Если он лежит, лежит не демо-стенд, а рабочий день.
Значит, менять его надо часто и при этом не ронять. Противоречие известное, и решают его обычно молитвой и словом «аккуратненько».
Бэклог: ничего не придумывали
Первое искушение любой команды — написать свой трекер задач. С канбаном, интеграциями и личной гордостью. Мы удержались.
Весь код живёт в GitHub. Бэклог — это issues и GitHub Projects. Инструмент существует, работает и, что важнее, не требует от нас его поддерживать. Мы не дописывали к нему плагины и не натягивали чужие процессы. Взяли как есть. Мы даже интеграцию с Битрикс24 не делали, потому что нафига? Агент может работать с GitHub и агент может работать с Битрикс24 через тот самый агентский API. Всё. Вот она и интеграция, только гибкая.
Стадий в канбане три, и пока этого хватает:
1. Бэклог — всё, что пришло в голову и записано, чтобы не потерялось.
2. В работе — то, что взяли и делают.
3. Закрыто — фича выпущена или баг исправлен.
Возможно, стадий станет больше. Пока каждая новая колонка выглядела бы как новый стул в приёмной: сидеть на нём некому, а пыль вытирать придётся.
Теперь деталь, ради которой этот раздел и написан. В GitHub Projects у нас почти никто не ходит. На красивую доску посмотрели пару раз, порадовались и перестали. Вся работа с бэклогом замкнута на AI-агента. Пришла идея посреди разговора о чём-то другом — агент через специальный скилл заводит issue, сам кладёт его в нужную стадию и сам вешает метки по нашим правилам. Человеку остаётся сказать фразу. Записывать задачу, искать нужную колонку и вспоминать, как называется метка для «это срочно, но не горит», больше не нужно.
А закрывается задача и вовсе без участия людей. Пулл-реквест ссылается на issue, при слиянии GitHub закрывает задачу и переносит её в «Закрыто». Доска в итоге всегда честная — не потому, что все дисциплинированные, а потому, что дисциплина переложена на автоматику.
Код: в main только через пулл-реквест
Главное правило, которое к тому же реализовано на уровне защиты ветки в GitHub, простое и ни для кого не делает исключений: в основную ветку изменения попадают только через пулл-реквест. Никаких «я быстренько поправлю прямо в main». Быстренько — это самый дорогой вид починки.
Кто пишет код? Весь код пишет агент. Разработчик ставит задачу, следит за своим пониманием задачи и понимание задачи агентом, задаёт вопросы, разбирает предложенное решение и отвечает за результат. Руками код он теперь трогает не чаще, чем раньше трогал документацию. То есть, как вы уже поняли, никогда. Это нормально. Важно другое: агент работает внутри того же процесса, что и человек, — с теми же ветками, тестами и правилами слияния. Скидок на «он же умный» нет.
Тесты проходят трижды.
Первый раз — локально, на машине разработчика, ещё до пулл-реквеста. Агент написал изменение — агент же прогнал тесты. Красное до чужих глаз не доходит.
Второй раз — в CI (continuous integration, непрерывная интеграция: автоматическая проверка каждого изменения), на каждом пулл-реквесте и потом ещё раз после слияния в main. На облачной машине GitHub, не на нашем сервере: проверка стиля кода, проверка типов, тесты, сборка. Слить ветку, пока проверки красные, невозможно — не «нежелательно», а технически невозможно. Заодно GitHub проверяет, не конфликтует ли ветка с основной. Если кто не знал — это стандартные возможности, тут нет магии. Нужен конфиг для GitHub. Любой агент вам его заточит за 5 минут, вы главное — попросите.
Третий раз — при сборке на проде, потому что гладиолус.
Тестов много, и с каждой новой функцией их становится больше. Это не гарантия, что ничего не сломано, — такой гарантии не даёт никто, кроме коммерческих предложений. Но на этом уровне мы проверяем всё, что можем проверить, и знаем, что именно не проверили.
Отдельный тест следит за миграциями базы. Миграции у нас только добавляют: новые таблицы, новые колонки. Удалять и переименовывать запрещено, и запрет держит не устная договорённость, а тест. Зачем — станет понятно через пару разделов.
Выкатка: сервер сам приходит за работой
После слияния в main и зелёного CI начинается выкатка. Вот здесь у многих команд и прячется главный тормоз: один человек, который «знает, как деплоить», и его ноутбук.
У нас выкатку запускает не человек и даже не GitHub. На продакшен-сервере работает агент выполнения задач CI — runner. Он держит исходящее соединение с GitHub и время от времени вежливо интересуется: нет ли для него работы? Когда работа появляется, он выполняет её у себя.
Из этого следует несколько приятных вещей:
-
в секретах GitHub нет SSH-ключа от продакшена;
-
на сервере нет входящего порта для деплоя;
-
нет реестра контейнерных образов: образ собирается прямо на сервере;
-
секреты приложения лежат только на сервере, в GitHub их нет.
Что стоит на продакшен-сервере и кто кого вызывает
Выкатывается ровно тот коммит, который проверил CI, а не тот, что оказался последним в main к моменту выкатки. Иначе в продакшен могло бы уехать то, что CI ещё не досмотрел.
Релизы идут строго по одному. Начатый релиз никогда не прерывается. Если за это время в очереди накопилось два — выкатывается самый свежий, промежуточный пропускается. Его изменения всё равно входят в свежий.
Blue-green: новую версию ставят рядом, а не вместо
На сервере живут две копии приложения — условно синяя и зелёная — и прокси перед ними. В каждый момент трафик получает ровно одна копия. Какая именно, записано одной строкой в одном файле. Не в голове администратора, не в чате, не в таблице «кто где» — в файле.
Выкатка идёт так:
1. На сервере скриптом собирается образ новой версии.
2. Запускается та копия, которая сейчас простаивает.
3. Проверка здоровья: новая копия должна ответить, что она жива, и назвать номер своего коммита. До тридцати попыток с интервалом в две секунды. Одного «я жива» мало: на том же порту мог остаться старый контейнер, который тоже жив и тоже рад ответить.
4. Если проверка не прошла — стоп. Трафик не тронут, пользователи ничего не заметили, сломанная копия оставлена, чтобы прочитать её логи.
5. Если прошла — прокси переключается на новую копию. Это точка невозврата: до неё любую ошибку исправляет бездействие, после неё — только откат.
6. Старая копия ещё шестьдесят секунд дорабатывает начатые запросы. Самый долгий запрос к Битрикс24 ограничен пятнадцатью секундами, так что запас четырёхкратный.
7. Старую копию останавливают, но не удаляют. Остановленная копия — это готовый откат: её достаточно снова запустить.
8. Уборка: на сервере остаются три последних образа, остальное удаляется.
Blue-green выкатка по шагам
Теперь про миграции. Шестьдесят секунд обе версии работают с одной базой. Старая версия ничего не знает о новых колонках, но и не падает от них. А вот если бы новая версия удалила колонку, старая упала бы посреди чьего-то запроса. Поэтому запрет на удаление держит тест, а не память о том, почему так нельзя. Память у команды, как известно, коллективная, то есть ничья.
Та же история с фоновыми задачами. Планировщик — напоминания, проверки порталов — тикает в обеих копиях. Чтобы за минуту перекрытия ничего не ушло дважды, каждое действие сначала застолбляется записью в базе. Кто первый записал, тот и выполняет. Второй видит запись и скромно отходит.
Как узнать, что релиз прошёл
Можно, конечно, спросить в чате: «Ну что, выехало?» Но у нас для этого есть способы скучнее и надёжнее:
-
Комментарий в пулл-реквесте. После выкатки бот пишет в слитый пулл-реквест: релиз выпущен, вот состояние сервиса до и после. Цвет копии между строками должен смениться. Не сменился — значит, трафик никуда не переехал, что бы ни утверждала зелёная галочка.
-
Статус на коммите — галочка или крестик.
-
Сводка в Actions — та же таблица до и после.
-
Журнал выкаток на сервере — каждый релиз и откат с временем.
Если выкатка упала, GitHub присылает уведомление тому, кто слил пулл-реквест. Не всем, не в общий чат, не начальнику — тому, кто слил. Письмо, адресованное лично, хотя бы читают.
Если что-то пошло не так
Что случилось
Что происходит
CI красный
Выкатка не запускается. Продакшен не тронут.
Сборка упала
Релиз остановлен до переключения. Продакшен не тронут.
Новая копия не прошла проверку
Релиз остановлен до переключения. В пулл-реквесте появляется комментарий, что продакшен обслуживает прежний коммит.
Новая версия работает, но с ошибкой
Скрипт отката запускает прошлую копию и переключает прокси обратно. Ничего не пересобирается, база не трогается.
Прошлой копии уже нет
Выкатывается один из трёх сохранённых образов.
Ручной откат на сервере — только для аварий и только по согласию ответственного. Исправление потом всё равно проходит через пулл-реквест. Правило «через PR, а не руками» не отменяется даже пожаром — пожар тушат руками, а ремонт делают по проекту.
Каждую ночь делается резервная копия базы, хранятся семь последних. Порядок восстановления описан заранее, а не будет сочиняться в момент восстановления.
А где стейджинг?
Его нет, и это осознанное решение. Для нашего сервиса отдельное промежуточное окружение было бы переусложнением: ещё один сервер, ещё одна база, ещё одна вещь, которая расходится с продакшеном именно в тот момент, когда на неё полагаются.
При этом ничто не мешает его добавить. Промежуточный сервер, отдельный тестовый портал Битрикс24, прогон пользовательских сценариев в специальном окружении — всё это ложится в ту же схему ещё одной ступенькой. Конвейер для того и строится, чтобы ступеньки добавлялись, а не изобретались заново.
QA тоже делает агент
Последнее звено. После выкатки агенты проверяют не только тесты, но и пользовательские сценарии — прямо в интерфейсе приложения: открыть страницу, нажать кнопку, убедиться, что результат совпал с ожидаемым. Та часть контроля качества, которую раньше делал человек с чек-листом и терпением, тоже автоматизирована.
Терпение при этом, кстати, никуда не делось. Просто теперь оно уходит на постановку задачи, а не на тридцатый клик по одной и той же кнопке.
Итого
Цикл целиком выглядит так:
-
Идея → агент заводит issue в бэклог с нужными метками.
-
Задачу берут в работу → агент пишет код в ветке под присмотром разработчика.
-
Тесты локально → пулл-реквест → тесты и сборка в CI. Красное не сливается.
-
Слияние в main → задача закрывается автоматически.
-
Runner на сервере забирает выкатку → blue-green → проверка → переключение.
-
Комментарий о релизе в пулл-реквесте → агент проверяет сценарии в интерфейсе.
Ни одно из этих звеньев не про AI. Это обычная инженерная дисциплина, известная задолго до нейросетей под скромным названием CI/CD — непрерывная интеграция и доставка. Но именно она превращает «агент написал код за десять минут» в «изменение у пользователей сразу после слияния», а не через неделю согласований, ручной выкатки и вопроса «а кто последний трогал сервер?».
Без неё агент пишет быстро, а выкатывается всё так же медленно. Ускорение остаётся на ноутбуке разработчика и до пользователя не доезжает — как курьер, который очень быстро бегает, но адреса не знает.
Источник: habr.com