Перейти к основному содержимому

7.04. Процесс CI/CD

Разработчику Архитектору Инженеру

Процесс CI/CD

CI/CD (Continuous Integration / Continuous Delivery or Deployment) — это совокупность практик, инструментов и процессов, направленных на автоматизацию этапов разработки, тестирования, сборки, релиза и развёртывания программного обеспечения с целью обеспечения непрерывной, предсказуемой и надёжной доставки изменений в продуктивную среду.

CI/CD представляет собой инженерную дисциплину, основанную на принципах системного мышления, обратной связи и минимального ручного вмешательства.

Цель CI/CD — сократить время от написания кода до его выпуска в эксплуатацию, минимизировать вероятность ошибок, повысить качество ПО и обеспечить воспроизводимость всех этапов жизненного цикла. При этом CI/CD-пайплайн (pipeline) — это оркестрированная последовательность автоматизированных задач, выполняемых в строго определённом порядке, каждая из которых имеет чётко заданный вход, выход и критерии успеха.

В современной инженерной практике CI/CD-пайплайн традиционно разделяется на две логические части:

  • Continuous Integration (CI) — фаза, охватывающая процессы, связанные с интеграцией кода в общую базу, его сборкой и первичным тестированием.
  • Continuous Delivery/Deployment (CD) — фаза, включающая подготовку к выпуску, релиз, развёртывание, управление инфраструктурой и мониторинг работоспособности в продакшене.

Следует отметить, что Continuous Delivery предполагает возможность ручного одобрения перед релизом, тогда как Continuous Deployment подразумевает автоматическое развертывание каждого прошедшего все проверки изменения в продакшен. В рамках данного материала термин CD используется в широком смысле, охватывающем оба варианта. Но на практике, воспринимайте именно как Deployment.

Я бы выделил восемь последовательных этапов:

  1. Планирование;
  2. Разработка;
  3. Сборка;
  4. Тестирование;
  5. Релиз;
  6. Развёртывание;
  7. Управление развёртыванием;
  8. Мониторинг.

Хотя планирование и разработка логически предшествуют CI, они не являются частью автоматизированного пайплайна и относятся к процессам подготовки. CI начинается с момента фиксации кода в репозитории и запуска автоматических задач. CD — с момента, когда артефакт считается релизным и начинает движение к продакшену.


Планирование (Planning).

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

Планирование включает:

  • Анализ бизнес-потребностей и формирование пользовательских историй (user stories);
  • Разработку технических спецификаций и диаграмм архитектуры;
  • Оценку трудозатрат и планирование спринтов (в рамках Agile/Scrum);
  • Документирование решений, политик доступа, стандартов кодирования и процедур управления конфигурацией.

Инструменты: Jira, Azure DevOps Boards, YouTrack, Trello, Confluence, Notion.

Планирование обеспечивает согласованность между бизнес-целями и технической реализацией. Отсутствие четкого плана делает автоматизацию бессмысленной — невозможно автоматизировать то, что не определено.


Разработка (Development).

На этапе разработки инженеры реализуют функциональные требования, пишут код в соответствии с принятыми стандартами и архитектурными паттернами. Код разрабатывается в изолированных ветках (feature branches), что позволяет избежать конфликтов и обеспечивает возможность параллельной работы нескольких разработчиков.

Ключевые действия:

  • Написание кода с соблюдением принципов SOLID, DRY и других парадигм;
  • Реализация unit- и integration-тестов на этапе разработки;
  • Фиксация изменений в системе контроля версий с соблюдением семантического коммит-менеджмента;
  • Выполнение локальных проверок кода (linting, форматирование).

Инструменты: GitLab, GitHub, Bitbucket, Azure Repos.

Важно отметить, что мы не говорим о том, что разработчики ещё должны, собственно, разрабатывать продукт - для этого используются, очевидно, инструменты разработки и отладки - IDE (VS, IDEA), клиенты Git (CLI, TortoiseGit, GitHub Desktop, Fork), различные редакторы, СУБД (PostgreSQL, MS SQL), утилиты, прикладное и инженерное ПО - всё, что нужно для написания кода или создания приложений.

В контексте CI/CD не так важна первая реализация программы. Здесь фокус будет именно на изменениях, то есть это вторая, третья и дальнейшие итерации, когда базовая программа/модуль уже созданы, и происходит развитие продукта и изменение кода.

