Dependencies Between Workflows on Github Actions
GithubContinuous IntegrationContinuous DeploymentGithub ActionsGithub Problem Overview
I have a monorepo with two workflows:
.github/workflows/test.yml
name: test
on: [push, pull_request]
jobs:
test-packages:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: test packages
run: |
yarn install
yarn test
...
.github/workflows/deploy.yml
name: deploy
on:
push:
tags:
- "*"
jobs:
deploy-packages:
runs-on: ubuntu-latest
needs: test-packages
steps:
- uses: actions/checkout@v1
- name: deploy packages
run: |
yarn deploy
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
...
This doesn't work, I can't reference a job in another workflow:
### ERRORED 19:13:07Z
- Your workflow file was invalid: The pipeline is not valid. The pipeline must contain at least one job with no dependencies.
Is there a way to create a dependency between workflows?
What I want is to run test.yml
then deploy.yml
on tags, and test.yml
only on push and pull requests. I don't want to duplicate jobs between workflows.
Github Solutions
Solution 1 - Github
Now it's possible to have dependencies between workflows on Github Actions using workflow_run.
Using this config, the Release
workflow will work when the Run Tests
workflow is completed.
name: Release
on:
workflow_run:
workflows: ["Run Tests"]
branches: [main]
types:
- completed
Solution 2 - Github
You can (also) do it by combining workflow_run and if.
Using the below config, the deploy
workflow will start only when all of these conditions are true:
- after the
test
workflow is completed, - if the
test
workflow was successful, Tere was a tag pushed to the default branch,
Assuming that the default branch is main
:
name: deploy
on:
# the 1st condition
workflow_run:
workflows: ["tests"]
branches: [main]
types:
- completed
jobs:
deploy-packages:
# the 2nd condition
if: ${{ github.event.workflow_run.conclusion == 'success' }}
(...)
....BUT unfortunately the 3rd condition cannot be checked this way as the deploy
workflow is triggered in a context of the HEAD of the default branch, without the knowledge about the tag that may be pointing there.
So doing something like:
if: ${{ github.event.workflow_run.conclusion == 'success' }} && startsWith(github.ref, 'refs/tags/') }}
...will NOT work.
I will update this answer when I find out the workaround for this issue.
Solution 3 - Github
This is possible with a combination of workflow_call
and needs
. Adding workflow_call
to the on
values of a job allows it to be called by other jobs. You can then call that job from the other workflow, and use needs
to force future steps to depend on the success of that job. You can read about making workflows callable here: https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#onworkflow_call and requiring a step to succeed before triggering future steps here: https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idneeds
So for your case, the following should work:
# cat .github/workflows/tests.yml
name: tests
on: [workflow_call] # allow this workflow to be called from other workflows
jobs:
...
# cat .github/workflows/deploy.yml
name: deploy
on:
push:
tags: # trigger the deploy job on tag creation
- *
jobs:
tests:
uses: ./.github/workflows/tests.yml # use the callable tests job to run tests
deploy:
name: deploy
needs: [tests] # require tests to pass before deploy runs
...
Solution 4 - Github
It seems that the Wait n Check action is currently the optimal workaround for this missing feature, as it declares in its README:
> It allows to work around a GitHub Actions limitation of non-interdependent workflows (we can only depend on jobs inside a single workflow).
UPDATE: see also my other answer for a partial solution using workflow_run
.
Solution 5 - Github
You can create reusable workflows: https://docs.github.com/en/actions/using-workflows/reusing-workflows.