Компьютеры · Инструкция
Как запустить GitHub Actions извне через repository_dispatch
`repository_dispatch` превращает внешнее событие в штатный trigger GitHub Actions.
Короткий ответ
Для запуска GitHub Actions из внешней системы используйте `repository_dispatch`: отправьте REST-запрос с `event_type`, при необходимости добавьте `client_payload`, а в YAML подпишитесь на тот же `event_type`. Workflow-файл должен существовать в default branch.
Когда repository_dispatch подходит лучше webhook или workflow_dispatch
`repository_dispatch` нужен, когда инициатор находится вне GitHub: CI другой платформы, внутренний сервис, система релизов или скрипт, который сообщает «артефакт готов». В отличие от `workflow_dispatch`, событие не требует ручного нажатия кнопки и семантически описывает внешнее событие. В отличие от обычного webhook, оно не просто отправляет уведомление из GitHub наружу, а запускает workflow внутри репозитория. В запросе задаётся `event_type` — короткий тип события, например `image_published`, а дополнительные данные помещаются в `client_payload`. Workflow читает их через `github.event.client_payload`. Это удобнее, чем кодировать параметры в имени ветки или создавать фиктивный commit только ради запуска автоматизации.
Совет: Давайте `event_type` смысловое имя события, а не имя команды. Тогда внешняя система сообщает факт, а решение о действиях остаётся в workflow.
Настройка внешнего запуска по шагам
- В `.github/workflows/external.yml` добавьте `on: repository_dispatch` и `types: [image_published]` или другой ваш event_type.
- Убедитесь, что этот workflow уже находится в default branch: GitHub не запустит `repository_dispatch`, если listener-файл отсутствует там.
- Для REST endpoint `POST /repos/{owner}/{repo}/dispatches` используйте GitHub App token или fine-grained PAT с минимально нужным доступом. Для fine-grained token GitHub указывает permission `Contents: write`; не храните долгоживущий токен в клиентском JavaScript.
- Из внешнего сервиса отправьте запрос к endpoint dispatches репозитория с JSON, где есть `event_type`, а при необходимости `client_payload` с id сборки, тегом, URL или другими параметрами.
- В workflow обращайтесь к данным через `github.event.client_payload.<поле>`. Для значений, влияющих на shell-команды, используйте env и валидируйте допустимый формат.
- Добавьте idempotency на стороне вашей логики: внешний сервис может повторить запрос, поэтому deployment/job не должен ломаться от повторного события.
Важно: GitHub ограничивает `event_type` 100 символами; в `client_payload` допускается до 10 полей верхнего уровня и до 65 535 символов. Переменные данные держите в payload, а не в имени события.
Как передавать параметры через client_payload безопасно
`client_payload` удобен для данных события; GitHub допускает до 10 свойств верхнего уровня и общий payload до 65 535 символов: номер сборки, имя окружения, digest образа, URL отчёта. Но payload следует считать внешним вводом. Не подставляйте строку из `github.event.client_payload` напрямую в `run:` так, чтобы она могла стать частью shell-синтаксиса. Сначала присвойте значение переменной окружения, проверьте регулярным выражением или allowlist и только затем используйте. Для окружения разумно разрешать, например, только `staging` и `production`; для тега контейнера — ограниченный набор символов. Секреты в payload передавать не нужно: они останутся в истории события и логах интеграции. Секрет для деплоя храните в GitHub environment/secret и выдавайте job только после валидации входных данных.
GITHUB_REF, default branch и неожиданный код
Для `repository_dispatch` GitHub связывает событие с default branch: `GITHUB_REF` указывает на неё, а `GITHUB_SHA` — на последний commit default branch в момент события. Это означает, что payload сам по себе не переключает исполняемый код на произвольную ветку. Если внешняя система присылает имя ref и workflow потом делает checkout этого ref вручную, вы уже создаёте собственную модель доверия и должны проверять значение. Для безопасного deploy-процесса лучше передавать неизменяемый идентификатор артефакта — например digest контейнера — чем название плавающей ветки. Такой подход также помогает повторяемости: повтор события должен развернуть тот же артефакт, а не то, что случайно оказалось в branch через несколько минут.
Предупреждение: Если внешний сервис может быть скомпрометирован, ограничьте его способность выбирать код или окружение. Событие должно запускать проверяемую процедуру, а не произвольную команду.
Что проверить, если repository_dispatch не запускает workflow
- Listener workflow находится в default branch.
- `event_type` в запросе совпадает со значением в `types`.
- Запрос отправляется в правильный owner/repo.
- Токен действителен и имеет требуемый доступ к репозиторию.
- JSON валиден и содержит обязательный `event_type`.
- Workflow не отфильтровывает событие дополнительным `if`.
- В Actions не отключены workflow или политика организации не блокирует их выполнение.
Когда выбрать другой механизм
Если запуск делает человек из интерфейса GitHub, проще `workflow_dispatch` с типизированными inputs. Если один workflow вызывает общий набор jobs, используйте reusable workflow через `workflow_call`: это даёт явный контракт inputs/secrets/outputs. Если нужно только реагировать на событие самого GitHub — push, pull request, release — используйте нативный trigger этого события, а не промежуточный dispatch. `repository_dispatch` остаётся сильным вариантом для внешних источников, потому что не требует фальшивых коммитов и не смешивает интеграционный сигнал с историей Git. Хорошая схема — узкий `event_type`, минимальный payload, строгая проверка и отдельные GitHub secrets. Тогда внешний сервис сообщает «что случилось», а репозиторий сам определяет, что разрешено сделать.
Практический пример контракта внешнего события
Хороший контракт dispatch-события минимален: `event_type: artifact_published`, а в `client_payload` — `artifact_id`, `digest`, `environment_hint` и `source_run`. В workflow сначала проверяется формат digest, затем по внутренней таблице определяется допустимое окружение, и только после этого запускается deployment. Плохой контракт выглядит как `client_payload.command: "kubectl .."`: тогда внешний источник фактически получает удалённую shell-консоль. Для наблюдаемости сохраняйте внешний correlation id в job summary или логах и возвращайте статус во внешнюю систему отдельным API-вызовом. Так повторные события можно дедуплицировать, а расследование не требует угадывать, какой внешний запрос породил конкретный Actions run. Если требуется строгая доставка «ровно один раз», реализуйте её прикладной логикой: сам HTTP-вызов не заменяет идемпотентность.
Как тестировать интеграцию до production
Создайте отдельный безвредный `event_type`, например `integration_test`, и job, который только валидирует payload и пишет correlation id. Так можно проверить токен, endpoint, default branch и формат JSON без запуска реального деплоя. После этого добавьте production-type с отдельным `if` и environment protection. Полезно также отправить намеренно неверные значения и убедиться, что workflow завершается до привилегированных шагов. Тест должен включать повтор одного и того же correlation id, чтобы проверить, что ваша прикладная логика не выполняет критичное действие дважды.
Что учитывать
Условия меняются. Страница отражает состояние на 2026-09-21; при расхождении с официальной документацией приоритет у первоисточника.
Источники и проверка
Фактическая часть сверена по первичным источникам (в т.ч. Events that trigger workflows). Пример и формулировки — редакция N1RO на 2026-09-21.