CI/CD своими словами: чем сборка отличается от доставки и как не сломать пайплайн

Аббревиатуру CI/CD пишут в каждом втором README, но за ней стоят три разные вещи, которые часто путают: непрерывная интеграция, непрерывная доставка и непрерывное развёртывание. Разберём по косточкам — что вообще делает пайплайн, из чего он состоит в GitHub Actions / GitLab CI / Jenkins, и где люди стабильно наступают на грабли. А в конце — как не переписывать валидные ключи YAML по документации каждый раз.

CI ≠ CD ≠ CD

  • CI (Continuous Integration) — автоматическая сборка и проверка каждого коммита: линтер, тесты, сборка артефакта. Цель — поймать поломку сразу, пока она не уехала в main. Здесь нет выката.
  • Continuous Delivery (непрерывная доставка) — всё, что в CI, плюс подготовка релиза, готового к выкатке одной кнопкой/командой человека. На прод само ничего не уходит.
  • Continuous Deployment (непрерывное развёртывание) — следующий шаг: то, что прошло все проверки, само уезжает на прод, без человеческого «нажать». Требует уверенности в тестах и откате.

Полезная модель: CI — это про «код не сломан»; Delivery — про «релиз готов»; Deployment — про «релиз уже у пользователей». Между Delivery и Deployment — ровно одно решение: доверяете ли вы автовикату.

Из чего состоит пайплайн

Любой пайплайн — последовательность стадий/джоб, каждая из которых:

  1. Запускается по триггеру — пуш, pull request, тег, расписание, вручную.
  2. Работает в чистом окружении (runner/контейнер): ставит нужную версию языка, кэширует зависимости.
  3. Выполняет шаги: checkout кода → install → lint → test → build → deploy.
  4. Публикует артефакты/статус: билд-архив, отчёт покрытия, зелёный/красный чек на PR.

Три понятия, которые встречаются во всех системах под своими именами:

ИдеяGitHub ActionsGitLab CIJenkins
Триггер/контейнер стадииjobs.<id>.on/workflowstages + rulespipeline stages
Единица работыjobjobstage/step
Шаг внутриsteps:script:sh внутри stage
Кэш зависимостейactions/cache, setup-* c cache:cache:paths--mount type=cache
Секреты${{ secrets.X }}variables/CI-переменныеCredentials
«Только на main»if: github.ref == 'refs/heads/main'rules:changes/ifwhen { branch 'main' }

Конкретный пример: что реально делает CI для PHP-проекта

# .github/workflows/ci.yml
on: [push, pull_request]
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: shivammathur/setup-php@v2
        with:
          php-version: '8.3'
          coverage: none
      - run: composer install --no-interaction --prefer-dist
      - run: vendor/bin/phpcs          # линтер
      - run: vendor/bin/phpunit        # тесты

Четыре вещи, которые здесь неочевидны новичку и ломают пайплайн:

  • actions/checkout@v4 обязателен — runner стартует с пустой машиной, код надо принести.
  • Порядок шагов важен: install до lint/test, иначе бинарников вендора просто нет.
  • Кэш — не «ускорение», а часть корректности: без него каждый пуш заново тянет весь vendor, и лимиты/таймауты кончаются.
  • Секреты никогда не пишутся литералом. ${{ secrets.DEPLOY_KEY }}, а не сам ключ. Закоммиченный в YAML ключ — уже скомпрометированный ключ.

Где стабильно наступают

  1. Deploy без гейта. Джоба выката есть, но условий «только main + все тесты зелёные» нет — зелёный билд фича-ветки уезжает на прод.
  2. Секреты в run: через echo / в логах. GitLabActions маскируют ${{ secrets.* }}, но если вы сделали echo "token=$TOKEN" — часть может засветиться в артефактах логов.
  3. Кэш по неверному ключу. Кешируют node_modules под ключом от package-lock.json, но забывают, что при смене версии раннера кэш протухает.
  4. Матрица без fail-fast: false. Одна ветка матрицы (php 8.2) падает — остальные отменяются, и вы не видите, что на 8.3 всё было хорошо.
  5. Нет отката. Пайплайн умеет только «наверх». Continuous Deployment без health-check и auto-rollback — это автоматическая доставка аварий до пользователей.
  6. Валидные ключи системы перепутаны с чужими. Написать в GitHub Actions stages: (это GitLab) или в GitLab uses: (это Actions) — конфигурация не запустится вообще.

Система ≠ пайплайн: почему нельзя «скопировать и чуть поправить»

Главная причина граблей выше — синтаксис каждой системы закрытый. У GitHub Actions набор ключей и синтаксис условий один, у GitLab CI — другой (rules/only-except/variables), у Jenkins (declarative pipeline) — третий (when { branch }, environment {}). «Починить YAML на глаз» здесь нельзя: неверный ключ не даёт предупреждения, он просто не исполняется или роняет пайплайн на старте. Перенос рабочего пайплайна с GitHub на GitLab — это по факту написание нового.

Собираем пайплайн под систему, а не «пример из гугла»

Чтобы не держать в голове, в какой системе как называется кэш и как правильно написать условие «только main», в codestack.space есть AI CI/CD Generator. Вы описываете проект по-человечески, а конфиг собирается под выбранную систему:

  • Система: GitHub Actions, GitLab CI, Jenkins, CircleCI, Azure Pipelines, Travis;
  • Стек: PHP, Node.js, Python, Go, Java, Ruby, .NET, Docker, другое;
  • Флаги: кэш зависимостей, matrix-сборка по версиям, отдельный линт-шаг, deploy только на main.

Генератор знает валидные ключи каждой системы: не подставит stages: в GitHub Actions, завернёт секреты в ${{ secrets.* }} (а не литералом), корректно выстроит порядок шагов checkout → install → lint → test → build и заголовок файла сделает настоящий (.github/workflows/ci.yml, .gitlab-ci.yml, Jenkinsfile). Попробуйте инструмент прямо здесь, на своих данных:

Генератор CI/CD
Гость
Токены: 0 / 50 000
Гостевой лимит — 50 000 токенов. Зарегистрируйтесь, для пользователей лимит + 200 000 токенов.

Понимание разницы CI / Delivery / Deployment из начала статьи никуда не девается — генератор снимает рутину «вспомнить, как в этой системе пишется кэш и условие ветки». Решать, доверяете ли вы автовикату и нужен ли откат, всё равно вам; а корректный под систему YAML/DSL вы получаете сразу.

👤 Зарегистрируйтесь, чтобы добавить материал в закладки.