Вы пушите код, ждёте 5 минут, заходите на сервер по SSH, делаете git pull, перезапускаете pm2 и молитесь, чтобы ничего не сломалось. Знакомо? Так деплоят большинство стартапов на ранней стадии. И это работает — ровно до момента, когда один неудачный деплой ломает продакшн в пятницу вечером.

CI/CD (Continuous Integration / Continuous Delivery) — это система, которая автоматически проверяет, собирает и разворачивает ваш код. Звучит сложно? На самом деле, базовый пайплайн настраивается за 2-3 часа и навсегда меняет подход к разработке. В этой статье мы пройдём путь от нуля до полноценного CI/CD для небольшой команды.

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

Continuous Integration (CI) — автоматическая проверка кода при каждом push: линтинг, тесты, type checking, сборка. Если что-то сломано, вы узнаёте за минуты, а не через неделю.

Continuous Delivery (CD) — автоматический деплой прошедшего проверку кода в нужное окружение. Push в main → деплой на staging. Создал тег → деплой в production.

Зачем это команде из 2-5 человек?

CI/CD — это не роскошь для больших компаний. Это гигиена разработки. Без неё вы тратите 20-30% времени на ручные процессы, которые машина делает за секунды.

Настройка GitHub Actions: пошаговый гайд

GitHub Actions — наш выбор для стартапов. Встроен в GitHub, 2,000 бесплатных минут в месяц, YAML-конфигурация, огромный маркетплейс готовых действий.

Базовый CI-пайплайн

Создайте файл .github/workflows/ci.yml в корне проекта:

name: CI

on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main]

jobs:
  lint-and-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: Type Check
        run: npm run type-check

      - name: Unit Tests
        run: npm run test

      - name: Build
        run: npm run build

Этот пайплайн запускается при каждом push в main/develop и при каждом Pull Request. Он выполняет четыре проверки: линтинг, проверка типов, юнит-тесты и сборка. Если хотя бы одна проверка падает — PR нельзя смержить (настраивается в Branch Protection Rules).

CD: автоматический деплой

Добавим деплой на staging при мерже в main и на production при создании тега:

name: Deploy

on:
  push:
    branches: [main]
    tags: ['v*']

jobs:
  deploy-staging:
    if: github.ref == 'refs/heads/main'
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: 'npm'
      - run: npm ci
      - run: npm run build
      - name: Deploy to Staging
        run: |
          # Ваша команда деплоя
          rsync -avz ./dist/ user@staging:/var/www/app/
        env:
          SSH_KEY: ${{ secrets.STAGING_SSH_KEY }}

  deploy-production:
    if: startsWith(github.ref, 'refs/tags/v')
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: 'npm'
      - run: npm ci
      - run: npm run build
      - name: Deploy to Production
        run: |
          rsync -avz ./dist/ user@prod:/var/www/app/
        env:
          SSH_KEY: ${{ secrets.PROD_SSH_KEY }}

5 стадий пайплайна

Полноценный CI/CD-пайплайн состоит из пяти стадий. Каждая следующая запускается только при успехе предыдущей:

1. Lint & Format

Проверка стиля кода: ESLint, Prettier, stylelint. Ловит баги на этапе написания кода (неиспользуемые переменные, missing dependencies в useEffect, и т.д.). Занимает 15-30 секунд.

2. Type Check

Для TypeScript-проектов — tsc --noEmit. Гарантирует, что все типы корректны, нет implicit any, все API-контракты соблюдены. Занимает 20-60 секунд.

3. Test

Unit-тесты (Vitest, Jest) для бизнес-логики, integration-тесты для API-эндпоинтов. На ранней стадии достаточно 20-50 тестов на критические пути. Занимает 30-120 секунд.

4. Build

Сборка приложения. Проверяет, что проект компилируется без ошибок, нет пропущенных импортов, все ассеты на месте. Занимает 30-120 секунд.

5. Deploy

