GitHub Actions для CI/CD: От теории к практике

GitHub Actions изменил подход к автоматизации процессов разработки, предоставляя мощный инструмент для создания CI/CD pipeline прямо в репозитории. В этом руководстве мы разберем как настроить полноценный пайплайн с автоматическим тестированием и развертыванием, оптимизировать workflow и использовать продвинутые фичи.

Что такое GitHub Actions?

GitHub Actions — это платформа для автоматизации workflows прямо в вашем GitHub репозитории. Она позволяет создавать, тестировать и развертывать код непосредственно из GitHub.

Основные компоненты:

Базовый CI Pipeline для Node.js приложения

Создайте файл .github/workflows/ci.yml:

name: CI Pipeline

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

jobs:
  test:
    runs-on: ubuntu-latest
    
    strategy:
      matrix:
        node-version: [16.x, 18.x, 20.x]
    
    steps:
    - name: Checkout code
      uses: actions/checkout@v4
    
    - name: Setup Node.js
      uses: actions/setup-node@v4
      with:
        node-version: ${{ matrix.node-version }}
        cache: 'npm'
    
    - name: Install dependencies
      run: npm ci
    
    - name: Run tests
      run: npm test
    
    - name: Run linting
      run: npm run lint
    
    - name: Build application
      run: npm run build

Оптимизация Workflow

Кеширование зависимостей

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

- name: Cache node modules
  uses: actions/cache@v4
  with:
    path: ~/.npm
    key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
    restore-keys: |
      ${{ runner.os }}-node-

Matrix Builds для мульти-платформенного тестирования

Тестируйте ваше приложение на разных ОС и версиях языков:

jobs:
  test:
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        os: [ubuntu-latest, windows-latest, macos-latest]
        node-version: [16.x, 18.x, 20.x]
        include:
          - os: ubuntu-latest
            node-version: 18.x
            coverage: true

Продвинутый CI/CD Pipeline

Полноценный пайплайн с тестированием, сборкой и деплоем:

name: Full CI/CD

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

env:
  NODE_VERSION: '18.x'
  DOCKER_IMAGE: ghcr.io/${{ github.repository }}

jobs:
  quality:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
    
    - name: Setup Node.js
      uses: actions/setup-node@v4
      with:
        node-version: ${{ env.NODE_VERSION }}
        cache: 'npm'
    
    - name: Install dependencies
      run: npm ci
    
    - name: Run security audit
      run: npm audit
    
    - name: Run linting
      run: npm run lint
    
    - name: Run tests with coverage
      run: npm run test:coverage
    
    - name: Upload coverage reports
      uses: codecov/codecov-action@v3

  build:
    runs-on: ubuntu-latest
    needs: quality
    if: github.event_name == 'push' && github.ref == 'refs/heads/main'
    
    steps:
    - uses: actions/checkout@v4
    
    - name: Build Docker image
      run: |
        docker build -t ${{ env.DOCKER_IMAGE }}:${{ github.sha }} .
    
    - name: Log into GitHub Container Registry
      uses: docker/login-action@v3
      with:
        registry: ghcr.io
        username: ${{ github.actor }}
        password: ${{ secrets.GITHUB_TOKEN }}
    
    - name: Push Docker image
      run: |
        docker push ${{ env.DOCKER_IMAGE }}:${{ github.sha }}
        docker tag ${{ env.DOCKER_IMAGE }}:${{ github.sha }} ${{ env.DOCKER_IMAGE }}:latest
        docker push ${{ env.DOCKER_IMAGE }}:latest

  deploy:
    runs-on: ubuntu-latest
    needs: build
    environment: production
    
    steps:
    - name: Deploy to production
      uses: appleboy/ssh-action@v1.0.3
      with:
        host: ${{ secrets.PRODUCTION_HOST }}
        username: ${{ secrets.PRODUCTION_USERNAME }}
        key: ${{ secrets.PRODUCTION_SSH_KEY }}
        script: |
          cd /opt/app
          docker-compose pull
          docker-compose up -d

Стратегии кеширования

Кеширование Docker слоев

- name: Cache Docker layers
  uses: actions/cache@v4
  with:
    path: /tmp/.buildx-cache
    key: ${{ runner.os }}-buildx-${{ github.sha }}
    restore-keys: |
      ${{ runner.os }}-buildx-