Разработка — источник изменений. Эффективность всей CI/CD-цепочки зависит от качества и регулярности коммитов в Git. Использование git-flow или trunk-based development определяет стратегию интеграции, поэтому ошибка на предыдущем этапе с выбором направления работы, здесь уже будет непростительной.


Сборка (Build).

Сборка — процесс преобразования исходного кода в исполняемую или деплоебельную форму. Это критически важный этап, поскольку именно здесь происходит компиляция, упаковка, разрешение зависимостей и генерация артефактов, которые будут использоваться на всех последующих стадиях. Мы не говорим о сборке на рабочем месте разработчика, нет - абсолютно не важна успешность компиляции на его компьютере, главное - чтобы сборка была успешной именно в рабочей целевой среде. Поэтому должно быть несколько сред - как минимум одна идентичная промышленной.

К примеру, мы хотим создать веб-приложение. Первая реализация содержит в себе самые базовые функции, успешно разворачивается и работает на главном сервере. И для изменения нужно создать идентичную среду на другом сервере (а в идеале - иметь несколько серверов, с хотя бы одним промежуточным), где и будет проверяться то, что изменили разработчики.

Типовые действия:

  • Компиляция исходного кода (в случае языков со статической типизацией);
  • Упаковка в контейнеры, JAR, WAR, MSI, DEB, RPM и другие форматы;
  • Резолвинг зависимостей через менеджеры пакетов;
  • Генерация карт зависимостей и метаданных для трассировки.

Инструменты поэтому тут соответствуют языкам и технологиям:

  • Java/Kotlin/Scala: Maven, Gradle
  • .NET: MSBuild, dotnet CLI, Cake
  • Python: pip, poetry, setuptools
  • JavaScript/TypeScript: Webpack, Vite, esbuild, npm/yarn
  • Go: go build, mod
  • PHP: Composer
  • C/C++: CMake, Bazel, Ninja
  • Universal: Bazel, Pants (для многоязычных репозиториев)

Сборка обеспечивает воспроизводимость. Если сборка не проходит — дальнейшие этапы не имеют смысла. Артефакт, созданный на этом этапе, становится единственным источником правды (single source of truth) для всех последующих стадий.

Важно учитывать, что сборка может быть именно что автоматической, а от администраторов требуется лишь подтверждать действия, чтобы ускорить развёртывание.


Тестирование (Testing).

Тестирование — система автоматизированных проверок, направленных на выявление дефектов на разных уровнях абстракции. Цель — обеспечить, что каждый коммит не нарушает существующую функциональность и соответствует заявленным требованиям.

Различают следующие уровни тестирования:

  • Unit-тесты — проверяют отдельные модули или функции (например, метод класса).
  • Интеграционные тесты — проверяют взаимодействие между компонентами (база данных, API, внешние сервисы).
  • End-to-end (E2E) — имитируют поведение пользователя в полноценной среде.
  • Статический анализ кода — проверка на соответствие стандартам, наличие уязвимостей, дублирования и сложности.
  • Тестирование производительности и безопасности — нагрузочные тесты, SAST/DAST сканеры.

Соответственно, инструменты тоже зависят от вида тестирования:

  • Unit: JUnit (Java), NUnit (.NET), pytest (Python), Jest (JS), GoTest (Go)
  • Integration/E2E: Playwright, Selenium, Cypress, TestNG
  • SAST/DAST: SonarQube, Checkmarx, OWASP ZAP, Snyk
  • Coverage: JaCoCo, Istanbul, Coverage.py

Смысл данного этапа как раз в том, что в команде разработки выделяются специальные сотрудники - QA-инженеры, тестировщики, которые проверяют то, что «налепили» разработчики, и задача тут - найти проблемы. Поэтому на тестовом сервере часто для симуляции сценарии дают «карт-бланш» со всеми задачами, порой формулируемых как «попробуй сломать».

Ручное тестирование требует человеческих затрат и большого количества времени, но автотесты должны быть всегда, чтобы от администраторов требовалось лишь нажать кнопку, и проверка прошла автоматически. Автоматически тестировать можно типовые ошибки, наборы данных, интеграции, доступа, валидации, обязательность, редактируемость и прочие простые вещи. Вручную проверять надо сложные многоэтапные сценарии работы, допустим когда нужно симулировать действия пользователя в определённой ситуации. Но и тут профессионалы автоматизации скажут, что можно обойтись «без рук».

