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

Почему CI/CD важен и что даёт в работе команды

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

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

Кратко о ключевых понятиях

CI — это автоматическое выполнение сборки и тестов при каждом изменении в репозитории. CD обычно подразумевает автоматический деплой в staging или production и может быть реализован как автоматическая подача релиза или как полуавтоматический процесс с ручным подтверждением.

Важные элементы: триггеры, шаги (jobs), окружения, секреты и раннеры. Понимание этих концепций позволит читать конфигурацию любого конвейера и быстро адаптировать её под задачу.

GitLab CI/CD: шаги от файла до рабочего пайплайна

В GitLab всё начинается с файла .gitlab-ci.yml, который лежит в корне репозитория. В нём описываются стадии, задания и правила запуска; GitLab Runner выполняет эти задания в контейнерах или на выделенных машинах.

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

Файл .gitlab-ci.yml — базовая структура

Типичный файл содержит блоки stages и jobs. В stages определяются последовательные этапы, например build, test, deploy, а в jobs указывается, что и как выполнять на каждом шаге.

Примерный набор полей: image, script, artifacts, only/except или rules. Правила rules дают гибкий контроль над тем, когда именно запускать задание.

Раннеры и их типы

GitLab Runner может работать в Docker, shell, Kubernetes и других режимах. Для большинства случаев достаточно Docker-раннера: он изолирован и прост в настройке.

Если у вас приватные зависимости или специфическое железо, имеет смысл выделить собственный раннер. Управление тегами раннеров позволит направлять задания на нужные машины.

Пример простого pipeline в GitLab

Ниже небольшой пример, который собирает приложение, запускает тесты и сохраняет артефакты. Такой шаблон подходит для большинства проектов на Node.js или Python.

stages:
  - build
  - test
  - deploy

build:
  stage: build
  image: node:16
  script:
    - npm ci
    - npm run build
  artifacts:
    paths:
      - dist/

test:
  stage: test
  image: node:16
  script:
    - npm ci
    - npm test

deploy:
  stage: deploy
  image: alpine:latest
  script:
    - echo "Deploy step here"
  when: manual

GitHub Actions: как начать и что учитывать

GitHub Actions опирается на workflow-файлы в каталоге .github/workflows. Каждый workflow — это набор jobs, объединённых триггером, например push, pull_request или cron.

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

Структура workflow и триггеры

Файл workflow начинается с name и on — триггеров запуска. Дальше идут jobs, где описываются окружение, шаги и зависимости между заданиями.

Можно задавать matrix для параллельного тестирования на разных версиях языка или ОС; это удобно для кроссплатформенных проектов.

Secrets и переменные окружения

В GitHub секреты хранятся в настройках репозитория или организации и передаются в workflow через secrets.NAME. Никогда не записывайте чувствительные данные прямо в файлы в репозитории.

Для безопасного управления доступами используйте короткоживущие токены и минимальные права. При необходимости разграничьте секреты для production и staging.

Пример workflow для Node.js

Приведённый ниже пример выполняет установку зависимостей и тесты при пуше в ветку main. Он демонстрирует стандартную структуру и использование actions/setup-node.

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

jobs:
  build-and-test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-node@v3
        with:
          node-version: 16
      - run: npm ci
      - run: npm test

Короткое сравнение GitLab CI и GitHub Actions

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

Параметр GitLab CI/CD GitHub Actions
Размещение конфигурации .gitlab-ci.yml .github/workflows/*.yml
Раннеры GitLab Runner (локальные и shared) self-hosted и hosted runners
Маркет действий Less centralized GitHub Marketplace с большим набором actions

Практические советы и распространённые ошибки

Не храните секреты в репозитории и не передавайте токены как обычные переменные в логах. Всегда помечайте секреты и используйте masked-логи, если платформа это поддерживает.

Другой частый просчёт — запуск тяжёлых задач на shared-раннерах без ограничений. Настраивайте таймауты и кэширование зависимостей, чтобы не тратить лишние ресурсы и сократить время выполнения.

Мой опыт: что сработало в реальных проектах

В одном из проектов я заменил ручные сборки на GitLab pipeline и сократил время релиза с часов до 20 минут. Ключевым оказалось кэширование зависимостей и разделение на параллельные тесты.

В другом случае GitHub Actions пригодился для быстрого развёртывания demo-версий при открытии pull request; мы использовали динамические среды и удаляли их по закрытию PR. Это значительно облегчило проверку фич командой и заказчиком.

Когда выбирать GitLab, а когда GitHub Actions

Если ваш проект уже в GitLab и вы используете встроенные возможности управления релизами и деплоем, имеет смысл остаться в рамках одной платформы. Это упрощает настройки и контроль доступа.

Если же вы в GitHub и цените богатую экосистему actions и marketplace, логично использовать GitHub Actions. Также нередки гибридные сценарии: храните репозиторий в GitHub, а для специализированных билдов используете self-hosted раннеры или внешние инструменты.

Быстрый чеклист для внедрения CI/CD

Вот минимальный набор шагов, который поможет запустить рабочий конвейер: настройте файл конфигурации, добавьте раннера или выберите hosted runner, подключите секреты, автоматизируйте тесты, настройте артефакты и окружения. Выполняйте эти пункты поэтапно и проверяйте результат на каждой итерации.

  • Создать конфигурационный файл в корне репозитория.
  • Определить stages: build, test, deploy.
  • Настроить раннер/runner и проверить подключение.
  • Добавить секреты через интерфейс платформы.
  • Включить кэширование и ограничения по времени.
  • Мониторить логи и метрики выполнения.

Несколько практических замечаний перед запуском

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

Документируйте pipeline в репозитории — файл с описанием этапов и контактами ответственных ускорит устранение ошибок при их появлении. Даже короткая инструкция спасёт время другим членам команды.

Настройка CI/CD — это не разовая задача, а процесс, который развивается вместе с проектом. Разбейте автоматизацию на понятные этапы и делайте изменения маленькими, чтобы легко откатывать и анализировать поведение системы. С таким подходом вы получите предсказуемые релизы и снизите стресс при деплое новых версий.