Кеширование для Python проектов

- name: Cache pip packages
  uses: actions/cache@v4
  with:
    path: ~/.cache/pip
    key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
    restore-keys: |
      ${{ runner.os }}-pip-

Автоматическое развертывание

Деплой в разные среды

deploy:
  runs-on: ubuntu-latest
  environment: ${{ github.ref == 'refs/heads/main' && 'production' || 'staging' }}
  strategy:
    matrix:
      environment: [staging, production]
  
  steps:
  - name: Deploy to ${{ matrix.environment }}
    run: |
      echo "Deploying to ${{ matrix.environment }}"
      # Ваши команды деплоя

Деплой с проверками

deploy-to-staging:
  runs-on: ubuntu-latest
  environment: staging
  needs: test
  
  steps:
  - name: Check deployment readiness
    run: |
      # Проверка готовности к деплою
  
  - name: Deploy to staging
    run: ./scripts/deploy.sh staging
  
  - name: Run smoke tests
    run: ./scripts/smoke-tests.sh staging
  
  - name: Notify team
    if: success()
    uses: 8398a7/action-slack@v3
    with:
      status: success
      channel: '#deployments'

deploy-to-production:
  runs-on: ubuntu-latest
  environment: production
  needs: deploy-to-staging
  
  steps:
  - name: Wait for approval
    uses: trstringer/manual-approval@v1
    with:
      secret: ${{ github.TOKEN }}
      approvers: ${{ vars.PRODUCTION_APPROVERS }}
  
  - name: Deploy to production
    run: ./scripts/deploy.sh production

Практический кейс: React + Node.js приложение

name: React + Node.js CI/CD

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

jobs:
  test-frontend:
    runs-on: ubuntu-latest
    
    steps:
    - uses: actions/checkout@v4
    
    - name: Setup Node.js
      uses: actions/setup-node@v4
      with:
        node-version: '18.x'
        cache: 'npm'
        cache-dependency-path: frontend/package-lock.json
    
    - name: Install frontend dependencies
      working-directory: frontend
      run: npm ci
    
    - name: Run frontend tests
      working-directory: frontend
      run: npm test -- --coverage --watchAll=false
    
    - name: Build frontend
      working-directory: frontend
      run: npm run build

  test-backend:
    runs-on: ubuntu-latest
    
    services:
      postgres:
        image: postgres:14
        env:
          POSTGRES_PASSWORD: postgres
        options: >-
          --health-cmd pg_isready
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5
        ports:
          - 5432:5432
    
    steps:
    - uses: actions/checkout@v4
    
    - name: Setup Node.js
      uses: actions/setup-node@v4
      with:
        node-version: '18.x'
        cache: 'npm'
        cache-dependency-path: backend/package-lock.json
    
    - name: Install backend dependencies
      working-directory: backend
      run: npm ci
    
    - name: Run database migrations
      working-directory: backend
      run: npm run migrate
      env:
        DATABASE_URL: postgresql://postgres:postgres@localhost:5432/test
    
    - name: Run backend tests
      working-directory: backend
      run: npm test
      env:
        NODE_ENV: test
        DATABASE_URL: postgresql://postgres:postgres@localhost:5432/test

  deploy:
    runs-on: ubuntu-latest
    needs: [test-frontend, test-backend]
    if: github.ref == 'refs/heads/main'
    
    steps:
    - name: Deploy to VPS
      uses: appleboy/ssh-action@v1.0.3
      with:
        host: ${{ secrets.SERVER_HOST }}
        username: ${{ secrets.SERVER_USER }}
        key: ${{ secrets.SERVER_SSH_KEY }}
        script: |
          cd /opt/myapp
          git pull origin main
          docker-compose -f docker-compose.prod.yml up -d --build

Best Practices GitHub Actions

Безопасность

Производительность

Мониторинг и нотификации

- name: Notify Slack on failure
  if: failure()
  uses: 8398a7/action-slack@v3
  with:
    status: failure
    channel: '#alerts'
    username: 'CI Bot'

- name: Upload build artifacts
  uses: actions/upload-artifact@v4
  with:
    name: test-results
    path: test-results/
    retention-days: 7

Полезные Actions для вашего workflow

Заключение

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

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