← Весь справочник

GitHub Actions

Workflow GitHub Actions — on, jobs, runs-on, steps uses/run, needs, matrix, выражения, workflow_call, actionlint

GitHub Actions запускает workflow — YAML-файлы из каталога .github/workflows/ — по событиям репозитория: push, pull request, расписание, ручной запуск. Workflow состоит из задач (jobs), которые по умолчанию идут параллельно, каждая на своей виртуальной машине (раннере). Задача — это последовательность шагов (steps): готовое действие (uses) или команда оболочки (run).

Проверка в песочнице: actionlint разбирает workflow и находит ошибки в ключах, выражениях ${{ }}, ссылках между задачами, входах популярных действий и (через shellcheck) в скриптах run.

Синтаксис

name: CI
on: push                 # когда запускать
jobs:
  имя_задачи:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: echo hello

Ключи верхнего уровня

КлючЧто задаёт
name / run-nameимя workflow / имя конкретного запуска (можно с выражениями)
onсобытия-триггеры
permissionsправа токена GITHUB_TOKEN: contents: read, packages: write…
envпеременные окружения для всех задач
defaults: run:shell и working-directory для всех шагов run
concurrencygroup и cancel-in-progress: не запускать параллельно одинаковые запуски
jobsзадачи

События on

СобытиеКогда срабатывает
pushpush; фильтры branches, tags, paths, branches-ignore, paths-ignore
pull_requestсобытия PR; types: [opened, synchronize], те же фильтры веток и путей
workflow_dispatchручной запуск кнопкой; inputs — параметры формы
scheduleпо расписанию: - cron: '0 3 * * 1' (время UTC)
workflow_callвызов из другого workflow (переиспользуемый); inputs, secrets, outputs
release, issues, workflow_run…другие события репозитория

Ключи задачи

КлючЧто задаёт
runs-onраннер: ubuntu-latest, windows-latest, macos-latest или метки своего раннера
needsот каких задач зависит: запустится после их успеха
ifусловие выполнения задачи
stepsшаги задачи
envпеременные для всех шагов задачи
outputsзначения, которые увидят зависимые задачи через needs.<id>.outputs
strategy.matrixзапустить задачу для каждой комбинации значений; include, exclude
strategy.fail-fast / max-parallelотменять ли остальные комбинации при падении / сколько одновременно
environmentокружение (секреты окружения, правила одобрения)
container / servicesвыполнять шаги в контейнере / поднять рядом контейнеры (БД)
timeout-minutes / continue-on-errorограничение времени / не валить workflow при ошибке
uses + with + secretsвместо steps: вызвать переиспользуемый workflow

Ключи шага

КлючЧто задаёт
uses: владелец/репо@версияготовое действие; ./путь — локальное
withвходные параметры действия
runкоманды оболочки (несколько строк — через |)
shellbash, sh, pwsh, python
name / idподпись в логе / идентификатор для steps.<id>.outputs
ifусловие выполнения шага
envпеременные шага
working-directoryкаталог для run
continue-on-error / timeout-minutesне валить задачу / ограничение времени

В одном шаге — либо uses, либо run.

Выражения и контексты

Выражения пишутся в ${{ … }}; в if скобки можно опустить.

КонтекстЧто содержит
githubсобытие и репозиторий: github.ref, github.sha, github.event_name, github.actor, github.event.*
env / varsпеременные окружения / переменные репозитория из настроек
secretsсекреты: secrets.DEPLOY_TOKEN, secrets.GITHUB_TOKEN
matrixзначения текущей комбинации матрицы
needsрезультаты и outputs задач из needs
stepsoutputs и исход предыдущих шагов (steps.<id>.outputs.x)
inputsпараметры workflow_dispatch / workflow_call
runnerсведения о раннере: runner.os, runner.temp
ФункцияЧто делает
success(), failure(), always(), cancelled()статус для if: по умолчанию шаг идёт только при success()
contains(a, b), startsWith(a, b), endsWith(a, b)проверки строк и списков
format('{0}-{1}', a, b), join(список, ',')сборка строк
toJSON(x) / fromJSON(s)в JSON / из JSON
hashFiles('**/package-lock.json')хэш файлов — для ключей кэша

