Документы · Инструкция
Как запустить GitHub Actions workflow после завершения другого через workflow_run
Событие `workflow_run` подходит, когда второй процесс должен быть отдельным запуском: например, тесты завершаются, а.
Короткий ответ
Чтобы запустить второй GitHub Actions workflow после завершения первого, используйте событие `workflow_run`: укажите имя исходного workflow в `workflows`, событие `completed`, а результат проверяйте через `github.event.workflow_run.conclusion`. Сам факт `completed` не означает успех — второй workflow стартует и после failed/cancelled, если не добавить условие.
Как работает workflow_run и чем он отличается от needs
`workflow_run` связывает два отдельных файла workflow, а `needs` связывает jobs внутри одного запуска. Это важно, когда сборка и привилегированное действие должны быть разнесены: например, тесты pull request идут без секретов, а отдельный workflow после них публикует результат или обновляет issue. GitHub создаёт новый workflow run, поэтому у него собственные jobs, permissions, логи и контекст. В событии доступны данные о запуске-источнике, включая его id и conclusion. Имя в `workflows` должно совпадать с `name:` исходного workflow, а файл принимающего workflow должен находиться в default branch. Если указать несколько имён, срабатывания достаточно от любого из них. Это не последовательность «по одному разу на каждый workflow», а подписка на завершение перечисленных запусков.
Совет: Для простой последовательности build → test → deploy в одном YAML обычно понятнее `needs`. `workflow_run` полезен именно между отдельными workflow.
Как настроить запуск второго workflow после первого
- В исходном файле задайте стабильное имя, например `name: Build`. Не полагайтесь на имя файла: в `workflow_run.workflows` используется отображаемое имя workflow.
- Создайте второй файл в `.github/workflows/`, добавьте `on: workflow_run`, `workflows: [Build]` и `types: [completed]`.
- В jobs второго workflow проверьте `github.event.workflow_run.conclusion`. Для деплоя обычно требуется `success`; для отдельного уведомления об ошибке — `failure`.
- Если нужно получить артефакт исходного запуска, передайте `run-id: ${{ github.event.workflow_run.id }}` в действие скачивания артефакта и выдайте минимальные `actions: read` permissions.
- Проверьте поведение на ветке: принимающий workflow должен существовать в default branch. При необходимости ограничьте событие фильтром `branches` по ветке исходного workflow.
- Сделайте тестовый failed-run и убедитесь, что привилегированный job не выполняется, если conclusion не `success`.
Почему второй workflow запускается даже после ошибки
Тип `completed` означает только то, что исходный запуск завершился. GitHub отдельно сообщает его итог в `github.event.workflow_run.conclusion`, поэтому условие успеха нужно писать явно. Практический шаблон: оставить trigger широким, а на job поставить `if: ${{ github.event.workflow_run.conclusion == 'success' }}`. Так в истории Actions будет видно, что событие пришло, но job корректно пропущен. Для диагностики ошибки можно сделать второй job с условием `failure`. Не подменяйте это проверкой `success()` без понимания контекста: функции статуса удобны внутри текущего workflow, а здесь вы оцениваете conclusion другого запуска. Также учитывайте, что повторный запуск исходного workflow создаёт событие `completed`; тип `requested` при re-run ведёт себя иначе и, по документации GitHub, для повторного запуска не возникает.
Предупреждение: Если downstream-процесс должен стартовать только после успешной сборки, фиксируйте это условие в YAML, а не в соглашении команды.
Ограничение цепочки и риск привилегий
GitHub ограничивает цепочку `workflow_run`: нельзя бесконечно строить A → B → C → D → E. Документация указывает максимум трёх уровней цепочки после исходного workflow; слишком длинную архитектуру лучше заменить reusable workflow, одним оркестрирующим workflow или внешней системой. Ещё важнее граница доверия. Downstream workflow может иметь секреты и write permissions, которых не было у workflow для pull request. Это полезно для безопасного двухфазного дизайна, но опасно, если второй workflow без проверки исполняет скрипты, бинарники или кэш, сформированные непроверенным кодом. Перед чтением артефакта валидируйте его формат, не распаковывайте исполняемые файлы в рабочую директорию и не используйте данные из PR как команды shell. Permissions задавайте явно и минимально.
Проверка перед включением в основной репозиторий
- Имя `workflows:` совпадает с `name:` исходного workflow.
- Принимающий YAML уже есть в default branch.
- На `completed` отдельно проверяется `conclusion`.
- Секреты и write permissions выдаются только тем jobs, которым они нужны.
- Артефакты предыдущего запуска скачиваются по `workflow_run.id`, а не по «последнему запуску».
- Нет цепочки workflow_run длиннее поддерживаемого лимита.
- Fail/cancel сценарии протестированы отдельно от success.
Важно: `workflow_run` может получить секреты и write-token даже после непривилегированного workflow. Не запускайте непроверенный код из скачанного артефакта в привилегированном контексте.
Когда workflow_run лучше не использовать
Не используйте `workflow_run` как универсальную замену зависимостей. При большом числе мелких стадий отдельные workflow усложняют трассировку: новый run получает собственный URL, очередь и permissions, а причинно-следственную связь приходится искать через payload. Для монорепозитория с обычными build/test/package этапами один workflow с `needs` чаще прозрачнее. `workflow_run` оправдан, когда нужен реальный разрыв доверия, отдельные права, разные владельцы процессов или независимый жизненный цикл файлов. Если требуется параметризованно вызывать общий набор jobs из нескольких workflow, используйте `workflow_call`; если событие приходит из внешней системы — `repository_dispatch`. Выбор механизма по границе задачи уменьшает количество условных конструкций и снижает вероятность того, что привилегированный workflow будет запускаться в неожиданном сценарии.
Edge cases: rerun, несколько исходных workflow и ветки
Если один listener подписан на несколько исходных workflow, событие возникает после завершения любого из них, поэтому в сложной схеме полезно проверять `github.event.workflow_run.name` и не считать, что все перечисленные процессы уже закончились. Для барьера «ждать A и B» `workflow_run` сам по себе не является join-механизмом: храните состояние отдельно или объединяйте стадии в один оркестрирующий workflow. При re-run обращайте внимание на тип события: `completed` снова приходит после завершения, а `requested` для повторного запуска не возникает. Фильтр `branches` относится к ветке, на которой выполнялся triggering workflow, а не к ветке файла listener. Перед production-пуском проверьте push в feature branch, pull request, ручной rerun и отмену — эти сценарии быстро показывают неверные предположения о payload.
Проверка имени и контекста triggering workflow
При отладке выведите в лог безопасные поля `github.event.workflow_run.id`, `name`, `head_branch` и `conclusion`. Это помогает увидеть, какой именно запуск вызвал listener, особенно если в `workflows` перечислено несколько имён. Не печатайте весь event payload без необходимости: в нём может оказаться лишняя служебная информация. Для production лучше логировать только идентификаторы, нужные для трассировки. Если downstream скачивает артефакт, связывайте его с конкретным run id, а не с поиском «самого свежего» артефакта по имени: параллельные запуски иначе легко перепутать.
Что учитывать
Тип `completed` означает только то, что исходный запуск завершился. GitHub отдельно сообщает его итог в `github.event.workflow_run.conclusion`, поэтому условие успеха нужно писать явно. Практический шаблон: оставить trigger широким, а на job поставить `if: ${{ github.event.workflow_run.conclusion == 'success' }}`. Так в истории Actions будет видно, что событие пришло, но job корректно пропущен. Для диагностики ошибки можно сделать второй job с условием `failure`. Не подменяйте это проверкой…
Источники и проверка
Фактическая часть сверена по первичным источникам (в т.ч. Events that trigger workflows). Пример и формулировки — редакция N1RO на 2026-09-21.