Почему пересборка для продакшена рискованнее, чем кажется
У вас зелёная сборка на стейджинге. Тесты пройдены. Команда готова к релизу. Кто-то говорит: «Давайте просто возьмём тот же тег, пересоберём и задеплоим в продакшен. Нам не нужно хранить старые артефакты».
Звучит эффективно. Не нужно управлять хранилищем артефактов. Не нужно копаться в старых сборках. Просто запустили сборку заново и задеплоили. Но этот, казалось бы, практичный подход порождает две проблемы, которые незаметно подрывают всё, чего вы пытаетесь достичь с помощью пайплайна доставки: вы теряете отслеживаемость и воспроизводимость.
Проблема отслеживаемости
Когда вы пересобираете для продакшена, артефакт, работающий в продакшене, — это не тот же артефакт, который прошёл тесты на стейджинге. Вы собрали его из того же исходного кода, но процесс сборки создал новый артефакт с новой идентичностью. У него другая контрольная сумма, другая временная метка сборки и, возможно, другие встроенные метаданные.
Если в продакшене что-то пойдёт не так, вы не сможете указать на результаты стейджинга и сказать: «именно этот артефакт был протестирован». Вам придётся довериться тому, что вторая сборка дала идентичный результат. Без проверки это доверие слепо.
Следующая блок-схема сравнивает два подхода:
Отслеживаемость — это не бюрократия. Это возможность ответить на простой вопрос: «Что именно сейчас работает в продакшене, и как я могу быть уверен, что это соответствует тому, что мы тестировали?» Когда вы пересобираете, на этот вопрос становится сложно ответить с уверенностью.
Проблема воспроизводимости
Даже если вы берёте тот же самый коммит, процесс сборки не всегда даёт одинаковый результат. Множество факторов могут изменить результат между двумя сборками:
Дрейф зависимостей. Ваша первая сборка в понедельник подтянула версию 1.2.3 открытой библиотеки. К среде мейнтейнер выпустил версию 1.2.4. Ваша вторая сборка автоматически подтягивает новую версию. Исходный код не изменился, но поведение приложения могло измениться. Небольшой патч может исправить ошибку, на которую вы полагались, или внести регрессию. Он также может незаметно подтянуть уязвимость в безопасности.
Обновления базового образа. Если ваша сборка использует Docker-образ с тегом latest или даже с конкретной минорной версией, которая получает патчи, вторая сборка может использовать другой слой операционной системы. Код приложения тот же, но среда выполнения изменилась.
Различия в среде сборки. На CI-раннере, собиравшем стейджинг, могла быть немного другая версия JDK, Node.js или системных библиотек. Возможно, кеш сборки истёк между запусками, что вызвало полную перекомпиляцию с другим байт-кодом. Эти различия редко проявляются при разработке, но могут привести к трудноуловимым сбоям в продакшене.
Временные метки и метаданные. Многие инструменты сборки встраивают в артефакт временные метки, номера сборки или хеши коммитов. Даже если функциональный код идентичен, метаданные артефакта различаются. Это усложняет отладку, когда нужно сопоставить поведение продакшена с конкретной сборкой.
Реальное влияние
Эти проблемы не теоретические. Команды выкатывали пересборки в продакшен и обнаруживали, что автоматически обновлённая зависимость внесла уязвимость в безопасность. Другие видели, как поведение приложения менялось из-за того, что патч-релиз библиотеки изменил работу функции. В некоторых случаях пересборка давала артефакт, который отлично работал в разработке, но падал в продакшене из-за другой версии компилятора в среде сборки.
Хуже всего то, что эти проблемы трудно обнаружить. Пайплайн зелёный. Хеш коммита совпадает. Всё выглядит нормально, пока кто-то не замечает, что в продакшене что-то не так, и к тому моменту поиск первопричины превращается в криминалистическую экспертизу.
Принцип: собрал один раз — продвигай везде
Именно поэтому существует принцип «build once, promote many». Вы собираете артефакт один раз, проверяете его, а затем продвигаете тот же самый артефакт через все окружения: разработку, стейджинг, продакшен. Никакой пересборки. Никаких вторых шансов.
При таком подходе артефакт в продакшене физически идентичен артефакту, прошедшему все тесты. Контрольная сумма совпадает. Встроенные метаданные совпадают. Вы точно знаете, что было протестировано и что было выкачено. Отслеживаемость встроена, потому что каждый артефакт имеет уникальный идентификатор, связанный с его коммитом, конфигурацией сборки и временной меткой. Воспроизводимость не является проблемой, потому что вы ничего не воспроизводите — вы используете тот же самый бинарник.
Когда пересборка неизбежна
Существуют легитимные случаи, когда пересборка необходима. Старый артефакт может быть несовместим с обновлением продакшен-инфраструктуры. Критический патч безопасности в базовом образе может вынудить к пересборке. Требования комплаенса могут потребовать, чтобы артефакты продакшена собирались в специальной ужесточённой среде.
Такие ситуации существуют, но они должны быть исключениями, а не правилом. Каждый раз, когда ваша команда решает пересобрать для продакшена, вы должны явно признать риски: вы нарушаете отслеживаемость и делаете ставку на то, что сборка воспроизводима. Задокументируйте решение, проверьте, что результат соответствует оригинальной сборке, и используйте это как возможность для разбора инцидента, чтобы предотвратить пересборки в будущем.
Практический чек-лист перед пересборкой для продакшена
- Можете ли вы проверить, что пересобранный артефакт функционально идентичен протестированному?
- Зафиксировали ли вы все версии зависимостей, включая транзитивные?
- Идентична ли среда сборки (компилятор, рантайм, системные библиотеки) оригинальной сборке?
- Зафиксированы ли базовые образы по конкретным дайджестам, а не по тегам?
- Есть ли у вас задокументированная причина, почему продвижение оригинального артефакта невозможно?
- Согласна ли команда рассматривать это как исключение, а не как стандартную практику?
Вывод
Каждая пересборка для продакшена вносит неопределённость в ваш пайплайн доставки. Вы теряете возможность с уверенностью сказать, что артефакт, работающий в продакшене, — это тот же самый, что прошёл тестирование. Экономия на хранении артефактов или удобство редко стоят затрат на отладку, когда что-то идёт не так. Собирайте один раз. Продвигайте один и тот же артефакт везде. Пусть пересборка будет исключением, требующим явного обоснования, а не стандартным путём в продакшен.