«Запустил билд. Пошёл сварил кофе. Вернулся. Всё ещё крутится».
Вот так выглядел обычный день на enterprise-платформе e-commerce, куда меня позвали. Пайплайны на Jenkins были настолько медленными, что разработчики мерили сборку не в минутах, а в походах за кофе. А теперь умножьте это на каждый pull request, каждую feature-ветку, каждый хотфикс — на всю инженерную команду. Получается очень дорогая привычка, которую никто даже не пытался посчитать. Меня взяли ровно за одним: вернуть скорость. Это честная история той самой миграции с Jenkins на GitHub Actions — что я нашёл, что реально поменял и что в итоге сработало.
Легаси-боль по учебнику
Всё в этой конфигурации было из серии «киваешь, потому что видел это десять раз». Всё выполнялось последовательно. Кэширования не было вообще — каждый запуск пересобирался с нуля. Общие раннеры стояли в очереди по двадцать минут, прежде чем билд вообще стартовал. А сверху — слой flaky-тестов, которые никто не трогал: единственным «фиксом» было перезапустить и надеяться на зелёный.
Вот это последнее важнее, чем звучит. Когда твой единственный способ починки — «запусти ещё раз», ты уже проиграл. Пайплайн перестаёт быть инфраструктурой и превращается в игровой автомат.
Я начал с карты, а не с миграции
Прежде чем написать хоть строчку нового YAML, я составил карту всех пайплайнов, которые реально работают. Не по документации — её не было. По живым, работающим джобам. Их оказалось 47. Некоторые не трогали три года, но они исправно запускались каждый день. Половину из них никто в офисе не мог даже объяснить — что они деплоят.
Именно этот шаг все пропускают, и именно он спасает. Нельзя модернизировать то, чего не видишь. Так что сначала я зафиксировал реальную картину, а потом нашёл боттлнеки:
- Последовательный прогон тестов — без всякой причины, просто так исторически сложилось
- Полная установка зависимостей на каждом запуске — ничего не кэшировалось, каждый билд заново тянул полмира
- Ноль параллелизма между сервисами — всё ждало своей очереди
- Ручные approve-гейты — упиравшиеся в одного человека, который вечно был на встречах
Что я повторял стейкхолдерам как мантру: проблема не в инструменте. Просто заменить Jenkins на GitHub Actions, сохранив ту же форму, не дало бы почти ничего. Миграция была поводом. Смысл был в смене архитектуры.
Новая архитектура
Вместо монолита из джоб-снежинок я собрал что-то модульное и скучное — скучное в самом хорошем смысле.
- Общие переиспользуемые workflow — один источник правды, который дёргает любой репозиторий в организации, вместо 47 разных вариантов руками
- Matrix builds — тесты параллельно на нескольких версиях Node, а не в одну медленную полосу
- Кэш зависимостей — билд перестал платить полный «налог на установку» каждый раз
- Аналитика билдов по каждому pull request — разработчик наконец видел, замедлил ли его коммит сборку
- Деплой с health-check-гейтами и автоматическим откатом — больше никаких скрещенных пальцев на релизе
В основе всего лежал один универсальный шаблон пайплайна на 634 строки. Теперь каждый сервис деплоится одинаково. Никаких конфигов-снежинок, никакого «ну у меня-то на моём Jenkins работает». В enterprise-масштабе эта стандартизация стоит не меньше, чем сама скорость.
Результат
Билды, которые раньше шли 55 минут, теперь завершаются за 7.
Это заголовочная цифра, и она настоящая. Но цифра, которая мне на самом деле дорога, — это изменение поведения за ней. Разработчики перестали варить кофе во время сборки, потому что билд заканчивается раньше, чем закипает чайник. Один из них сказал, что ощущение — будто перешёл в другую компанию. Вот это и есть победа — не семь минут, а то, что деплой перестал ощущаться как наказание.
Самое сложное было не техническим
Буду честен. Параллельные билды, кэш, matrix-тесты — это просто инженерия. Она познаваема и конечна, её можно просто перемолоть. По-настоящему сложным было убедить команды, что боль от изменения меньше, чем боль от того, чтобы остаться как есть. Люди уже смирились с походами за кофе. Они выстроили весь свой день вокруг сломанного пайплайна. Перемена — это угроза ровно до того момента, пока она перестаёт ею быть.
Твой пайплайн — это продукт
Вот что я хочу, чтобы вы отсюда забрали. Медленный пайплайн — это не мелкое неудобство, которое можно обойти. Это налог на каждого разработчика, каждый день. Он тихо убивает темп, а потом убивает мораль.
Ваш CI/CD-пайплайн — это продукт, а разработчики — его пользователи. Измеряйте его. Оптимизируйте. Относитесь к 55-минутному билду как к инциденту, которым он и является. Сделайте это — и вы вернёте людям то самое чувство, ради которого они вообще пошли писать код: чувство отгрузки.
Так что честно: сколько сейчас идёт ваш самый медленный пайплайн — и вы, случайно, просто молча с этим смирились?