Что должен уметь 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

Следующая диаграмма показывает, как эти шесть возможностей соединяются в типичном пайплайне:

flowchart TD A[Code Push] --> B[Build] B --> C[Test] C --> D{Package} D --> E[Deploy] E --> F[Migrate DB] F --> G{Health Check} G -- Pass --> H[Complete] G -- Fail --> I[Rollback] I --> J[Restore DB] J --> K[Redeploy Previous] K --> L[Verify]

Прежде чем выбирать CI/CD-инструмент или перепроектировать пайплайн, составьте карту: какие из этих возможностей у вас есть, а какие отсутствуют. Инструмент, который обещает всё, но не умеет обрабатывать миграции базы данных или планирование отката, оставит вас уязвимыми.

Краткий чек-лист возможностей

  • Сборка выполняется в изолированном, воспроизводимом окружении
  • Тесты запускаются автоматически на нескольких уровнях
  • Артефакты версионированы и хранятся в центральном реестре
  • Развёртывание поддерживает правильную стратегию для каждой среды
  • Миграции базы данных упорядочены относительно развёртывания приложения
  • Откат протестирован и работает для приложения, базы данных и инфраструктуры

Конкретный вывод

Пайплайн — это не набор шагов. Это система, которая должна обрабатывать полный жизненный цикл изменения: от кода до работающего сервиса и обратно, если потребуется. Если ваш пайплайн не умеет собирать, тестировать, упаковывать, развёртывать, мигрировать и откатывать, он неполноценен. Начните с заполнения отсутствующей возможности, а не со смены инструмента.