Depend on another workflow

Is it possible for a workflow to depend on another workflow?

We currently have two workflows. test and deploy.

Currently, the test workflow is responsible for testing the code base. The deploy workflow is responsible for testing, building and deploying the code base.

The test workflow runs on any push to all branches.

The deploy workflow only runs from a push on the master branch.

The current setup has two negative side effects. 1) we have to duplicate the test steps in both the test and deploy workflow. 2) when pushing to master the test steps get run twice. Once in the test workflow and once in the deploy workflow.

If would be great if there was a way to only run the deploy workflow if the test workflow was successful. Eliminating the requirement of duplicating steps between workflows and testing the code base twice.

24 Likes

I believe the intent in GH Actions is to use _jobs_ for this purpose rather than workflows.

e.g., one ci.yml workflow that contains jobs for building, testing, deploying, etc.

To that end, it would be great if jobs could be factored out into stand-alone files as parameterized templates.

4 Likes

Yes, this is possible. Assuming that you have enabled protection settings on your master branch to only allow merging pull requests whenever your CI workflow has run successful, you can create a secondary workflow that only triggers when the pull request is merged (because by then you already know the tests succeeded).

So you could have a CI workflow like:

---
name: CI

on:
  pull_request:
    branches:
      - master

jobs:
  test:
    runs-on: ubuntu-latest

    steps:
      - <YOUR TEST STEPS HERE>
...

Then, create a secondary workflow (let’s call it deploy) that only runs when the PR was merged. By default, actions are not run when a PR is closed, unless you specifically request this with the types condition in your on clause, so the CI workflow will not trigger, but this one will:

---
name: Deploy

on:
  pull_request:
    types: [closed]
    branches:
      - master

jobs:
  deploy:
    runs-on: ubuntu-latest
if: github.event.pull_request.merged

    steps:
      - name: checkout
        if: github.event.pull_request.merged
        uses: actions/checkout@v1
with:
ref: master

- <YOUR DEPLOY LOGIC HERE>

The:

if: github.event.pull_request.merged

condition on the job makes sure that it is only run when the PR was actually merged (rather then being closed without merging).

16 Likes

Is the latter if (the one under steps) actually necessary?

Yes, because you can close a PR without merging it I guess

This would require the second workflow to re-run build + all tests. I’d need the artifacts generated by the previous workflow and only deploy there, not having to run the whole thing again

1 Like

I am also looking for this. Would be nice if we could use on in a specific *job* (as opposed to the whole workflow), so e.g. the deploy job could run after the build job, but only when it was a merge to master.

@ianaz I found this which seems to help: https://stackoverflow.com/questions/58139406/only-run-job-on-specific-branch-with-github-actions

tl;dr use if condition in job

if: github.ref == 'refs/heads/master'

Hi :wave:

We’re in a similar situation now. I was here to ask the same question, then found this thread.

We have 4 workflows:

  • commit-stage (sanity-check, lint, unit-tests, coverage): runs on every commit
  • build-stage (startup, build, preview-deployment, integration-tests, functional-tests, teardown): runs on new pull requests to master
  • deploy (build, deploy, smoke-test): runs on every new commit to master (basically after pr’s merged)
  • release (build, deploy): runs when there’s a new release/tag

As you can see, every step highly depends on the previous steps to be done completely, to move forward. But since we cant use needs to point to another workflow, we need to duplicate most of the jobs and steps in every file, we need to add unnecessary ifs here and there, and in the end, it’ll take a lot more effort to keep them maintained and sync.

We can put them all in one workflow, that listens to commit, pull_request, release events, and use needs to at least make them depend on each other, but again, we need to somehow limit their scopes with ifs and with maybe other checks.

What I was thinking was, in build-stage.build for example, it’d be great to use something like needs: [ 'commit-stage.unit-tests' ] so that it goes up to the workflows folder, finds commit-stage.yml (part comes before .) then goes in there and finds unit-tests. Not sure if logistically this is possible (considering action workspace and all) but that’d definitely make dependencies more powerful and help with a nicer/leaner workflows.

I hope this makes sense, thanks in advance!

15 Likes

@gokaygurcan ++ to your comment
This feature is needed when companies migrating from other CI - CD systems
Right now this is how i maintain the workflows

example:

every app repository:
       .github/workflow/dispatch_event.yaml
       each app repo custom payload ex:{ github.sha, github.ref ,  }
       POST the payload to the centralized_repo
centralized_repo_structure:
       .github/workflow/seed.yaml
                    - clone repository that dispatched the event
                    - some payload checks 
                    - start jobs-setup.sh 
       scripts/jobs-setup.sh (Setting some flags like {"rebuild": true , "environment": [dev,stg,prod], "deploy": [true,false] })
      and some more scripts like versionBump , build_docker, build_helm, deploy and some more.
      those scripts all are depends on every step inside the seed.yaml
                  

So , everything is maintained in the same file .
Some day it will be chaos to maintain it .

is there any feature in future that will enable it?

Thanks in advance .

Is it maybe possible to use some kind of sunrise hook that runs before other workflows are parsed to create the workflows? In this way the workflow files can be built on the fly right before they are parsed and run. Something like this:

run: |
cat test-header >> test.yml
cat test-steps >> test.yml
cat test-footer >> test.yml

run: |
cat deploy-header >> deploy.yml
cat test-steps >> deploy.yml
cat deploy-steps >> deploy.yml
cat deploy-footer >> deploy.yml

Any thoughts?

It would be possible to use for example the git tool husky to create these workflow files before pushing.

@milesrichardson and @ianaz,

You can upload an artifact in the CI workflow and then download workflow artifact in the Deploy pipeline using these actions


Only thing I don’t like about using this with what oldskool is proposing is that the ci artifact downloaded in the deploy on pull request merge is coming from a development branch, not master

yea… looks like doing CI builds again in the deploy workflow is the way to go.

or just putting CI and deploy in the same workflow using what @milesrichardson is proposing

here’s one way I’ve done it with Terraform. Please bear with me as I’m still developing it and converting from nodejs to powershell. Nonetheless, the CI/CD workflow is working well.

I use a wait for continuous integration to succeed check in the deploy pipeline.