Перейти к основному содержимому
Вернуться в категорию

Автоматическое развёртывание с GitHub Actions: настройка CI/CD Pipeline

Создание CI/CD-пайплайнов с GitHub Actions: сборка и публикация Docker, развёртывание на сервере по SSH, автоматизация тестов, управление секретами и оптимизация рабочих процессов.

Время чтения: 18 мин DevOps и автоматизация
github-actionsci/cddeploymentdevopsавтоматизацияdockerssh

Содержание

Автоматическое развёртывание с GitHub Actions: настройка CI/CD Pipeline

GitHub Actions — мощная CI/CD-платформа, которая автоматически тестирует, собирает и развёртывает изменения кода на сервере. В этом руководстве мы создадим готовый к production пайплайн с нуля.

Что такое GitHub Actions?

GitHub Actions — платформа автоматизации, интегрированная в репозитории GitHub:

  • Реагирует на события: push, PR, расписание
  • Запускает параллельные и последовательные рабочие процессы
  • 2 000 минут/месяц бесплатно (неограниченно для публичных репозиториев)
  • Расширяется тысячами готовых actions

Файлы рабочих процессов GitHub Actions хранятся в формате YAML в директории .github/workflows/.

Базовая структура рабочего процесса

hljs yaml
# .github/workflows/deploy.yml
name: CI/CD Pipeline

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

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Настройка Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '20'
      - name: Установка зависимостей
        run: npm ci
      - name: Запуск тестов
        run: npm test

  deploy:
    needs: test
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main'
    steps:
      - uses: actions/checkout@v4
      - name: Развернуть
        run: echo "Шаги развёртывания здесь"

Структура on / jobs / steps

Триггеры (on)

hljs yaml
on:
  # Push в ветку
  push:
    branches: [main, develop]
    paths:
      - 'src/**'
      - 'package.json'

  # Pull request
  pull_request:
    branches: [main]
    types: [opened, synchronize, reopened]

  # Запуск по расписанию (cron)
  schedule:
    - cron: '0 2 * * *'  # Каждую ночь в 02:00

  # Ручной запуск
  workflow_dispatch:
    inputs:
      environment:
        description: 'Среда развёртывания'
        required: true
        default: 'staging'
        type: choice
        options: [staging, production]

  # При завершении другого рабочего процесса
  workflow_run:
    workflows: ["Build"]
    types: [completed]

Конфигурация задания

hljs yaml
jobs:
  build:
    runs-on: ubuntu-latest
    env:
      NODE_ENV: test
    timeout-minutes: 30
    strategy:
      matrix:
        node-version: [18, 20, 22]
        os: [ubuntu-latest, windows-latest]
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node-version }}

Сборка и публикация Docker

Публикация в Docker Hub

hljs yaml
jobs:
  docker:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Метаданные Docker
        id: meta
        uses: docker/metadata-action@v5
        with:
          images: username/myapp
          tags: |
            type=ref,event=branch
            type=semver,pattern={{version}}
            type=sha,prefix=sha-

      - name: Настройка Docker Buildx
        uses: docker/setup-buildx-action@v3

      - name: Вход в Docker Hub
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}

      - name: Сборка и публикация
        uses: docker/build-push-action@v5
        with:
          context: .
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          labels: ${{ steps.meta.outputs.labels }}
          cache-from: type=gha
          cache-to: type=gha,mode=max

GitHub Container Registry (GHCR)

hljs yaml
      - name: Вход в GHCR
        uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Сборка и публикация (GHCR)
        uses: docker/build-push-action@v5
        with:
          context: .
          push: true
          tags: ghcr.io/${{ github.repository }}:latest

Развёртывание на сервере по SSH

Использование appleboy/ssh-action

hljs yaml
  deploy:
    needs: docker
    runs-on: ubuntu-latest
    environment: production
    steps:
      - name: Развёртывание по SSH
        uses: appleboy/ssh-action@v1.0.3
        with:
          host: ${{ secrets.SERVER_HOST }}
          username: ${{ secrets.SERVER_USER }}
          key: ${{ secrets.SSH_PRIVATE_KEY }}
          port: ${{ secrets.SERVER_PORT }}
          script: |
            cd /root/myapp
            git pull origin main
            docker compose pull
            docker compose up -d --remove-orphans
            docker image prune -f
            echo "Развёртывание завершено: $(date)"

Развёртывание с Docker Compose

