GitHub Actions появился в 2019 году и быстро стал стандартом для проектов на GitHub. Суть простая: описываете в YAML-файле, что нужно сделать при определённом событии в репозитории, — и GitHub сам запускает это на своих серверах. Пуш в ветку, открытый PR, тег релиза, расписание — всё это триггеры.

Главное преимущество перед Jenkins или собственным CI-сервером — ничего не надо поднимать и поддерживать. Репозиторий есть? CI/CD тоже есть. Бесплатный план даёт 2000 минут в месяц для приватных репозиториев, для публичных — без ограничений. Большинству небольших проектов этого хватает с запасом.

Базовые понятия за пять минут

Терминологии немного, и она логичная.

Workflow — весь сценарий автоматизации. Хранится в файле .github/workflows/название.yml. У одного репозитория может быть несколько воркфлоу.

Job — отдельная задача внутри воркфлоу. Джобы могут выполняться параллельно или последовательно, если между ними есть зависимости.

Step — конкретный шаг внутри джобы. Это либо команда в терминале, либо готовое действие из маркетплейса.

Action — переиспользуемый блок логики. Можно взять чужой из GitHub Marketplace или написать свой.

Runner — сервер, на котором всё это запускается. GitHub предоставляет Ubuntu, Windows и macOS. Ubuntu — самый быстрый и дешёвый вариант.

Event — событие-триггер. Самые частые: push, pull_request, workflow_dispatch (ручной запуск), schedule (по расписанию через cron).

Первый workflow: от нуля до работающего CI

Напишем простой воркфлоу для Node.js-проекта. Запускается при каждом пуше и PR в ветку main, устанавливает зависимости и гоняет тесты.

name: CI

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

jobs:
  test:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: 'npm'

      - name: Install dependencies
        run: npm ci

      - name: Run tests
        run: npm test

Разберём по строкам:

  • on — два триггера: пуш и PR в main.
  • runs-on: ubuntu-latest — последняя Ubuntu от GitHub.
  • actions/checkout@v4 — стандартное действие, клонирует репозиторий в runner.
  • actions/setup-node@v4 — устанавливает Node.js нужной версии. Параметр cache: 'npm' кеширует зависимости между запусками — экономит 30–60 секунд на каждом прогоне.
  • npm ci вместо npm install — более строгая и воспроизводимая установка: берёт версии точно из package-lock.json.

Этого файла уже достаточно, чтобы в GitHub появились зелёные галочки на PR. Больше не нужно спрашивать коллегу «а ты тесты запустил?» — всё видно автоматически.

Деплой: автоматически на сервер после мержа

Тесты — хорошо, но хочется ещё автоматически деплоиться. Вот пример деплоя на VPS через SSH:

name: Deploy

on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    needs: test

    steps:
      - name: Deploy via SSH
        uses: appleboy/ssh-action@v1
        with:
          host: ${{ secrets.SERVER_HOST }}
          username: ${{ secrets.SERVER_USER }}
          key: ${{ secrets.SSH_PRIVATE_KEY }}
          script: |
            cd /var/www/myapp
            git pull origin main
            npm ci --production
            pm2 restart myapp

Несколько важных моментов.

Секреты${{ secrets.SERVER_HOST }} и подобные хранятся в Settings → Secrets → Actions в репозитории. Никаких паролей и ключей в коде.

needs: test — деплой запустится только если джоба test прошла успешно. Без этого параметра джобы идут параллельно.

appleboy/ssh-action — популярное действие из маркетплейса для работы через SSH, более 10 миллионов использований.

Матрица: тестируем на нескольких версиях сразу

Если нужно проверить совместимость с несколькими версиями Node.js или Python — есть матрица:

jobs:
  test:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        node-version: [18, 20, 22]

    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node-version }}
      - run: npm ci
      - run: npm test

GitHub запустит три параллельных джобы. Время прогона почти то же, а уверенности в совместимости больше.

Кеширование: ускоряем в разы

Для Node.js cache: 'npm' в setup-node делает кеширование автоматически. Но можно настроить тоньше:

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

Ключ кеша включает хеш package-lock.json. Если файл не менялся — берётся кеш. Если менялся — кеш инвалидируется. Это снижает время установки зависимостей с 60 до 5–10 секунд.

Для PHP/Composer, Python/pip, Ruby/Bundler логика та же — у actions/cache есть документированные примеры для всех популярных менеджеров пакетов.

Environments и защита продакшена