Разворачивание на целевое окружение. Staging — автоматически. Production — по тегу или кнопке. Занимает 30-120 секунд.

Общее время пайплайна: 2-5 минут. Если больше — оптимизируйте кеширование зависимостей и параллельность джобов.

Тестирование: что и сколько тестировать

Для стартапа тестовая пирамида выглядит так:

Минимальный набор для MVP:

  1. 10-20 unit-тестов на ключевую бизнес-логику
  2. 5-10 integration-тестов на API
  3. 3 E2E-теста: регистрация, основное действие, оплата

Используйте Vitest для unit/integration-тестов (в 5-10x быстрее Jest) и Playwright для E2E.

Docker: контейнеризация для деплоя

Docker решает проблему «у меня на машине работает». Ваш Dockerfile — это рецепт для точного воспроизведения окружения.

# Multi-stage build для минимального образа
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

FROM node:20-alpine AS runner
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
COPY package.json ./

ENV NODE_ENV=production
EXPOSE 3000
CMD ["node", "dist/server.js"]

Multi-stage build — сначала собираем (со всеми dev-зависимостями), потом копируем только результат сборки в чистый образ. Итоговый образ весит 100-200 MB вместо 1+ GB.

Docker Compose для локальной разработки

version: '3.8'
services:
  app:
    build: .
    ports:
      - "3000:3000"
    environment:
      - DATABASE_URL=postgres://user:pass@db:5432/app
    depends_on:
      - db
      - redis

  db:
    image: postgres:16-alpine
    environment:
      POSTGRES_DB: app
      POSTGRES_USER: user
      POSTGRES_PASSWORD: pass
    volumes:
      - pgdata:/var/lib/postgresql/data

  redis:
    image: redis:7-alpine

volumes:
  pgdata:

Один docker compose up поднимает всё окружение: приложение, базу данных, Redis. Новый разработчик продуктивен через 5 минут.

Окружения: dev, staging, production

Минимальная конфигурация для стартапа — два окружения:

Правила:

  1. Никогда не деплойте в production напрямую — только через CI/CD
  2. Staging и production используют разные базы данных, разные API-ключи, разные переменные окружения
  3. Все переменные хранятся в GitHub Secrets, а не в коде
  4. Production-деплой требует ручного подтверждения (Environment Protection Rules)

Мониторинг и алерты

CI/CD без мониторинга — это автоматический способ сломать продакшн незаметно. Вот минимальный набор инструментов:

Задача Инструмент Стоимость
Ошибки в коде Sentry Бесплатно (5K событий/мес)
Uptime мониторинг UptimeRobot / BetterStack Бесплатно (50 мониторов)
Логи Axiom / Loki Бесплатно (до 500MB/день)
Метрики приложения Grafana Cloud Бесплатно (10K серий)
Алерты PagerDuty / Telegram-бот Бесплатно / $0

Минимум: Sentry для ошибок + UptimeRobot для uptime. Sentry интегрируется с GitHub Actions — при деплое автоматически создаёт release и привязывает ошибки к конкретным коммитам.

Rollback-стратегии

Что делать, когда деплой сломал продакшн:

Вариант 1: Git Revert (самый простой)

git revert HEAD
git push origin main
# CI/CD автоматически задеплоит откат

Вариант 2: Docker-образ (быстрый)

Откатитесь к предыдущему Docker-образу. Если используете теги (v1.0.1, v1.0.0), просто запустите предыдущий образ.

Вариант 3: Blue-Green деплой

Две одинаковые среды: blue (текущая) и green (новая). Деплоите в green, проверяете, переключаете трафик. Если что-то не так — переключаете обратно за секунды.

Золотое правило: всегда имейте план отката ДО деплоя. Не придумывайте его во время инцидента в 3 часа ночи.

Чеклист CI/CD для стартапа

Мы настраиваем CI/CD для каждого проекта в BossMode — это часть нашего стандартного процесса разработки. Подробнее о том, как мы работаем: веб-разработка и наш стек технологий.