Тестирование — механизм обратной связи. Автоматизированные тесты являются гарантом стабильности системы. Не прошедшие тесты блокируют продвижение артефакта дальше по пайплайну (gatekeeping).


Релиз (Release).

Релиз — это формальное создание версии продукта, готовой к распространению. На этом этапе артефакт, прошедший все этапы CI, маркируется версией (SemVer), сохраняется в репозиторий артефактов и сопровождается метаданными: хэш коммита, автор, дата, список изменений, ссылки на задачи.

Ключевые действия:

  • Присвоение версии (v1.2.3-beta.4);
  • Создание release-ветки или тега в репозитории;
  • Упаковка changelog, документации, лицензий;
  • Загрузка артефакта в централизованное хранилище (Artifact Repository).

Инструменты - Jenkins, GitLab CI/CD, Buildkite, CircleCI, GitHub Actions.

Релиз — точка невозврата. После этого этапа артефакт считается потенциально релизным. Он может быть задержан для ручного одобрения (Continuous Delivery) или сразу отправлен на деплой (Continuous Deployment).


Развёртывание (Deployment).

Развёртывание — процесс помещения артефакта в целевую среду (staging, canary, production). Этот этап отличается от сборки тем, что он связан с применением артефакта к работающей системе, а не с его созданием.

Действия включают:

  • Копирование артефакта на целевые серверы или в контейнерный реестр;
  • Подготовка конфигураций (config maps, secrets);
  • Запуск контейнеров, сервисов, функций;
  • Применение миграций БД (если требуется).

Инструменты:

  • Контейнеризация: Docker (создание образов), Podman
  • Serverless: AWS Lambda, Google Cloud Functions, Azure Functions
  • Облачные платформы: Terraform (инфраструктура как код), Pulumi
  • Специализированные деплоеры: Argo CD, Flux, Spinnaker

Развёртывание — переход от состояния «код написан» к состоянию «код работает». Качество этого этапа определяется воспроизводимостью и повторяемостью — один и тот же артефакт должен разворачиваться одинаково в dev, staging и prod.


Управление развертыванием (Orchestration & Infrastructure Management).

Этот этап отвечает за управление жизненным циклом инфраструктуры и сервисов, обеспечивающих работу приложения. Он включает автоматизированное управление масштабированием, обновлением, отказоустойчивостью и конфигурацией сред.

Ключевые задачи:

  • Управление кластерами контейнеров (оркестрация);
  • Автоматическое масштабирование по нагрузке;
  • Обеспечение высокой доступности (HA) и rolling updates;
  • Управление секретами, сетевыми политиками, RBAC;
  • Инфраструктура как код (IaC): декларативное описание окружения.

Инструменты:

  • Оркестрация: Kubernetes, Docker Swarm, Nomad
  • IaC: Terraform, Pulumi, AWS CloudFormation, Ansible
  • Управление конфигурацией: Helm, Kustomize, Crossplane

Без оркестрации развертывание становится хаотичным. Этот этап гарантирует, что инфраструктура соответствует описанному состоянию (desired state) и способна адаптироваться к изменениям без ручного вмешательства.


Мониторинг и обратная связь (Monitoring & Observability).

Мониторинг — это сбор, агрегация и анализ метрик, логов и трейсов для оценки работоспособности системы в реальном времени. Он замыкает цикл CI/CD, предоставляя данные для принятия решений о качестве релиза и необходимости отката.

Ключевые направления:

  • Метрики: CPU, память, latency, throughput, error rate (Prometheus, Grafana);
  • Логи: централизованный сбор и поиск (ELK Stack, Loki, Splunk);
  • Трассировка: distributed tracing (Jaeger, OpenTelemetry);
  • Алертинг: автоматическое оповещение о девиациях (Alertmanager, PagerDuty);
  • Анализ причин отказов: root cause analysis на основе событий.

Инструменты: Prometheus, Grafana, Datadog, New Relic, ELK, Sentry, OpenTelemetry.

Мониторинг — источник эмпирических данных. Он позволяет переходить от реактивного к проактивному управлению качеством. Если тесты говорят «код работает», то мониторинг говорит «система работает». Именно здесь рождаются новые требования и улучшения для следующего цикла.