Аббревиатуру 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 — ровно одно решение: доверяете ли вы автовикату.
Из чего состоит пайплайн
Любой пайплайн — последовательность стадий/джоб, каждая из которых:
- Запускается по триггеру — пуш, pull request, тег, расписание, вручную.
- Работает в чистом окружении (runner/контейнер): ставит нужную версию языка, кэширует зависимости.
- Выполняет шаги: checkout кода → install → lint → test → build → deploy.
- Публикует артефакты/статус: билд-архив, отчёт покрытия, зелёный/красный чек на PR.
Три понятия, которые встречаются во всех системах под своими именами:
| Идея | GitHub Actions | GitLab CI | Jenkins |
|---|---|---|---|
| Триггер/контейнер стадии | jobs.<id>.on/workflow | stages + rules | pipeline stages |
| Единица работы | job | job | stage/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/if | when { 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 ключ — уже скомпрометированный ключ.
Где стабильно наступают
- Deploy без гейта. Джоба выката есть, но условий «только main + все тесты зелёные» нет — зелёный билд фича-ветки уезжает на прод.
- Секреты в
run:через echo / в логах. GitLabActions маскируют${{ secrets.* }}, но если вы сделалиecho "token=$TOKEN"— часть может засветиться в артефактах логов. - Кэш по неверному ключу. Кешируют
node_modulesпод ключом отpackage-lock.json, но забывают, что при смене версии раннера кэш протухает. - Матрица без
fail-fast: false. Одна ветка матрицы (php 8.2) падает — остальные отменяются, и вы не видите, что на 8.3 всё было хорошо. - Нет отката. Пайплайн умеет только «наверх». Continuous Deployment без health-check и auto-rollback — это автоматическая доставка аварий до пользователей.
- Валидные ключи системы перепутаны с чужими. Написать в GitHub Actions
stages:(это GitLab) или в GitLabuses:(это 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 / Delivery / Deployment из начала статьи никуда не девается — генератор снимает рутину «вспомнить, как в этой системе пишется кэш и условие ветки». Решать, доверяете ли вы автовикату и нужен ли откат, всё равно вам; а корректный под систему YAML/DSL вы получаете сразу.
👤 Зарегистрируйтесь, чтобы добавить материал в закладки.
