Что должен уметь CI/CD-пайплайн на самом деле (без маркетинга)
Вы пушите код, пайплайн зеленеет, деплой уходит в прод. Но когда что-то ломается, вы понимаете: пайплайн никогда не был спроектирован для такой ситуации. Миграция базы данных выполнилась в неправильном порядке. Артефакт из стейджинга отличается от того, что попал в продакшен. А про откат никто даже не подумал.
Это разница между «у нас есть пайплайн» и «у нас есть пайплайн, который реально работает». Jenkins, GitHub Actions, GitLab CI, ArgoCD — все эти инструменты обещают доставку, но проблема никогда не в инструменте. Проблема в отсутствующих возможностях. Если в пайплайне нет правильных строительных блоков, никакой инструмент это не исправит.
Вот шесть фундаментальных возможностей, которые должны быть в каждом CI/CD-пайплайне. Не «хорошо бы иметь», не «добавим, когда будет время». Это минимальные требования для безопасной доставки изменений из кода в продакшен.
Сборка: превратить код в нечто выполняемое
Каждый раз, когда разработчик пушит изменение, пайплайн должен превратить этот код в то, что реально можно запустить. Для компилируемых языков (Go, Rust, Java) это означает сборку исходников в бинарники. Для интерпретируемых (Python, JavaScript) — проверку синтаксиса, сборку модулей, разрешение зависимостей и подготовку среды выполнения.
Сборка — первый шлюз. Если код не собирается, всё остальное не имеет значения. Пайплайн должен падать быстро, не тратя время на тесты кода, который даже не компилируется.
Частая ошибка — относиться к сборке как к простому шагу, который всегда работает. Но окружения сборки различаются. Сборка, успешная на ноутбуке разработчика, может упасть в пайплайне из-за отсутствия системных библиотек, других версий инструментов или переменных окружения. Шаг сборки в пайплайне должен быть воспроизводимым и изолированным, чтобы то, что работает в CI, работало везде.
Тестирование: ловить проблемы до того, как их увидят пользователи
После успешной сборки пайплайн должен запускать автоматические тесты. Речь не только о юнит-тестах, которые выполняются за миллисекунды. Здоровый пайплайн запускает несколько уровней тестирования:
- Юнит-тесты, проверяющие отдельные поведения
- Интеграционные тесты, проверяющие совместную работу компонентов
- Сквозные тесты, симулирующие реальные сценарии пользователей
Каждый уровень ловит разные типы проблем. Юнит-тесты — логические ошибки. Интеграционные — несоответствия между сервисами. Сквозные — сбои в рабочих процессах, затрагивающие несколько систем.
Ключевой момент — автоматизация. Тесты должны запускаться без участия человека. Если кто-то должен вручную запускать тесты или интерпретировать результаты, пайплайн теряет свою основную ценность: скорость и консистентность. Каждый автоматический тест — это одна вещь, которую человеку не нужно помнить.
Упаковка: создать версионированный развёртываемый артефакт
Когда код собран и тесты пройдены, пайплайн должен упаковать результат в артефакт, готовый к развёртыванию. Формат артефакта зависит от того, что вы доставляете:
- Контейнерный образ для микросервисов
- Бинарный файл для десктопных приложений
- APK или IPA для мобильных приложений
- ZIP-архив для serverless-функций
- Helm-чарт для развёртывания в Kubernetes
Каждый артефакт должен иметь уникальную версию. Не просто метку времени или номер сборки, а версию, которая привязывается к точному коммиту, запуску пайплайна и результатам тестов. Эта прослеживаемость позволяет точно знать, что работает в продакшене и что изменилось между версиями.
Артефакт должен храниться в центральном реестре или репозитории, доступном для этапа развёртывания. Если вы пересобираете артефакт во время деплоя, вы теряете консистентность. Артефакт, прошедший тесты, должен быть тем же самым артефактом, который попадает в продакшен.
Развёртывание: разместить артефакт в целевой среде
Деплой — это не просто копирование файлов. Это процесс размещения новой версии в среде и обеспечения обработки трафика. Для стейджинга деплой означает установку новой версии для тестирования. Для продакшена — замену работающей версии без прерывания работы пользователей.
Для разных уровней риска существуют разные стратегии развёртывания:
- Rolling update: замена инстансов по одному
- Blue-green: переключение трафика между двумя идентичными средами
- Canary: направление небольшого процента трафика на новую версию
- Feature flags: развёртывание кода, но скрытие его за переключателем
Пайплайн должен поддерживать правильную стратегию для каждой среды. Для стейджинга подойдёт простая замена. Для продакшена часто требуется постепенное развёртывание с мониторингом. Пайплайн должен автоматизировать весь процесс, а не только копирование файлов.
Миграции: безопасно работать с изменениями базы данных
Если ваше приложение использует базу данных, пайплайн должен обрабатывать миграции схемы. Добавление колонки, изменение типа данных или создание новой таблицы требует выполнения скриптов миграции в определённом порядке. Эти миграции нельзя смешивать случайным образом с развёртыванием приложения.
Сложность в порядке выполнения. Иногда миграция должна запускаться до развёртывания нового кода приложения. Например, добавление nullable-колонки, которую будет использовать новый код. В других случаях миграция должна запускаться после развёртывания нового кода. Например, удаление старой колонки, на которую всё ещё ссылается старый код.
Пайплайн должен знать этот порядок и выполнять его корректно. Миграция, запущенная не вовремя, может привести к простою, потере данных или и тому, и другому. Это одна из самых недооценённых возможностей CI/CD-пайплайнов и одна из самых опасных при неправильной реализации.
Откат: отменить изменения, когда что-то пошло не так
Не каждый деплой успешен. Когда новая версия вызывает ошибки, деградацию производительности или повреждение данных, пайплайн должен уметь откатиться к предыдущей версии. Откат — это не просто повторное развёртывание старого артефакта. Он включает:
- Возврат приложения к предыдущей версии
- Запуск обратных миграций базы данных
- Восстановление конфигурации инфраструктуры
- Проверку, что откат действительно сработал
Откат должен быть спланирован до первого деплоя. Если вы проектируете пайплайн, не думая о том, как отменить изменения, вы будете в панике писать скрипты отката, пока продакшен лежит. Это худшее время для разбирательств.
Для миграций базы данных откат означает наличие down-миграций, которые отменяют up-миграции. Для инфраструктуры — хранение предыдущих файлов состояния или использование инструментов infrastructure-as-code, поддерживающих откат состояния. Для приложений — сохранение предыдущего артефакта и наличие стратегии развёртывания, поддерживающей мгновенное переключение.
Собирая всё вместе
Эти шесть возможностей — сборка, тестирование, упаковка, развёртывание, миграции и откат — формируют основу любого реального CI/CD-пайплайна. В зависимости от того, что вы доставляете, некоторые возможности могут выглядеть иначе. Пайплайны для инфраструктуры могут заменить сборку и упаковку на валидацию конфигурации и подготовку состояния. Мобильные пайплайны могут добавить подпись кода и отправку в магазин приложений. Но основные функции остаются теми же.
Вот минимальный пайплайн GitLab CI, который сопоставляет каждую возможность со стадией:
stages:
- build
- test
- package
- deploy
- migrate
- rollback
build:
stage: build
script:
- go build -o app
test:
stage: test
script:
- go test ./...
package:
stage: package
script:
- docker build -t myapp:$CI_COMMIT_SHA .
- docker push registry.example.com/myapp:$CI_COMMIT_SHA
deploy:
stage: deploy
script:
- kubectl set image deployment/myapp myapp=registry.example.com/myapp:$CI_COMMIT_SHA
migrate:
stage: migrate
script:
- ./run_migrations up
rollback:
stage: rollback
script:
- ./run_migrations down
- kubectl rollout undo deployment/myapp
when: manual
Следующая диаграмма показывает, как эти шесть возможностей соединяются в типичном пайплайне:
Прежде чем выбирать CI/CD-инструмент или перепроектировать пайплайн, составьте карту: какие из этих возможностей у вас есть, а какие отсутствуют. Инструмент, который обещает всё, но не умеет обрабатывать миграции базы данных или планирование отката, оставит вас уязвимыми.
Краткий чек-лист возможностей
- Сборка выполняется в изолированном, воспроизводимом окружении
- Тесты запускаются автоматически на нескольких уровнях
- Артефакты версионированы и хранятся в центральном реестре
- Развёртывание поддерживает правильную стратегию для каждой среды
- Миграции базы данных упорядочены относительно развёртывания приложения
- Откат протестирован и работает для приложения, базы данных и инфраструктуры
Конкретный вывод
Пайплайн — это не набор шагов. Это система, которая должна обрабатывать полный жизненный цикл изменения: от кода до работающего сервиса и обратно, если потребуется. Если ваш пайплайн не умеет собирать, тестировать, упаковывать, развёртывать, мигрировать и откатывать, он неполноценен. Начните с заполнения отсутствующей возможности, а не со смены инструмента.