hljs yaml
      - name: Развёртывание Docker Compose
        uses: appleboy/ssh-action@v1.0.3
        with:
          host: ${{ secrets.SERVER_HOST }}
          username: ${{ secrets.SERVER_USER }}
          key: ${{ secrets.SSH_PRIVATE_KEY }}
          script: |
            # Получить новый образ
            docker pull ghcr.io/${{ github.repository }}:latest

            # Развёртывание без простоя
            docker compose -f /root/app/docker-compose.yml up -d \
              --no-deps \
              --build \
              --remove-orphans

            # Очистить старые образы
            docker image prune -af --filter "until=24h"

            # Проверка работоспособности
            sleep 10
            curl -f http://localhost:3000/health || exit 1

Управление секретами

GitHub Secrets надёжно хранит конфиденциальную информацию:

hljs yaml
steps:
  - name: Конфигурация приложения
    env:
      DATABASE_URL: ${{ secrets.DATABASE_URL }}
      JWT_SECRET: ${{ secrets.JWT_SECRET }}
      API_KEY: ${{ secrets.API_KEY }}
    run: |
      echo "Конфигурация загружена"
      # Секреты никогда не выводятся в логи, автоматически маскируются

Необходимые секреты:

  • SERVER_HOST: IP-адрес сервера
  • SERVER_USER: имя пользователя SSH
  • SSH_PRIVATE_KEY: приватный ключ SSH
  • DOCKERHUB_USERNAME: имя пользователя Docker Hub
  • DOCKERHUB_TOKEN: токен доступа Docker Hub

Использование кэша

hljs yaml
      - name: Кэширование зависимостей Node.js
        uses: actions/cache@v4
        with:
          path: ~/.npm
          key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
          restore-keys: |
            ${{ runner.os }}-node-

      - name: npm ci  кэшем)
        run: npm ci

      # Кэш слоёв Docker
      - name: Сборка и публикация
        uses: docker/build-push-action@v5
        with:
          cache-from: type=gha
          cache-to: type=gha,mode=max

Matrix Builds

hljs yaml
jobs:
  test:
    strategy:
      fail-fast: false
      matrix:
        node: [18, 20]
        os: [ubuntu-latest, macos-latest]
        include:
          - node: 20
            os: ubuntu-latest
            coverage: true
        exclude:
          - node: 18
            os: macos-latest
    runs-on: ${{ matrix.os }}
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node }}
      - run: npm ci
      - run: npm test
      - name: Отчёт о покрытии
        if: matrix.coverage
        run: npm run coverage

Правила защиты окружений

hljs yaml
jobs:
  deploy-production:
    runs-on: ubuntu-latest
    environment:
      name: production
      url: https://example.com
    steps:
      - name: Развёртывание в production
        run: echo "Развёртывание в production"

В GitHub в разделе Settings > Environments > production:

  • Required reviewers (требуется одобрение)
  • Wait timer (время ожидания)
  • Deployment branches (только main)

Полный пример CI/CD Pipeline

hljs yaml
name: Full CI/CD

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

env:
  REGISTRY: ghcr.io
  IMAGE_NAME: ${{ github.repository }}

jobs:
  test:
    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 lint
      - run: npm test -- --coverage
      - name: Загрузить покрытие
        uses: codecov/codecov-action@v4

  build:
    needs: test
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write
    steps:
      - uses: actions/checkout@v4
      - uses: docker/setup-buildx-action@v3
      - uses: docker/login-action@v3
        with:
          registry: ${{ env.REGISTRY }}
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
      - id: meta
        uses: docker/metadata-action@v5
        with:
          images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
      - uses: docker/build-push-action@v5
        with:
          push: ${{ github.event_name != 'pull_request' }}
          tags: ${{ steps.meta.outputs.tags }}
          cache-from: type=gha
          cache-to: type=gha,mode=max

  deploy:
    needs: build
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main'
    environment:
      name: production
      url: https://example.com
    steps:
      - uses: appleboy/ssh-action@v1.0.3
        with:
          host: ${{ secrets.SERVER_HOST }}
          username: ${{ secrets.SERVER_USER }}
          key: ${{ secrets.SSH_PRIVATE_KEY }}
          script: |
            docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:main
            docker compose -f /root/app/docker-compose.yml up -d
            docker image prune -f

Заключение

Настроив полностью автоматизированный CI/CD-пайплайн с GitHub Actions, вы сможете повысить качество кода, сократить ошибки при развёртывании и ускорить процесс разработки. Управление секретами, оптимизация кэша и правила защиты окружений обеспечат вам пайплайн production-уровня.