Пайплайн CI/CD: от пуша до рабочего сервера

Как проходит пайплайн из восьми задач, чем CI отличается от поставки и развёртывания, быстрый пайплайн за 4 минуты вместо 15, сравнение шести инструментов, четыре способа выкладки, два файла кода, правила и ошибки.

Стек и технологии Обновлено

Коротко

Пайплайн CI/CD — это путь, который каждое изменение кода проходит автоматически: линтер, проверка типов и тесты, затем сборка, выкладка на тестовый сервер и на рабочий, а после — наблюдение и откат, если выросли ошибки. CI — непрерывная интеграция — проверяет каждое изменение до того, как его примут в основную ветку. CD — это либо непрерывная поставка, когда релиз готов, а кнопку нажимает человек, либо непрерывное развёртывание, когда всё, что прошло проверки, выходит в работу само. Пайплайн описывают в файле рядом с кодом: на GitHub это GitHub Actions, на GitLab — GitLab CI/CD. Небольшому сайту он заменяет ручную заливку файлов и забытые шаги, а команде даёт выкладывать изменения каждый день, не ломая друг другу работу. Хороший пайплайн проходит меньше чем за десять минут, останавливается на первой упавшей проверке и возвращает прошлую версию за секунды.

Как проходит пайплайн

Восемь задач от пуша до рабочего сервера. Переключите сценарий: всё проходит, падает тест или плохой релиз доходит до рабочего сервера.

  1. Пуш git push в main 0:02
  2. Линтер стиль и ошибки 0:38
  3. Типы tsc --noEmit 0:51
  4. Тесты 214 тестов 2:04
  5. Сборка npm run build 1:12
  6. Тестовый выкладка и проверка 0:46
  7. Рабочий выкладка 0:31
  8. Наблюдение ошибки, 10 минут 10:00
✓ 214 тестов прошли
✓ тестовый сервер отвечает 200
✓ выложено: v1.42 → рабочий сервер
✓ ошибок не больше, чем до выкладки

Выкладка прошла сама: от пуша до рабочего сервера — меньше пяти минут, на сервер никто не заходил.

  1. Пуш git push в main 0:02
  2. Линтер стиль и ошибки 0:38
  3. Типы tsc --noEmit 0:51
  4. Тесты 214 тестов 1:47
  5. Сборка npm run build —
  6. Тестовый выкладка и проверка —
  7. Рабочий выкладка —
  8. Наблюдение ошибки, 10 минут —
✗ checkout.test.ts › скидка не применяется к корзине
  ожидалось 2 700 ₽, получено 3 000 ₽
— сборка и выкладка пропущены
→ автору изменения ушло письмо

Пайплайн остановился на тестах. На рабочем сервере осталась прежняя версия, покупатели ошибку не увидели.

  1. Пуш git push в main 0:02
  2. Линтер стиль и ошибки 0:38
  3. Типы tsc --noEmit 0:51
  4. Тесты 214 тестов 2:04
  5. Сборка npm run build 1:12
  6. Тестовый выкладка и проверка 0:46
  7. Рабочий выкладка 0:31
  8. Наблюдение ошибки, 10 минут 3:20
✓ выложено: v1.42 → рабочий сервер
✗ ошибок 4,1 % при пороге 1 %
↩ возвращена v1.41 за 28 секунд
→ команде ушло сообщение с журналом

После выкладки выросли ошибки — пайплайн сам вернул прошлую версию. Разбираться можно спокойно, сайт работает.

Ценность пайплайна — в двух плохих сценариях. Упавший тест останавливает выкладку раньше, чем ошибку кто-то увидит, а проскочивший плохой релиз откатывается сам, без ночного звонка. Линтер, типы и тесты идут одновременно — они друг от друга не зависят.

CI, непрерывная поставка и непрерывное развёртывание

Три ступени автоматизации. Каждая опирается на предыдущую.

ТерминЧто автоматизированоКто выкладываетПодходит
Непрерывная интеграция (CI) линтер, типы, тесты и сборка на каждое изменение человек, вручную любой проект, где больше одного разработчика
Непрерывная поставка плюс выкладка на тестовый сервер и готовый релиз для рабочего человек нажимает одну кнопку магазины, сервисы с графиком релизов
Непрерывное развёртывание всё, вплоть до рабочего сервера и отката никто: прошло проверки — вышло в работу команды с хорошими тестами и наблюдением