Операторы: ==, !=, &&, ||, !, <, >.

Файлы раннера

ПеременнаяЧто в неё писать
$GITHUB_OUTPUTимя=значение — output шага (steps.<id>.outputs.имя)
$GITHUB_ENVИМЯ=значение — переменная окружения для следующих шагов
$GITHUB_PATHкаталог, который добавится в PATH следующих шагов
$GITHUB_STEP_SUMMARYMarkdown для страницы итогов запуска

Примеры

name: CI

on:
  push:
    branches: [main]
  pull_request:

jobs:
  test:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        node: [20, 22]
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node }}
      - run: npm ci
      - run: npm test

  build:
    needs: test
    runs-on: ubuntu-latest
    outputs:
      version: ${{ steps.ver.outputs.version }}
    steps:
      - uses: actions/checkout@v4
      - id: ver
        run: echo "version=1.0.${{ github.run_number }}" >> "$GITHUB_OUTPUT"
      - name: Сборка
        run: |
          mkdir -p dist
          echo "built" > dist/app.txt
      - uses: actions/upload-artifact@v4
        with:
          name: dist
          path: dist/
      - if: failure()
        run: echo "сборка упала"

Переиспользуемый workflow и его вызов:

# .github/workflows/deploy.yml
on:
  workflow_call:
    inputs:
      environment:
        type: string
        required: true
    secrets:
      token:
        required: true
jobs:
  deploy:
    runs-on: ubuntu-latest
    environment: ${{ inputs.environment }}
    steps:
      - run: echo "deploy to ${{ inputs.environment }}"
        env:
          TOKEN: ${{ secrets.token }}
---
# .github/workflows/release.yml
on: workflow_dispatch
jobs:
  call:
    uses: ./.github/workflows/deploy.yml
    with:
      environment: production
    secrets:
      token: ${{ secrets.DEPLOY_TOKEN }}
# проверить все workflow репозитория (запускать внутри git-репозитория)
actionlint

# проверить конкретные файлы
actionlint .github/workflows/ci.yml

# пример сообщения:
# ci.yml:6:5: unexpected key "branch" for "push" section. expected one of "branches", ... [syntax-check]

# посмотреть триггеры через yq (он понимает YAML 1.2 и видит ключ on как строку)
yq '.on | keys' .github/workflows/ci.yml

Подводные камни

  • on в YAML 1.1 — это true. GitHub и actionlint читают ключ on правильно, но парсеры YAML 1.1 (например, PyYAML в Python-скриптах) превращают его в булево True, и data['on'] даёт KeyError. В своих скриптах ищи ключ True или пиши в файле "on": в кавычках. Так же в YAML 1.1 ведут себя yes/no/off.
  • actionlint без аргументов ищет git-репозиторий вверх по каталогам. Вне репозитория он завершится с ошибкой no project was found — передай пути к файлам явно.
  • Workflow должен лежать в .github/workflows/ и иметь расширение .yml или .yaml, иначе GitHub его не увидит.
  • Шаг с uses и run одновременно — ошибка. Разнеси их по двум шагам.
  • Ключи с опечатками (branch вместо branches, step вместо steps, fetch_depth вместо fetch-depth) не дают работающего workflow — actionlint их ловит.
  • needs.<id>.outputs доступны, только если задача указана в needs и объявила outputs. Иначе выражение пустое, а actionlint предупредит.
  • После падения шага следующие пропускаются. Чтобы шаг выполнился всегда (уборка, отчёт), нужен if: always() или if: failure().
  • Недоверенные данные в run — инъекция. ${{ github.event.pull_request.title }} подставляется в скрипт как текст. Передавай такие значения через env: и используй как "$TITLE".
  • schedule работает по UTC и только для основной ветки репозитория.
  • Версии действий закрепляй тегом или хэшем (@v4), а не веткой: ветка может измениться без предупреждения.

См. также

gitlab-ci · git · yq · shellcheck