223

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.

5 Answers 5

231

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
7
  • 176
    It's important to know that the Release workflow in your example will run whenever the Run Tests workflow completes, regardless of whether it succeeds or fails. You need to inspect github.event.workflow_run.conclusion if workflow outcome is important (which is usually is). More details here: github.community/t/… Commented Dec 8, 2020 at 19:49
  • 4
    Can we give two workflow names in workflows? I have to trigger this after completion of two other workflows. Commented Oct 11, 2021 at 9:11
  • 1
    @lakshmiravalirimmalapudi You can give two names, but that only means that it will trigger when either of those workflows completes, not when both of them complete. Commented Sep 9, 2022 at 19:27
  • 7
    To anyone looking to use this, it only runs on the default branch and not the branch that actually triggered the workflow that this one depends on ( see notes about this here ) Commented Feb 3, 2023 at 18:37
  • 1
    @DaveJohansen So to be clear, even if "Run Tests" was run on a branch (created for a PR, and assuming there were no branches: filter in the above), the "Release" workflow is run from main/master/etc.?
    – Brian
    Commented Mar 13, 2023 at 17:12
125

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 in the "Reusing workflows" docs and requiring a step to succeed before triggering future steps here.

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
    ...
4
  • 6
    This is a great solution. Very clean, and in my opinion, the solution. Especially as this will stop other steps from running Commented Dec 8, 2022 at 7:07
  • 3
    Beware, secrets and params are not automatically forwarded. You can use and the magic secrets: inherit syntax at the same level as uses:. Refer to docs.github.com/en/actions/using-workflows/… Commented Apr 28, 2023 at 14:50
  • The drawback to this approach is that workflows included by other workflows like this will not get an entry in their respective workflow run logs, but only in the logs of the calling run.
    – Appleshell
    Commented May 19, 2023 at 15:30
  • 1
    That's good, why would you want to click multiple different workflows in the left pane of the actions tab, rather than click your triggering workflow and looking at the status of individual jobs?
    – miigotu
    Commented Oct 19, 2023 at 0:57
50

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:

  1. after the test workflow is completed,
  2. if the test workflow was successful,
  3. There 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.

8

The Wait n Check action is a 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.

3
  • That action just seems to wait like a timeout and not actually waiting on a workflow finishing before letting the succinct jobs starting. Commented Apr 10, 2021 at 17:26
  • @MaxieBerkmann It does wait for another workflow to finish. But it does it by repeatedly checking on some interval to see if the job has finished, which is why you see wait-interval as an option. Commented Sep 9, 2022 at 19:31
  • 1
    It looks that the project is searching for new maintainers: github.com/lewagon/wait-on-check-action/issues/83
    – xonya
    Commented Oct 19, 2023 at 8:07
5

You can accomplish this without any third party tools using reusable workflows

example:

Create a workflow under .github/workflows called callable.yml

callable.yml:

  on:
  workflow_call:

  jobs:
    some_job:
      runs-on: ubuntu-latest
      name: some_job

Then call it from a main workflow (we'll call it ci.yml for this example)

ci.yml:

name: Call a reusable workflow

on:
  pull_request:
    branches:
      - main

    jobs:
      call-workflow:
        uses: ./.github/workflows/callable.yml

the ./.github/ notation is used to indicate a local workflow, but you can use them from other repos as well.

More details found in the docs:

https://docs.github.com/en/actions/using-workflows/reusing-workflows

2

Not the answer you're looking for? Browse other questions tagged or ask your own question.