Быстрый пайплайн: 15 минут или 4

Одни и те же задачи, запущенные по-разному. Медленный пайплайн начинают обходить, поэтому скорость — часть надёжности.

Весь прогон14:40

  • зависимости каждый раз качаются заново
  • проверки ждут друг друга
  • все тесты в одном потоке
  • сборка с нуля

Весь прогон4:00

  • зависимости из кеша
  • линтер, типы и тесты — одновременно
  • тесты поделены на три части
  • сборка берёт неизменённое из кеша

Пример проекта на Node.js; минуты условные, соотношение — типичное.

Сравнение инструментов CI/CD

Бесплатные лимиты — с открытых страниц сервисов, октябрь 2026. Инструмент обычно выбирают по тому, где лежит код.

ИнструментГде работаетБесплатноСильная сторона
GitHub Actions облако GitHub или свой сервер открытые репозитории и свои раннеры; закрытые — 2 000 минут в месяц, дальше от $0,006 за минуту тысячи готовых действий, всё рядом с кодом
GitLab CI/CD облако GitLab или свой GitLab 400 минут в месяц; Premium — 10 000 за $29 на человека код, задачи и пайплайны в одном месте, можно поставить у себя
Bitbucket Pipelines облако Atlassian 50 минут в месяц; +1 000 минут за $10 команды, которые уже работают в Jira
CircleCI облако CircleCI или свой сервер 30 000 кредитов в месяц — около 3 000 минут, 5 человек быстрые сборки, параллельные задачи, деление тестов
Jenkins только свой сервер бесплатный, открытый код; платите за сервер и его обслуживание полный контроль, большие старые проекты
Vercel, Netlify, Cloudflare Pages собственные платформы бесплатные тарифы для небольших сайтов фронтенд выходит на каждый пуш, у каждой ветки своё превью

Четыре способа выкладки

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

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

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

Что автоматизировать в первую очередь

  1. 1. Выкладка одним действием

    Слияние в основную ветку выкладывает сайт. Никакой заливки руками и «забыл скопировать файл».

  2. 2. Проверки на каждый запрос на слияние

    Линтер, типы и сборка: они ловят большую часть глупых ошибок ещё до проверки коллегой.

  3. 3. Тесты на деньги и регистрацию

    Не стопроцентное покрытие, а корзина, оплата, регистрация и форма заявки.

  4. 4. Превью до выкладки

    Тестовый сервер или превью для каждой ветки: заказчик видит изменение раньше посетителей.

  5. 5. Проверка после выкладки и откат

    Сайт отвечает, ошибок не прибавилось — иначе прошлая версия возвращается сама.

  6. 6. Обновления зависимостей и проверка уязвимостей

    Раз в неделю — запросы на слияние с обновлениями, которые проходят те же проверки.

Пайплайн в коде: 2 файла

Пайплайн GitHub Actions для сайта на своём сервере и скрипт на сервере, который переключает релизы и откатывает.

Проверки, сборка и выкладка

Проверки идут на каждый запрос на слияние, выкладка — только из main и только если все проверки прошли. Ключи хранятся в секретах репозитория, а не в коде.

.github/workflows/deploy.yml
name: CI/CD

on:
  pull_request:
  push:
    branches: [main]

concurrency:                       # новый пуш отменяет прогон старого
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

jobs:
  checks:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v7
      - uses: actions/setup-node@v7
        with:
          node-version: 24
          cache: npm               # зависимости из кеша: минуты → секунды
      - run: npm ci
      - run: npm run lint
      - run: npm run typecheck
      - run: npm test
      - run: npm run build
      - uses: actions/upload-artifact@v7
        with:
          name: site
          path: dist/

  deploy:
    needs: checks                  # упала проверка — выкладки не будет
    if: github.ref == 'refs/heads/main'
    runs-on: ubuntu-latest
    environment: production        # секреты и, если нужно, ручное подтверждение
    steps:
      - uses: actions/download-artifact@v8
        with:
          name: site
          path: dist/
      - name: Загрузить и переключить
        env:
          SSH_KEY: ${{ secrets.DEPLOY_SSH_KEY }}
          KNOWN_HOSTS: ${{ secrets.DEPLOY_KNOWN_HOSTS }}
          HOST: ${{ vars.DEPLOY_HOST }}
        run: |
          mkdir -p ~/.ssh
          echo "$SSH_KEY" > ~/.ssh/id_ed25519 && chmod 600 ~/.ssh/id_ed25519
          echo "$KNOWN_HOSTS" > ~/.ssh/known_hosts
          RELEASE=$(date -u +%Y%m%d%H%M%S)
          rsync -az dist/ "deploy@$HOST:/srv/site/releases/$RELEASE/"
          ssh "deploy@$HOST" "/srv/site/switch.sh $RELEASE"

