Learn (Almost) Anything
КаталогСкачать курс

Автоматизация в GitHub

Каталог trigger-механики: `push`, `pull_request`, `pull_request_target`, `workflow_dispatch`, `schedule`, `repository_dispatch`, `workflow_run`, `workflow_call`, activity types, branch/tag/path filters и типичные ловушки с pending checks.

ruЭнциклопедия33 урока6 модулей9
GitHub actionsАвтоматизация в GitHubМодель workflowсостояние и артефактыматрицы и runtimeрелизы и environmentsПереиспользование и собственные actionsgovernance и эксплуатацияgithubactions

Events и filters

Каталог trigger-механики: `push`, `pull_request`, `pull_request_target`, `workflow_dispatch`, `schedule`, `repository_dispatch`, `workflow_run`, `workflow_call`, activity types, branch/tag/path filters и типичные ловушки с pending checks.

Events и filters

Event в GitHub Actions — это причина, по которой GitHub создает workflow run. В предыдущей статье workflow был описан как файл с on, jobs и steps; здесь фокус только на on: какие события бывают, как их сузить фильтрами и почему «workflow не запустился» иногда означает не ошибку, а точное совпадение правил.

Базовая форма короткая:

on: push

Но в реальных репозиториях почти всегда используют развернутую форму, потому что trigger без фильтров быстро становится шумным:

on:
  push:
    branches: [main]
    paths:
      - "apps/web/**"
      - "packages/ui/**"
  pull_request:
    branches: [main]
    types: [opened, synchronize, reopened, ready_for_review]

push здесь означает «коммиты попали в подходящую ветку и изменили подходящие файлы». pull_request означает «изменилось состояние PR в сторону main». types ограничивает activity types: не все действия вокруг PR должны гонять CI.

flowchart TD A[Событие в GitHub или внешний вызов] --> B{Совпал event в on?} B -- нет --> X[Run не создается] B -- да --> C{Совпали types?} C -- нет --> X C -- да --> D{Совпали branches / tags?} D -- нет --> X D -- да --> E{Совпали paths?} E -- нет --> P[Workflow может быть skipped; required check иногда остается Pending] E -- да --> F[GitHub создает workflow run] F --> G[Jobs ставятся в очередь на runners] G --> H[Steps выполняются последовательно внутри job]
flowchart TD
  A[Событие в GitHub или внешний вызов] --> B{Совпал event в on?}
  B -- нет --> X[Run не создается]
  B -- да --> C{Совпали types?}
  C -- нет --> X
  C -- да --> D{Совпали branches / tags?}
  D -- нет --> X
  D -- да --> E{Совпали paths?}
  E -- нет --> P[Workflow может быть skipped; required check иногда остается Pending]
  E -- да --> F[GitHub создает workflow run]
  F --> G[Jobs ставятся в очередь на runners]
  G --> H[Steps выполняются последовательно внутри job]
Как GitHub превращает событие и фильтры в workflow run.

Частые события

push — основной trigger для CI на ветках, релизных tag’ов и деплоя после merge. На push доступны фильтры branches, branches-ignore, tags, tags-ignore, paths, paths-ignore. Важно: если указать только branches, workflow не будет запускаться для tag’ов; если только tags — не будет запускаться для веток.

on:
  push:
    branches:
      - main
      - "release/**"
    tags:
      - "v*.*.*"

pull_request — обычный trigger для проверки входящих изменений. Он запускается в контексте PR и подходит для тестов, линтеров, сборки, preview-проверок. Для PR из fork’ов действуют ограничения по secrets и запуску workflow, поэтому не стоит ожидать, что такой workflow получит все привилегии основного репозитория. Права и токены отдельно разобраны в Permissions и GITHUB_TOKEN.

pull_request_target похож названием, но это другой инструмент. Он выполняется в контексте base-репозитория и default branch, поэтому годится для безопасных действий с PR как с объектом GitHub: поставить label, оставить комментарий, проверить метаданные. Его не используют для сборки или запуска кода из untrusted PR. Если в таком workflow сделать checkout кода из fork’а и выполнить scripts, можно открыть доступ к write-token’у или secrets. Для этой темы есть отдельная статья pull_request_target и untrusted PR.

workflow_dispatch — ручной запуск из UI, GitHub CLI или API. Он хорош для deploy, backfill, ручных maintenance-задач. Обычно его используют с inputs:

on:
  workflow_dispatch:
    inputs:
      environment:
        description: "Target environment"
        required: true
        type: choice
        options: [staging, production]
      dry_run:
        description: "Do not apply changes"
        type: boolean
        default: true

Inputs доступны через inputs и github.event.inputs; разница между expression-time и shell runtime раскрыта в Contexts и expressions.

schedule запускает workflow по cron. По умолчанию расписания живут на default branch и используют latest commit default branch. Cron-задачи не стоит ставить ровно на начало часа: в периоды высокой нагрузки возможны задержки, а при сильной нагрузке GitHub может отбросить часть queued jobs. Практичный вариант — 17 3 * * *, а не 0 3 * * *.

