Pause a workflow until a job in another workflow completes successfully.
This action uses the Checks API to poll for check results. On success, the action exit allowing the workflow resume. Otherwise, the action will exit with status code 1 and fail the whole workflow.
This is a workaround to GitHub's limitation of non-interdependent workflows 🎉
You can run your workflows in parallel and pause a job until a job in another workflow completes successfully.
name: Test
on: [push]
jobs:
test:
name: Run tests
runs-on: ubuntu-latest
steps:
...
name: Publish
on: [push]
jobs:
publish:
name: Publish the package
runs-on: ubuntu-latest
steps:
- name: Wait for tests to succeed
uses: lewagon/[email protected]
with:
ref: ${{ github.ref }}
check-name: 'Run tests'
repo-token: ${{ secrets.GITHUB_TOKEN }}
wait-interval: 10
...
For GHE support you just need to pass in api-endpoint
as an input.
name: Publish
on: [push]
jobs:
publish:
name: Publish the package
runs-on: ubuntu-latest
steps:
- name: Wait for tests to succeed
uses: lewagon/[email protected]
with:
ref: ${{ github.ref }}
check-name: 'Run tests'
repo-token: ${{ secrets.GITHUB_TOKEN }}
api-endpoint: YOUR_GHE_API_BASE_URL # Fed to https://octokit.github.io/octokit.rb/Octokit/Configurable.html#api_endpoint-instance_method
...
If you can keep the dependent jobs in a single workflow:
name: Test and publish
on: [push]
jobs:
test:
runs-on: ubuntu-latest
steps: ...
publish:
runs-on: ubuntu-latest
needs: test
steps: ...
If you can run dependent jobs in a separate workflows in series:
name: Publish
on:
workflow_run:
workflows: ['Test']
types:
- completed
-
Pushes to master trigger a
test
job to be run against the application code. -
Pushes to master also trigger a webhook that builds an image on external service such as Quay.
-
Once an image is built, a
repository_dispatch
hook is triggered from a third-party service. This triggers adeploy
job. -
We don't want the
deploy
job to start until the master branch passes itstest
job.
name: Trigger deployment on external event
on:
# https://github.com/lewagon/quay-github-actions-dispatch
repository_dispatch:
types: [build_success]
jobs:
deploy:
if: startsWith(github.sha, github.event.client_payload.text)
name: Deploy a new image
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Wait for tests to succeed
uses: lewagon/[email protected]
with:
ref: master
check-name: test
repo-token: ${{ secrets.GITHUB_TOKEN }}
wait-interval: 20
- name: Save the DigitalOcean kubeconfig
uses: digitalocean/action-doctl@master
env:
DIGITALOCEAN_ACCESS_TOKEN: ${{ secrets.DIGITALOCEAN_ACCESS_TOKEN }}
with:
args: kubernetes cluster kubeconfig show my-cluster > $GITHUB_WORKSPACE/.kubeconfig
- name: Upgrade/install chart
run: export KUBECONFIG=$GITHUB_WORKSPACE/.kubeconfig && make deploy latest_sha=$(echo $GITHUB_SHA | head -c7)}}
Check name goes according to the jobs.<job_id>.name parameter.
In this case the job's name is 'test':
jobs:
test:
runs-on: ubuntu-latest
steps:
...
In this case the name is 'Run tests':
jobs:
test:
name: Run tests
runs-on: ubuntu-latest
steps:
...
In this case the names will be:
-
Run tests (3.6)
-
Run tests (3.7)
jobs:
test:
name: Run tests
runs-on: ubuntu-latest
strategy:
matrix:
python: [3.6, 3.7]
To inspect the names as they appear to the API:
curl -u username:$token \
https://api.github.com/repos/OWNER/REPO/commits/REF/check-runs \
-H 'Accept: application/vnd.github.antiope-preview+json' | jq '[.check_runs[].name]'
If you would like to wait for all other checks to complete you may set running-workflow-name
to the name of the current job and not set a check-name
parameter.
name: Publish
on: [push]
jobs:
publish:
name: Publish the package
runs-on: ubuntu-latest
steps:
- name: Wait for other checks to succeed
uses: lewagon/[email protected]
with:
ref: ${{ github.ref }}
running-workflow-name: 'Publish the package'
repo-token: ${{ secrets.GITHUB_TOKEN }}
wait-interval: 10
...
Using this action in a reusable workflow means accepting a constraint that all calling jobs will have the same name. For example, all calling workflows must call their jobs caller
(or some more relevant constant) so that if the reused workflow containing the job that uses this action to wait is called callee
then the task can successfully wait on caller / callee
. Working example follows.
.github/workflows/caller.yml
on:
push:
jobs:
caller:
uses: ./.github/workflows/callee.yml
.github/workflows/callee.yml
on:
workflow_call:
jobs:
callee:
runs-on: ubuntu-latest
steps:
- name: Wait for Other Workflows
uses: lewagon/[email protected]
with:
ref: ${{ github.ref }}
running-workflow-name: 'caller / callee'
repo-token: ${{ secrets.GITHUB_TOKEN }}
wait-interval: 10
By default, checks that conclude with either success
or skipped
are allowed, and anything else is not. You may configure this with the allowed-conclusions
option, which is a comma-separated list of conclusions.
name: Publish
on: [push]
jobs:
publish:
name: Publish the package
runs-on: ubuntu-latest
steps:
- name: Wait for tests to succeed
uses: lewagon/[email protected]
with:
ref: ${{ github.ref }}
check-name: 'Run tests'
repo-token: ${{ secrets.GITHUB_TOKEN }}
wait-interval: 10
allowed-conclusions: success,skipped,cancelled
...
Similar to the check-name
parameter, this filters the checks to be waited but using a Regular Expression (aka regexp) to match the check name (jobs.<job_id>.name)
Example of use:
name: Wait using check-regexp
on:
push:
jobs:
wait-for-check-regexp:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Wait on tests
uses: lewagon/[email protected]
with:
ref: ${{ github.sha }}
repo-token: ${{ secrets.GITHUB_TOKEN }}
running-workflow-name: wait-for-check-regexp
check-regexp: .?-task
To selectively filter checks and ignore specific ones, you can specify the ignore-checks option with a list of comma-separated check names to be ignored. Example of use:
name: Wait using check-regexp
on:
push:
jobs:
wait-for-check-regexp:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Wait on tests
uses: lewagon/[email protected]
with:
ref: ${{ github.sha }}
repo-token: ${{ secrets.GITHUB_TOKEN }}
running-workflow-name: wait-for-check-regexp
ignore-checks: label1,label2
As it could be seen in many examples, there's a parameter wait-interval
, and sets a time in seconds to be waited between requests to the GitHub API. The default time is 10 seconds.
If true, it prints some logs to help understanding the process (checks found, filtered, conclussions, etc.)
Since we are using Octokit for using GitHub API, we are subject to their limitations. One of them is the pagination max size: if we have more than 100 workflows running, the auto-pagination won't help. More about Octokit auto-pagination can be found here The solution would be to fetch all pages to gather all running workflows if they're more than 100, but it's still no implemented.
There are sample workflows in the .github/workflows
directory. Two of them are logging tasks to emulate real-world actions being executed that have to be waited. The important workflows are the ones that use the wait-on-check-action.
A workflow named "wait_omitting-check-name" waits for the two simple-tasks, while the one named "wait_using_check-name" only waits for "simple-task".