Антон Ларичев

Введение
CI/CD расшифровывается как Continuous Integration и Continuous Delivery/Deployment — непрерывная интеграция и непрерывная доставка. Это практика автоматического запуска тестов, сборки и деплоя приложения при каждом изменении кода. Если вы до сих пор деплоите вручную или запускаете тесты только перед релизом — эта статья для вас.
GitHub Actions — встроенный инструмент автоматизации GitHub. Он бесплатен для публичных репозиториев и предоставляет щедрый лимит минут для приватных. Никакие сторонние сервисы не нужны: всё настраивается прямо в репозитории через YAML-файлы.
В этой статье мы разберём основы GitHub Actions, напишем первый pipeline и настроим полноценный CI/CD для Node.js-приложения.
Как устроены GitHub Actions
Рабочий процесс (workflow) — это автоматический сценарий, который запускается при определённых событиях: пуш в ветку, создание pull request, расписание по cron и другие.
Ключевые понятия:
- Workflow — файл
.ymlв директории.github/workflows/ - Job — набор шагов, выполняющихся на одном runner
- Step — отдельная команда или переиспользуемый action
- Runner — виртуальная машина, на которой выполняется job
- Action — готовый блок логики из маркетплейса GitHub
GitHub автоматически обнаруживает все файлы в .github/workflows/ и регистрирует их как рабочие процессы.
Первый workflow: запуск тестов
Создайте файл .github/workflows/ci.yml:
# Название отображается в интерфейсе GitHub во вкладке Actions
name: CI
# Триггеры: запускаем при пуше в любую ветку и при создании PR в main
on:
push:
branches: ['**']
pull_request:
branches: [main]
jobs:
test:
# Используем последнюю версию Ubuntu в качестве runner
runs-on: ubuntu-latest
steps:
# Клонируем репозиторий на runner
- name: Checkout code
uses: actions/checkout@v4
# Устанавливаем нужную версию Node.js с кэшированием npm
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
# Устанавливаем зависимости строго по lock-файлу
- name: Install dependencies
run: npm ci
# Запускаем тесты
- name: Run tests
run: npm test
После пуша этого файла GitHub автоматически запустит pipeline. Результат можно увидеть во вкладке Actions репозитория.
Матрица версий
Если приложение должно работать на нескольких версиях Node.js, используйте стратегию матрицы — GitHub создаст параллельные job для каждой комбинации:
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
# Запускаем тесты для каждой указанной версии Node.js
node-version: [18, 20, 22]
steps:
- uses: actions/checkout@v4
- name: Setup Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
# Подставляем текущую версию из матрицы
node-version: ${{ matrix.node-version }}
cache: 'npm'
- run: npm ci
- run: npm test
Секреты и переменные окружения
Никогда не храните токены, пароли и ключи прямо в YAML-файле. Для этого в GitHub есть Secrets.
Добавьте секрет: Settings → Secrets and variables → Actions → New repository secret.
Используйте его в workflow через синтаксис ${{ secrets.ИМЯ_СЕКРЕТА }}:
steps:
- name: Deploy to server
env:
# Передаём секрет через переменную окружения
DEPLOY_KEY: ${{ secrets.DEPLOY_SSH_KEY }}
SERVER_HOST: ${{ secrets.SERVER_HOST }}
run: |
# Настраиваем SSH-доступ к серверу
mkdir -p ~/.ssh
echo "$DEPLOY_KEY" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
ssh -o StrictHostKeyChecking=no user@$SERVER_HOST 'cd /app && git pull && npm ci && pm2 restart app'
Полный CI/CD pipeline
Соберём всё вместе: тесты в CI, деплой только после их успешного прохождения.
name: CI/CD Pipeline
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
# Первый job: проверка кода
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- run: npm ci
# Проверяем стиль кода линтером
- name: Lint
run: npm run lint
# Запускаем тесты с отчётом о покрытии
- name: Test
run: npm run test:coverage
# Второй job: деплой на сервер
deploy:
runs-on: ubuntu-latest
# Запускаем только после успешного прохождения job test
needs: test
# Деплоим только при прямом пуше в main, но не при PR
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
# Устанавливаем только production-зависимости
- run: npm ci --omit=dev
- name: Build
run: npm run build
- name: Deploy
env:
DEPLOY_KEY: ${{ secrets.DEPLOY_SSH_KEY }}
SERVER_HOST: ${{ secrets.SERVER_HOST }}
run: |
mkdir -p ~/.ssh
echo "$DEPLOY_KEY" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
# Синхронизируем собранные файлы на сервер
rsync -avz --delete ./dist/ user@$SERVER_HOST:/app/dist/
# Перезапускаем приложение через pm2
ssh user@$SERVER_HOST 'pm2 restart app'
Частые ошибки
Хранение секретов в коде. Токены, закоммиченные в YAML или .env-файлы, остаются в истории git даже после удаления. Всегда используйте Secrets в настройках репозитория.
Деплой без зависимости от тестов. Если запустить деплой параллельно с тестами или вообще без них, сломанный код попадёт на сервер. Используйте needs: test, чтобы обязательно дождаться результата проверок.
npm install вместо npm ci. В CI всегда используйте npm ci — она устанавливает зависимости строго по package-lock.json и очищает node_modules перед установкой. npm install может обновить lock-файл и создать расхождение между окружениями.
Отсутствие кэширования. Без кэша каждый запуск pipeline скачивает все зависимости заново. На больших проектах это добавляет 2–5 минут к каждому запуску. Параметр cache: 'npm' в setup-node решает проблему.
Триггер только для main. Если pipeline запускается исключительно для главной ветки, разработчики узнают о проблемах только после merge. Настройте CI для всех веток: branches: ['**'].
Заключение
GitHub Actions — доступный инструмент для построения CI/CD прямо внутри GitHub без дополнительной инфраструктуры. Мы разобрали основные концепции: workflow, jobs, steps, secrets и кэширование зависимостей. Написали pipeline, который запускает тесты для нескольких версий Node.js и автоматически деплоит приложение после успешной проверки.
Следующий шаг — изучите маркетплейс Actions: там тысячи готовых action для деплоя в AWS, Kubernetes, отправки уведомлений в Slack и многого другого. Большинство задач уже решены — не нужно писать скрипты с нуля.
CI/CD — это не про сложные инструменты, это про культуру качества. Автоматизируйте рутину и сосредоточьтесь на коде.






Комментарии
0