Для продакшена стоит добавить дополнительную защиту. В GitHub есть понятие Environments — окружений с правилами. Создаётся в Settings → Environments. Можно настроить:

  • Required reviewers — деплой пойдёт только после одобрения конкретного человека
  • Wait timer — автоматическая задержка перед деплоем
  • Deployment branches — только из определённых веток

В воркфлоу это добавляется одной строкой:

jobs:
  deploy:
    runs-on: ubuntu-latest
    environment: production

Теперь деплой в продакшн потребует ручного подтверждения. Простая защита от случайного пуша не в ту ветку.

Полезные паттерны из практики

Запуск только при изменениях в нужных папках. Полезно в монорепозитории — незачем гонять тесты бэкенда при изменении только фронтенда:

on:
  push:
    paths:
      - 'backend/**'
      - 'package.json'

Условное выполнение шагов. Уведомление в Slack только при падении:

- name: Notify on failure
  if: failure()
  uses: slackapi/slack-github-action@v1
  with:
    payload: '{"text": "Deploy failed on ${{ github.ref }}"}'
  env:
    SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }}

Ручной запуск с параметрами. Кнопка «Run workflow» с выпадающим списком прямо в интерфейсе GitHub:

on:
  workflow_dispatch:
    inputs:
      environment:
        description: 'Target environment'
        required: true
        default: 'staging'
        type: choice
        options:
          - staging
          - production

Артефакты. Если в CI собирается билд — его можно сохранить и скачать:

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

Docker и GitHub Container Registry

Если проект деплоится через Docker — GitHub Actions умеет собирать и пушить образы в GitHub Container Registry (ghcr.io):

- name: Log in to Container Registry
  uses: docker/login-action@v3
  with:
    registry: ghcr.io
    username: ${{ github.actor }}
    password: ${{ secrets.GITHUB_TOKEN }}

- name: Build and push
  uses: docker/build-push-action@v5
  with:
    context: .
    push: true
    tags: ghcr.io/${{ github.repository }}:latest
    cache-from: type=gha
    cache-to: type=gha,mode=max

GITHUB_TOKEN — встроенный секрет, доступен в каждом воркфлоу автоматически, создавать вручную не нужно. cache-from: type=gha — кеш Docker-слоёв прямо в Actions Cache, ускоряет сборку образа в 2–5 раз при итеративных изменениях.

Безопасность: версионируйте actions через SHA

Популярный, но недооценённый совет — не используйте @latest или даже @v4 в production-пайплайнах. Вместо этого — полный commit SHA:

# Так делать не стоит:
uses: actions/checkout@latest

# Надёжно:
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683  # v4.2.2

Это защита от supply chain атак: если в популярный action пробрался вредоносный коммит, ваш воркфлоу продолжит использовать проверенную версию.

Когда Actions недостаточно

GitHub Actions закрывает 90% задач, но у него есть ограничения.

Очень долгие пайплайны. Если прогон тестов занимает несколько часов — бесплатные минуты закончатся быстро. Решение: self-hosted runner на своём сервере. Настраивается за 10 минут — скачиваете агент, регистрируете в репозитории, запускаете как сервис. В воркфлоу просто пишете runs-on: self-hosted, и минуты не тратятся.

Сложная оркестрация. Если нужны DAG-пайплайны с десятками зависимостей и условных ветвлений — возможно, удобнее ArgoCD или Tekton.

Другие платформы. GitLab CI, Bitbucket Pipelines, Forgejo Actions — у каждого своя экосистема. Концепции схожи, синтаксис отличается.

Организация файлов

Несколько советов, которые упрощают жизнь:

  • Называйте файлы понятно: ci.yml, deploy-staging.yml, deploy-prod.yml, release.yml
  • Не кладите всё в один большой файл — лучше несколько маленьких с чёткой ответственностью
  • Переиспользуемую логику выносите в reusable workflows или composite actions в папке .github/actions/
  • Держите воркфлоу под ревью: изменение в .github/workflows/ — такой же PR, как и изменение в коде

В REEXY при разработке сайтов и ботов мы по умолчанию настраиваем GitHub Actions на автодеплой — это часть стандартного рабочего процесса. Клиент получает проект, где пуш в main автоматически доставляет изменения на сервер и прогоняет тесты. Если вас интересует разработка с нормально выстроенными процессами, посмотрите на r3xy.ru.

GitHub Actions — инструмент, который растёт вместе с проектом. Начинаете с десяти строк YAML на запуск тестов, постепенно добавляете деплой, нотификации, матрицы, environments. Порог входа низкий, потолок высокий — и всё это не требует отдельного сервера и команды DevOps для поддержки.