on:
  schedule:
    - cron: "17 3 * * 1-5"

repository_dispatch нужен, когда событие приходит извне GitHub: например, внешний сервис закончил импорт данных и хочет дернуть workflow. Это API-trigger с event_type и client_payload. Он выполняется на default branch и требует, чтобы workflow-файл уже был там.

on:
  repository_dispatch:
    types: [catalog-imported]

jobs:
  react:
    runs-on: ubuntu-latest
    steps:
      - run: echo "${{ github.event.client_payload.batch_id }}"

workflow_run связывает два workflow: один завершился, второй стартовал. Это удобно для privilege separation: первый workflow на pull_request запускает тесты без secrets, второй после успешного результата публикует комментарий или делает privileged action. Но workflow_run тоже security-sensitive: артефакты и данные из предыдущего workflow надо считать входом из недоверенного источника. Граф job’ов внутри одного workflow через needs обычно проще; смотри Jobs, dependencies и conditions.

workflow_call — не событие из внешнего мира, а объявление reusable workflow. Такой workflow вызывается другим workflow на уровне job через jobs.<id>.uses, а не внутри steps. Подробности — в Reusable workflows.

Activity types

Многие события имеют activity types. Для pull_request это, например, opened, synchronize, reopened, closed, ready_for_review. Для issuesopened, edited, labeled и так далее. Если types не указан, GitHub использует default-набор для конкретного event, а не обязательно «все возможные действия».

on:
  pull_request:
    types: [opened, synchronize, reopened]

types полезен как документирование намерения. CI обычно реагирует на synchronize, потому что это новый push в PR. Автоматизация labels может реагировать на opened и edited. Release workflow может слушать release: types: [published], чтобы не запускаться на draft-правках.

Branch, tag и path filters

Фильтры отвечают на вопрос: «Это событие вообще должно создавать run?» Они применяются до выполнения job’ов. Поэтому фильтр — не то же самое, что if внутри job. if оставит workflow run в истории, а фильтр может не создать run вовсе.

on:
  pull_request:
    branches:
      - main
    paths:
      - "src/**"
      - "package-lock.json"
      - "!src/experimental/**"

Если одновременно указаны branch filters и path filters, workflow запускается только когда выполнены оба условия. Для push по tag’ам path filters не оцениваются. Порядок path-паттернов с ! важен: отрицательный паттерн после положительного исключает путь, а положительный после отрицательного может снова включить его. Для чистого исключения проще использовать paths-ignore, но нельзя одновременно использовать paths и paths-ignore для одного и того же event.

Типичная ловушка — required checks и skipped workflow. Если workflow пропущен из-за branch filter, path filter или commit message skip, связанный check может остаться в состоянии Pending, и PR будет заблокирован branch protection. Это часто проявляется в монорепозиториях: команда добавляет paths: ["apps/api/**"], потом делает docs-only PR, а branch protection все еще требует check с тем же именем. Решение — проектировать required checks так, чтобы они всегда создавались, либо разделять обязательный lightweight workflow и тяжелые path-filtered jobs.

Несколько trigger’ов в одном workflow

Один workflow может иметь несколько events:

name: CI

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

Это нормальная схема для CI: проверять PR до merge, проверять main после merge и позволять ручной rerun. Но не стоит механически складывать все в один файл. Deploy на push в main, release по tag’у и scheduled cleanup имеют разные permissions, secrets, environments и failure-модели. Часто их лучше разделить на ci.yml, deploy.yml, release.yml.

Практическая карта выбора

Для обычной проверки кода берите pull_request плюс push в protected branches. Для публикации после merge — push в main или release branch. Для versioned release — push.tags или release. Для ручной операции — workflow_dispatch. Для cron-задачи — schedule. Для вызова из внешней системы — repository_dispatch. Для стандартизации pipeline между репозиториями — workflow_call. Для privileged continuation после неполномочного workflow — workflow_run, но с явной threat model.

Главная привычка: сначала назвать источник события, затем сузить его минимальными filters, затем отдельно проверить security-контекст. Trigger решает не только «когда запускать», но и «какие данные, SHA, ref, token и secrets окажутся внутри run».

See also

Быстрое повторение #rc-1

В workflow написано:

on:
  push:
    branches: [main]
    paths:
      - "apps/web/**"

Что должно совпасть, чтобы GitHub вообще создал run?

Показать ответ

Должны одновременно совпасть и branch filter, и path filter: push должен быть в main, а изменения должны затронуть apps/web/**. Если одно из условий не выполнено, workflow run не создается.

Источники

  1. GitHub Docs — Events that trigger workflows
  2. GitHub Docs — Workflow syntax for GitHub Actions
  3. GitHub Docs — Triggering a workflow
  4. GitHub Docs — Secure use reference