Содержание

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

Разберём, из чего состоит конвейер, покажем рабочий пример и частые ошибки.

Что такое CI/CD и зачем он небольшой команде?

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

Что даёт конвейер:

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

Из каких этапов состоит конвейер?

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

Этап Что происходит Когда запускается
Проверки Линтер, форматирование, типы, тесты На каждый запрос на слияние
Безопасность Уязвимости зависимостей, поиск секретов На каждый запрос на слияние
Сборка Docker-образ или артефакт с версией После слияния в основную ветку
Выкладка на стенд Автоматически на тестовое окружение После сборки
Выкладка в продакшен По кнопке, тегу или автоматически после проверки По решению команды
Проверка после выкладки Смоук-тест главного сценария, мониторинг Сразу после выкладки

Ноутбук рядом с кружкой на деревянном столе Фото: Unsplash

Как выглядит конвейер на GitHub Actions?

Конвейер на GitHub Actions описывается YAML-файлами в каталоге .github/workflows репозитория. Ниже — пример для PHP-проекта: проверки на каждый запрос на слияние и выкладка после слияния в основную ветку.

name: CI
on:
  pull_request:
  push:
    branches: [main]

jobs:
  test:
    runs-on: ubuntu-latest
    services:
      postgres:
        image: postgres:18
        env: { POSTGRES_PASSWORD: secret }
        ports: ['5432:5432']
    steps:
      - uses: actions/checkout@v4
      - uses: shivammathur/setup-php@v2
        with: { php-version: '8.4' }
      - run: composer install --no-interaction --prefer-dist
      - run: vendor/bin/pint --test
      - run: composer audit
      - run: php artisan test

  deploy:
    needs: test
    if: github.ref == 'refs/heads/main'
    runs-on: ubuntu-latest
    environment: staging
    steps:
      - uses: actions/checkout@v4
      - run: ./deploy.sh staging
        env:
          DEPLOY_KEY: ${{ secrets.STAGING_DEPLOY_KEY }}

Что здесь важно

  1. Тесты работают с настоящей базой данных в сервисном контейнере.
  2. Выкладка запускается только после успешных проверок и только из основной ветки.
  3. Секреты хранятся в настройках репозитория и окружений, а не в коде.
  4. Окружения GitHub позволяют требовать подтверждения перед выкладкой в продакшен.

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

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

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

Что помогает:

  • кешировать зависимости Composer и npm между запусками;
  • запускать линтер, тесты и проверку безопасности параллельно;
  • медленные сквозные тесты запускать на основной ветке, а не на каждый коммит;
  • отменять устаревшие запуски, когда в ветку пришёл новый коммит;
  • собирать Docker-образы с кешем слоёв.

Какие ошибки встречаются чаще всего?

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

Типичные ошибки:

  • нестабильные тесты, которые «иногда падают», — их перезапускают и перестают замечать настоящие ошибки;
  • ключи и пароли в репозитории вместо секретов CI;
  • нет отката: исправить сломанный релиз можно только новым релизом;
  • миграции базы, несовместимые с предыдущей версией кода, — откат становится невозможным;
  • проверки можно пропустить, потому что основная ветка не защищена.

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

Коротко

  • CI проверяет каждое изменение, CD автоматически доставляет проверенный код на серверы.
  • Конвейер: проверки и безопасность на запрос на слияние, сборка и выкладка на стенд после слияния, продакшен по решению.
  • На GitHub Actions всё описывается YAML-файлами, секреты — в настройках репозитория.
  • Держите конвейер быстрым: кеш, параллельные шаги, медленные тесты отдельно.
  • Чините нестабильные тесты сразу, храните секреты в CI и продумайте откат.

Частые вопросы

  • Сколько стоит GitHub Actions?

    Для публичных репозиториев стандартные раннеры бесплатны, для приватных есть бесплатный лимит минут в месяц, а сверх него — оплата по тарифу. Актуальные условия лучше уточнить на странице тарифов GitHub.

  • Нужно ли выкладывать в продакшен автоматически?

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

  • Чем GitHub Actions отличается от GitLab CI?

    Принципы одинаковые: YAML-описание этапов, раннеры, секреты и окружения. Выбор обычно определяется тем, где хранится код; если репозиторий в GitLab, удобнее GitLab CI.