Переключить и откатить

Ссылка переключается одним действием, потом скрипт проверяет сайт. Не прошла проверка — возвращается прошлый релиз, а пайплайн становится красным.

switch.sh
#!/bin/sh
# Переключает сайт на новый релиз и возвращает старый, если проверка не прошла
set -eu
SITE=/srv/site
NEW="$SITE/releases/$1"
OLD=$(readlink -f "$SITE/current" || true)

switch_to() {
  ln -sfn "$1" "$SITE/current.next"
  mv -T "$SITE/current.next" "$SITE/current"   # разом: старая или новая
}

switch_to "$NEW"

if ! curl -fsS --max-time 10 https://example.ru/health > /dev/null; then
  [ -n "$OLD" ] && switch_to "$OLD"
  echo "Проверка не прошла, вернули $(basename "$OLD")" >&2
  exit 1
fi

# храним пять последних релизов для быстрого отката
ls -1dt "$SITE"/releases/*/ | tail -n +6 | xargs -r rm -rf

7 правил хорошего пайплайна

  1. 01

    Меньше десяти минут

    Кеш, параллельные задачи и деление тестов. Медленный пайплайн начинают обходить.

  2. 02

    Одна сборка на все среды

    На тестовый и рабочий сервер уходят одни и те же файлы, отличаются только настройки.

  3. 03

    Секреты — вне кода

    Ключи в секретах репозитория, с минимальными правами для своей задачи.

  4. 04

    Стоп на первой красной проверке

    Выкладка с упавшим тестом не уходит даже «один разок».

  5. 05

    Миграции, которые переживёт старая версия

    Сначала добавить колонку, выложить, потом убрать старую — тогда откат не ломает базу.

  6. 06

    Откат одним действием

    Хранить несколько прошлых релизов и проверить откат до того, как он понадобится.

  7. 07

    Сообщение — только когда важно

    Красный пайплайн и откат приходят человеку сразу, зелёные прогоны остаются в журнале.

Частые ошибки в CI/CD

  1. Нестабильные тесты, которые все перезапускают

    Красный прогон перестаёт что-то значить, и вместе с ним проходит настоящая ошибка.

  2. Отдельная сборка для рабочего сервера

    На тестовом проверили одни файлы, на рабочий ушли другие.

  3. Ключи в репозитории

    Они остаются в истории даже после удаления файла.

  4. Правки руками на сервере

    Следующая выкладка их затирает, и никто не помнит, почему ошибка вернулась.

  5. Миграция без пути назад

    Код можно откатить, а удалённую колонку — нет.

  6. Уведомления о каждом зелёном прогоне

    Через неделю их никто не читает, включая красные.

Вопросы о CI/CD

Нужен ли CI/CD небольшому сайту?

Да, в самом простом виде: выкладка из основной ветки одним действием и откат. Настраивается за несколько часов и навсегда убирает ручную заливку.

Чем CI отличается от CD?

CI проверяет и собирает каждое изменение. CD доставляет результат на серверы: по кнопке при непрерывной поставке или само при непрерывном развёртывании.

Какой инструмент выбрать?

Встроенный в ваш хостинг кода: GitHub Actions для GitHub, GitLab CI/CD для GitLab. Отдельный инструмент оправдан только при особых требованиях.

Обязателен ли Docker?

Нет. Сайт можно выкладывать папкой файлов с переключением ссылки. Docker помогает, когда сервисов или серверов несколько.

Как выкладывать без простоя?

Готовить новую версию рядом со старой и переключать трафик одним действием: ссылкой на одном сервере, балансировщиком — на нескольких.

Сколько стоит CI/CD?

Большинству небольших проектов хватает бесплатных лимитов: 2 000 минут в месяц на GitHub, 400 на GitLab. Основные затраты — настройка и тесты.

Форма

Выкладка
без страха

Настраиваю пайплайны для сайтов и сервисов: проверки каждого изменения, выкладка в один шаг и откат за секунды. Расскажите о проекте — отвечу в течение рабочего дня.

Или пишите на [email protected]