GitHub Actions
GitHub Actions — это платформа автоматизации, встроенная в GitHub, которая позволяет определять и запускать автоматизированные рабочие процессы непосредственно в вашем репозитории кода без использования каких-либо внешних инструментов CI/CD.
Типичные сценарии использования включают: автоматический запуск тестов после отправки кода, автоматическое развёртывание на серверах после слияния PR, а также запуск скриптов сбора данных по расписанию.

GitHub Actions дляпубличных репозиториев полностью бесплатен., для приватных репозиториев доступна бесплатная квота 2,000 минут в месяц.
Основные концепции
Прежде чем писать файл конфигурации, нужно понять следующие основные концепции, а связи между ними таковы:
仓库(Repository)
└── Workflow(工作流) ← 一个 .yml 文件 = 一个 Workflow
├── Event(触发事件) ← 什么情况下启动这个 Workflow,如 push、PR
└── Job(作业)× N ← 一个 Workflow 可以包含多个并行或串行的 Job
├── Runner(运行器) ← 执行 Job 的服务器,如 ubuntu-latest
└── Step(步骤)× N ← Job 内按顺序执行的一系列操作
├── Action ← 可复用的封装好的操作,如 actions/checkout
└── Run ← 直接执行 Shell 命令
| Концепции | Описание | Аналогия |
|---|---|---|
| Рабочий процесс | Весь автоматизированный рабочий процесс определяется.ymlфайлом, хранящимся в.github/workflows/в каталоге |
полный план работы. |
| Event | Условия, запускающие Workflow, например отправка кода, создание PR, запланированные задачи и т. д. | Условие запуска плана. |
| Job(задание) | Независимая единица задачи в Workflow. Каждый Job выполняется на отдельной виртуальной машине, а несколько Job по умолчанию выполняются параллельно. | Раздел в плане. |
| Шаг | Наименьшая единица операции, выполняемая последовательно внутри Job; это может быть команда Shell или Action. | Каждый конкретный шаг в разделе. |
| Действие | Переиспользуемые упакованные операции, от официальных GitHub, сторонних или самостоятельно написанных, черезusesСсылка |
Готовые шаблоны инструментов |
| Runner | Сервер, который выполняет Jobs. GitHub предоставляет три хостируемые среды: Ubuntu, Windows и macOS. | Исполнитель, который выполняет план. |
Создайте свой первый Workflow.
1. Структура каталогов
Все файлы Workflow должны храниться в.github/workflows/каталоге в корне репозитория, а имена файлов должны заканчиваться на.ymlили.yamlИмя файла можно настроить:
your-repo/ ├── .github/ │ └── workflows/ │ ├── ci.yml ← 持续集成流程(如运行测试) │ ├── deploy.yml ← 部署流程 │ └── scheduled.yml ← 定时任务 ├── src/ ├── package.json └── README.md
Репозиторий может содержать несколько файлов Workflow, которые независимы друг от друга и запускаются соответствующими определёнными событиями.
2. Простейший рабочий процесс
Ниже приведён самый простой пример: каждый раз, когда код отправляется в репозиторий, выводится строка "Привет, GitHub Actions!".
Пример
name: Привет, мир # Название рабочего процесса, отображаемое на странице GitHub Actions
on: push # Условие запуска: срабатывает при отправке кода в любую ветку
jobs: # Определить все задания
say-hello: # ID задания (пользовательское имя, уникальное в пределах одного рабочего процесса)
name: Вывести приветствие# Отображаемое имя задания (необязательно; если пусто, отображается ID задания)
runs-on: ubuntu-latest # Указать среду выполнения: использовать последнюю виртуальную машину Ubuntu, предоставленную GitHub
steps: # Все шаги этого задания выполняются по порядку
- name: printMessage# Имя шага (необязательно, используется для идентификации этого шага в логах)
run: echo "Привет, GitHub Actions!" # run: напрямую выполнить команды Shell
YAML-файлы очень чувствительны к отступам и должны использоватьпробелдля отступов, и нельзя использовать клавишу Tab. Рекомендуется использовать VS Code и установить плагин YAML, который может обнаруживать ошибки форматирования в реальном времени.
События-триггеры (on)
onЭто поле определяет, какие события запускают этот Workflow. Это может быть одно событие или комбинация нескольких событий.
1. Общие события-триггеры
| Events | Момент срабатывания | Типичные применения |
|---|---|---|
push |
Когда код отправляется в репозиторий. | Запуск тестов, проверок кода |
pull_request |
Когда создается или обновляется Pull Request. | Автоматическая проверка и тестирование перед слиянием PR. |
schedule |
Запуск по расписанию с использованием Cron-выражения. | Плановые резервные копии, плановый сбор данных. |
workflow_dispatch |
Ручной запуск на веб-странице GitHub | Развертывание по требованию, ручной запуск скриптов. |
release |
При публикации новой версии (создании релиза) | Автоматическая упаковка и публикация в production. |
workflow_call |
При вызове из других рабочих процессов | Повторное использование публичных рабочих процессов (например, публичных рабочих процессов тестирования) |
2. Фильтрация по веткам или путям
Пример
on:
push:
branches:
- main # Срабатывает только при push в ветку main
- develop # Или срабатывает при push в ветку develop
- 'release/**' # Или срабатывает при push в любую ветку, начинающуюся с release/ (** соответствует любым символам)
paths:
- 'src/**' # Дополнительная фильтрация: срабатывает только при изменении файлов в каталоге src/.
- 'package.json' # Или срабатывает при изменении файла package.json
# Эти два находятся в отношении «ИЛИ»; срабатывает любой из них
pull_request:
branches:
- main # Срабатывает только на PR, у которых целевая ветка — main (то есть на PR, предназначенных для слияния в main)
types:
- opened # Когда создаётся PR
- synchronize # Когда в PR отправляется новый коммит
- reopened # Когда PR открывается повторно
3. Триггеры по расписанию (schedule)
Используйте стандартное Cron-выражение для определения времени выполнения; часовой пояс — UTC (пекинское время = UTC+8, требуется преобразование):
Пример
on:
schedule:
# Формат Cron: минута час день месяц неделя
- cron: '0 2 * * *' # Запускать раз в день в 02:00 UTC (то есть в 10:00 по пекинскому времени)
- cron: '0 9 * * 1' # Выполняется один раз каждый понедельник в 09:00 UTC (т.е. в 17:00 по пекинскому времени)
- cron: '*/30 * * * *' # Запускать каждые 30 минут
# Краткий справочник по распространённым cron-выражениям:
# '0 0 * * *' Каждый день в полночь (UTC 00:00)
# '0 * * * *' каждый час ровно в начале часа
# '0 0 * * 0' каждое воскресенье в полночь
# '0 0 1 * *' Полночь 1-го числа каждого месяца
4. Ручной запуск (workflow_dispatch)
workflow_dispatchПозволяет вручную нажать кнопку на вкладке Actions веб-страницы GitHub, чтобы запустить Workflow, а также можно задать входные параметры:
Пример
on:
workflow_dispatch:
inputs:
environment: # Имя входного параметра (можно ссылаться в шагах через ${{ inputs.environment }})
description: 'Целевая среда развёртывания'# Описание параметра, отображается в форме ручного запуска
required: true # Требуется ли это?
default: 'staging' # Значение по умолчанию
type: choice # Тип параметра: choice (выбор из выпадающего списка)
options:
- staging # Необязательные значения
- production
run_tests:
description: 'Запускать ли тесты'
required: false
type: boolean # Тип параметра: boolean (флажок)
default: true
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Отобразить параметры развертывания
run: |
echo "Целевая среда: ${{ inputs.environment }}"
echo "Run tests: ${{ inputs.run_tests }}"
Подробное объяснение заданий и шагов
1. Базовая структура задания
Пример
jobs:
build: # Идентификатор задания, должен быть уникальным в пределах одного рабочего процесса
name: structurebuildProject# Отображаемое имя задания (необязательно)
runs-on: ubuntu-latest # Среда выполнения (обязательно)
# Необязательно: задать переменные окружения для всего задания, доступные всем шагам в задании
env:
NODE_ENV: production
APP_PORT: 8080
# Необязательно: задать тайм-аут в минутах. Задание будет автоматически отменено после тайм-аута, чтобы предотвратить зависание.
timeout-minutes: 30
steps:
# Способ шага 1: использовать Action (ссылка с помощью uses)
- name: Извлечь код
uses: actions/checkout@v4 # Ссылка на официальный checkout Action (@v4 указывает, что используется версия v4)
# Синтаксис шага 2: выполнить команду Shell (указывается с помощью run)
- name: Вывести версию Node
run: node --version
# Шаг 3: выполнение многострочных команд Shell (использование | для нескольких строк)
- name: Установить зависимости и собрать структуру
run: |
npm install
npm run build
echo "Build complete"
2. Среда выполнения (runs-on)
GitHub предоставляет следующие бесплатные размещённые раннеры, которые вы можете выбрать по необходимости:
| Теги | Операционная система | Описание |
|---|---|---|
ubuntu-latest |
Ubuntu (последняя LTS) | Наиболее часто используемый, быстрый и имеет самую щедрую бесплатную квоту. Рекомендуется использовать в первую очередь. |
ubuntu-22.04 |
Ubuntu 22.04 | Укажите фиксированную версию, чтобы избежать проблем несовместимости, вызванных последними обновлениями. |
windows-latest |
Windows Server (последний) | Используется для тестирования или сборки, требующей среды Windows. |
macos-latest |
macOS (последняя) | Используется для сборки приложений iOS/macOS, быстрее всего расходует бесплатную квоту (примерно в 10 раз больше, чем у Ubuntu). |
3. Зависимости между заданиями (needs)
По умолчанию несколько заданий выполняются параллельно. ИспользуйтеneedsВы можете задать порядок выполнения заданий, формируя последовательные зависимости:
Пример
jobs:
test: # Шаг 1: Запустить тесты
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm test
build: # Шаг 2: Сборка проекта
runs-on: ubuntu-latest
needs: test # build запустится только после успешного завершения задания test
steps:
- uses: actions/checkout@v4
- run: npm run build
deploy: # Шаг 3: Развертывание
runs-on: ubuntu-latest
needs: [test, build] # Deploy должен дождаться, пока и test, и build успешно завершатся
steps:
- run: echo Начинаем развертывание...
# Порядок выполнения: test → build → deploy (последовательно)
# Если убрать needs, три задания будут выполняться параллельно.
4. Условное выполнение (if)
ЧерезifВы можете управлять тем, будет ли выполняться Job или Step; это обычно используется для различения веток, определения того, успешно ли завершился предыдущий шаг, и т. д.:
Пример
jobs:
deploy:
runs-on: ubuntu-latest
# если написать if на уровне Job: весь Job выполняется только при push в ветку main
if: github.ref == 'refs/heads/main'
steps:
- uses: actions/checkout@v4
- name: Развертывание в производственную среду
run: ./deploy.sh
# if также можно записать на уровне шага, чтобы контролировать, выполняется ли конкретный шаг
- name: Отправить уведомление об успехе
if: success() # success(): выполняется только когда все вышеуказанные шаги завершатся успешно
run: echo "Развертывание успешно, отправьте уведомление"
- name: Отправить уведомление о сбое
if: failure() # failure(): выполняется только при сбое любого шага
run: echo Развертывание не удалось, отправьте оповещение
- name: Шаги очистки выполняются всегда
if: always() # always(): Выполняется независимо от успеха или сбоя (часто используется для очистки временных файлов)
run: rm -rf ./tmp
Переменные среды и секреты
1. Переменные среды (env)
Переменные среды можно определить на трёх уровнях в рабочем процессе, при этом область действия уменьшается в указанном порядке:
Пример
env:
APP_NAME: my-app
NODE_VERSION: '18'
jobs:
build:
runs-on: ubuntu-latest
# Уровень 2: уровень задания (доступны только шагам внутри текущего задания)
env:
BUILD_MODE: production
steps:
- name: Отобразить переменные среды
# Уровень 3: уровень шага (доступны только текущему шагу)
env:
STEP_VAR: hello
run: |
echo "Имя приложения: $APP_NAME" # Доступ к переменной уровня рабочего процесса
echo "Режим сборки: $BUILD_MODE" # Доступ к переменной уровня задания
echo "Переменная шага: $STEP_VAR" # Доступ к переменной уровня шага
echo "Версия Node: $NODE_VERSION"
2. Встроенные переменные GitHub (контекст github)
GitHub Actions предоставляет набор встроенных переменных контекста, к которым можно получить доступ в любом месте с помощью${{ }}Справочник по синтаксису:
Пример
steps:
- name: Вывести общие встроенные переменные
run: |
echo "Имя репозитория: ${{ github.repository }}" # Например: your-user/your-repo
echo "Событие запуска: ${{ github.event_name }}" # напр., push, pull_request
echo "Текущая ветка: ${{ github.ref_name }}" # напр., main, develop
echo "Submit SHA:${{ github.sha }}" # текущее значение полного SHA-хеша коммита
echo "Committer: ${{ github.actor }}" # имя пользователя, запустившего этот Workflow
echo "Working directory: ${{ github.workspace }}" # путь к каталогу, где находится код после checkout
echo "Run ID:${{ github.run_id }}" # уникальный ID каждого запуска Workflow
echo "RuneditNumber:${{ github.run_number }}" # количество запусков этого Workflow
3. Secrets (управление конфиденциальной информацией)
Конфиденциальная информация, такая как пароли, ключи API, адреса серверов и т. д.Не может быть записана напрямую в файл yml.(Поскольку код является публичным), она должна храниться в Secrets репозитория GitHub.
Шаги настройки: перейдите на страницу репозитория →Settings → Secrets and variables → Actions→ НажмитеNew repository secretзаполните имя и значение, затем сохраните.
Пример
steps:
# В Step ссылайтесь на настроенный Secret через ${{ secrets.secret_name }}
# Значения Secret автоматически маскируются с помощью *** в логах и не будут раскрыты
- name: Развертывание на сервере
env:
SSH_KEY: ${{ secrets.SSH_PRIVATE_KEY }} # Приватный SSH-ключ сервера
SERVER_IP: ${{ secrets.DEPLOY_SERVER_IP }} # IP-адрес сервера
run: |
echo "$SSH_KEY" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
ssh user@$SERVER_IP "cd /app && git pull && pm2 restart all"
# GitHub автоматически предоставляет GITHUB_TOKEN для операций с этим репозиторием (например, отправка кода, создание релизов)
# Не нужно создавать вручную, просто используйте его напрямую
- name: Отправить изменения в репозиторий
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add .
git commit -m "Автообновление [skip ci]"
git push
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # GitHub предоставляет автоматически, не нужно создавать вручную
Введение в общие Actions
Официальный GitHub и сообщество предоставляют большое количество готовых к использованию Actions, черезuses: action名称@版本ссылки, вы можете избежать повторного написания общих операций.
1. actions/checkout (получение кода)
Почти первым шагом каждого Workflow является получение кода репозитория с использованием официальногоactions/checkout:
Пример
steps:
# Самое основное использование: получить последнюю версию кода текущей ветки в рабочий каталог
- uses: actions/checkout@v4
# Расширенное использование: настройка путём передачи параметров с помощью 'with'
- uses: actions/checkout@v4
with:
ref: develop # Получить указанную ветку (по умолчанию получает ветку, в которой произошло событие-триггер)
fetch-depth: 0 # Получить полную историю git (по умолчанию извлекается только последний коммит)
# Установите 0, чтобы получить всю историю, тогда команды вроде git log смогут работать правильно.
submodules: true # Также инициализировать и обновить git-подмодули
2. actions/setup-node (настройка окружения Node.js)
Пример
steps:
- uses: actions/checkout@v4
- name: Настройка окружения Node.js
uses: actions/setup-node@v4
with:
node-version: '20' # Укажите версию Node.js
# После завершения настройки команды npm и node можно использовать напрямую
- run: node --version
- run: npm install
- run: npm test
3. actions/setup-python (настройка окружения Python)
Пример
steps:
- uses: actions/checkout@v4
- name: Настройка окружения Python
uses: actions/setup-python@v5
with:
python-version: '3.11' # Укажите версию Python
- name: Установка зависимостей
run: pip install -r requirements.txt
- name: Запуск тестов
run: pytest tests/
4. actions/cache (кэширование зависимостей для ускорения сборок)
Скачивание зависимостей при каждом запуске рабочего процесса может быть медленным. Использование действия cache позволяет кэшировать зависимости и напрямую использовать их при следующем запуске, что значительно сокращает время сборки:
Пример
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- name: Кэшировать node_modules
uses: actions/cache@v4
with:
path: ~/.npm # Укажите каталог для кэширования
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
# key: уникальный идентификатор для кэша
# hashFiles('**/package-lock.json'): сгенерировать хеш-значение на основе содержимого lock-файла
# Если lock-файл не изменён, ключ не изменён, и кэш попадает напрямую; если lock-файл изменяется, зависимости переустанавливаются.
restore-keys: |
${{ runner.os }}-node-
# restore-keys: стратегия запасного сопоставления при промахе ключа, использующая самый свежий действительный кэш
- run: npm ci # npm ci лучше подходит для CI-сценариев, чем npm install: быстрее и строже
- run: npm test
5. actions/upload-artifact / download-artifact (передача файлов между заданиями)
Разные задания выполняются на независимых виртуальных машинах, поэтому файлы нельзя совместно использовать напрямую. С помощью артефактов можно передать выходные файлы одного задания другому заданию:
Пример
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm install && npm run build # Артефакты сборки будут выведены в каталог ./dist
- name: Загрузить артефакты сборки
uses: actions/upload-artifact@v4
with:
name: dist-files # Имя артефакта (на него ссылаются по этому имени при скачивании)
path: ./dist # Каталог или путь к файлу для загрузки
retention-days: 7 # Количество дней хранения артефакта (макс. 90 дней)
deploy:
runs-on: ubuntu-latest
needs: build # Выполняется после завершения задания build
steps:
- name: Скачать артефакты сборки
uses: actions/download-artifact@v4
with:
name: dist-files # То же, что и имя при загрузке
path: ./dist # Каталог для скачивания локально
- name: DeploymentFile
run: rsync -avz ./dist/ user@server:/var/www/html/
Матричные сборки (Matrix)
Матричные сборки позволяют запускать одну конфигурацию задания параллельно в нескольких средах; обычно используются для тестирования совместимости между версиями и операционными системами:
Пример
jobs:
test:
name: Тест Node ${{ matrix.node-version }} на ${{ matrix.os }}
runs-on: ${{ matrix.os }} # Читает среду выполнения из переменных матрицы
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest] # 3 операционные системы
node-version: ['18', '20', '22'] # 3 версии Node
# Приведённые выше комбинации дают 3 × 3 = 9 параллельных заданий
fail-fast: false # По умолчанию true: отменяет все оставшиеся задания, если одно задание завершается с ошибкой.
# Установите false: даже если комбинация завершается с ошибкой, другие комбинации продолжают выполняться,
# Удобно видеть результаты тестов для всех окружений
steps:
- uses: actions/checkout@v4
- name: Настроить Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }} # Ссылка на переменные matrix
- run: npm ci
- run: npm test
Пример
strategy:
matrix:
os: [ubuntu-latest, windows-latest]
node-version: ['18', '20']
exclude:
- os: windows-latest
node-version: '18' # Исключить комбинацию Windows + Node 18
include:
- os: ubuntu-latest
node-version: '20'
experimental: true # Добавьте дополнительные переменные для конкретных комбинаций (на них можно ссылаться в шагах с помощью matrix.experimental)
Практические примеры
Пример 1: CI проекта Node.js (автоматизированное тестирование)
Каждый раз, когда код отправляется или создаётся PR, автоматически устанавливайте зависимости и запускайте проверки кода и тесты:
Пример
name: Node.js CI
на:
push:
branches: [main, develop]
pull_request:
branches: [main]
jobs:
test:
name: CodeChecksandTesting
runs-on: ubuntu-latest
steps:
- name: Извлечь код
uses: actions/checkout@v4
- name: Настройка окружения Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm' # setup-node имеет встроенную поддержку кэширования, что более лаконично, чем отдельно использовать действие cache
- name: Установка зависимостей
run: npm ci # npm ci будет устанавливать строго в соответствии с package-lock.json,
# Больше подходит для сценариев CI, чем npm install
- name: Запустить линтинг кода (ESLint)
run: npm run lint
- name: Запустить модульные тесты
run: npm test -- --coverage # Также сгенерировать отчёт о покрытии тестов
- name: Загрузить отчёт о покрытии
uses: actions/upload-artifact@v4
if: always() # Загрузить отчёт независимо от того, пройдёт ли тест (чтобы было легко просмотреть причины сбоя)
with:
name: coverage-report
path: ./coverage
Пример 2: CI проекта на Python
Пример
name: Python CI
на:
push:
branches: [main]
pull_request:
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Настройка окружения Python
uses: actions/setup-python@v5
with:
python-version: '3.11'
cache: 'pip' # Кэшировать зависимости pip
- name: Установка зависимостей
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
pip install flake8 pytest # Установить инструменты линтинга и тестирования кода
- name: Запустить проверку форматирования кода (flake8)
run: |
# Проверить синтаксические ошибки и неопределённые переменные (серия E9, F63, F7, F82) и сразу завершить с ошибкой, если обнаружена любая проблема
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
# Проверить стиль кода (максимальная длина строки 120), только подсчитать количество проблем, не завершать с ошибкой.
flake8 . --count --max-line-length=120 --statistics
- name: Запуск тестов
run: pytest tests/ -v # -v выводит подробные результаты тестов
Пример 3: Сборка и отправка Docker-образа(ов)
Пример
name: Сборка и отправка Docker-образа
на:
push:
branches: [main]
tags:
- 'v*' # Запуск при отправке тегов, начинающихся с v, например v1.0.0
jobs:
docker:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
# Используйте официальный Docker Action для генерации тегов образа.
# Например, при отправке v1.2.3 автоматически создаются несколько тегов, таких как 1.2.3, 1, latest
-: Извлечение метаданных Docker (теги образа и т. д.)
id: meta # Установите ID для этого шага, чтобы последующие шаги могли ссылаться на его вывод.
uses: docker/metadata-action@v5
with:
images: your-dockerhub-username/your-image-name
- name: Вход в Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }} # Используйте Access Token вместо пароля для лучшей безопасности
- name: structurebuildandPush образ
uses: docker/build-push-action@v5
with:
context: . # Каталог, в котором находится Dockerfile (текущий каталог)
push: true # true: отправить в Registry после завершения сборки
tags: ${{ steps.meta.outputs.tags }} # Ссылается на список тегов, сгенерированный шагом meta
labels: ${{ steps.meta.outputs.labels }} # Ссылается на информацию о тегах, сгенерированную шагом meta
Пример 4: Автоматическое развёртывание на сервер после сборки
Пример
name: Сборка и развёртывание
на:
push:
branches: [main] # Развёртывание запускается только при push в ветку main
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- name: Установить зависимости и собрать структуру
run: |
npm ci
npm run build # Артефакты сборки выводятся в каталог ./dist
- name: Развернуть на сервере через SSH
uses: appleboy/[email protected] # Сторонний SSH Action, не нужно вручную настраивать SSH
with:
host: ${{ secrets.SERVER_HOST }} # IP-адрес или домен сервера
username: ${{ secrets.SERVER_USER }} # Имя пользователя для входа по SSH
key: ${{ secrets.SSH_PRIVATE_KEY }} # Содержимое приватного ключа SSH (соответствующего открытому ключу на сервере)
port: 22 # Порт SSH, по умолчанию 22
script: |
# Следующие команды выполняются на удалённом сервере
cd /var/www/my-app
git pull origin main
npm ci --production
pm2 restart my-app # Перезапустить приложение Node.js с помощью pm2
echo "Развёртывание завершено: $(date)"
Пример 5: Запланированная задача (автоматическое резервное копирование базы данных)
Пример
name: определить, когда создавать резервную копию базы данных
на:
schedule:
- cron: '0 2 * * *' # Запускать ежедневно в 02:00 UTC (10:00 по пекинскому времени)
workflow_dispatch: # Также поддерживает ручной запуск для временных резервных копий
jobs:
backup:
runs-on: ubuntu-latest
steps:
- name: Выполнить скрипт резервного копирования через SSH
uses: appleboy/[email protected]
with:
host: ${{ secrets.SERVER_HOST }}
username: ${{ secrets.SERVER_USER }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
script: |
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
BACKUP_FILE="/backup/db_$TIMESTAMP.sql"
# Выполнить резервное копирование базы данных
mysqldump -u root -p${{ secrets.DB_PASSWORD }} my_database > $BACKUP_FILE
# Сжать файлы резервных копий
gzip $BACKUP_FILE
# Удалить файлы резервных копий старше 30 дней, чтобы диск не переполнялся
find /backup -name "*.sql.gz" -mtime +30 -delete
echo "Резервное копирование завершено: ${BACKUP_FILE}.gz"
Советы по отладке
1. Включение журналов отладки
Когда запуск Workflow завершается неудачно, но информации в журнале недостаточно, можно включить подробный режим отладки. Способ: перейдите в репозиторийSettings → Secrets and variables → Actions, добавьте следующие два Secrets (установите оба значения вtrue):
ACTIONS_RUNNER_DEBUGВключить подробные журналы runnerACTIONS_STEP_DEBUG: Включить подробное логирование отладки для каждого шага.
2. Вывод контекстной информации для облегчения устранения неполадок
Пример
steps:
- name: Вывести всю контекстную информацию (для отладки; добавляйте при устранении неполадок, удаляйте после решения)
run: |
echo "=== github context ==="
echo '${{ toJson(github) }}' # toJson() преобразует объект в строковый вывод JSON
echo "=== контекст env ==="
echo '${{ toJson(env) }}'
echo "=== контекст job ==="
echo '${{ toJson(job) }}'
3. Локальное тестирование рабочего процесса (с помощью act)
Тестировать рабочий процесс, каждый раз только отправляя код, очень неэффективно.act— это инструмент с открытым исходным кодом, который позволяет локально имитировать выполнение GitHub Actions, значительно повышая эффективность отладки:
# 安装 act(需要本地已安装 Docker) # macOS brew install act # Linux curl https://raw.githubusercontent.com/nektos/act/master/install.sh | sudo bash # 在仓库根目录运行所有 Workflow act # 只运行指定事件触发的 Workflow act push # 只运行指定的 Job act -j build
При запуске локальных тестов,
actОн использует Docker-контейнеры для имитации среды выполнения GitHub, но некоторые Actions (такие какactions/cache) могут вести себя иначе при локальной имитации по сравнению с реальной средой. Окончательные результаты зависят от того, что фактически выполняется на GitHub.
Типичные проблемы и примечания
1. Проблема с разрешениями (Permission denied)
Если Workflow нужно отправить код в репозиторий или работать с Issues, необходимо явно объявить разрешения в файле конфигурации:
Пример
разрешения:
contents: write # Разрешает чтение/запись содержимого репозитория (код, файлы)
issues: write # Разрешает создание и изменение Issues
pull-requests: write # Разрешает операции с Pull Requests
# Принцип наименьших привилегий: предоставляйте только фактически необходимые разрешения, остальные по умолчанию read или none
2. Как избежать циклических срабатываний Workflow
Если Workflow автоматически отправляет код в репозиторий, это может вызвать новое событие push, что приведёт к бесконечному циклу. Решение: в сообщении автоматического коммита добавьте[skip ci]ключевое слово, и GitHub пропустит срабатывание Workflow для этого коммита:
git commit -m "自动格式化代码 [skip ci]"
3. Экранирование специальных символов в YAML
ВrunВ Shell-команде поля используйте${{ }}выражение, если выражение содержит двоеточие (:) и другие специальные символы YAML, нужно заключить всё значение в кавычки или вместо этого сначала присвоить его переменной окружения, а затем использовать переменную окружения:
Пример
steps:
# Не рекомендуется: прямое встраивание сложных команд в выражения ${{ }} может вызвать ошибки синтаксического анализа YAML.
- run: echo ${{ github.event.pull_request.title }}
# Рекомендуется: сначала присвоить значение переменной окружения, затем использовать переменную окружения в Shell
- name: Вывести заголовок PR
env:
PR_TITLE: ${{ github.event.pull_request.title }}
run: echo "Заголовок PR: $PR_TITLE"
Для получения более полной документации, пожалуйста, обратитесь к официальной документации:https://docs.github.com/zh/actions
Другие расширения