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 для поддержки.