Github Actions - CI/CD - Need optional jobs

I have an extremely common CI workflow, that I already implemented in some repositories with Gitlab CI, Bitbucket pipelines, Travis and Circle CI, and I can’t find ways to represent it with Github Actions:

* When I push to any branch it executes a bunch of unit tests. (That can easily be represented by a job)

* When I create a tag it should also do the same thing and, if all tests succeed, it should deploy the project (to NPM as example).

With most CI system it would simply be some config that says “only execute this job if we are on a tag” but it doesn’t seem to be possible with Github Actions. Or maybe I’m wrong and in that case please tell me.

So, does any one have a solution about this ?

Just for info here are a few solutions I thought about to implement that workflow that would not be satisfactory:

* Define two different workflows, one for normal branches and one for release: That would seem to be a very bad solution. First I would need to create two conditions regarding workflow triggering for those workflows to be mutually exclusive and the documentation about workflow triggering conditions is so bad currently that I’m not even sure it’s possible. Second that mean I would have to copy-paste my testing job to multiple workflows (as far as I know there is no way to share a job accross multiple workflows)

* Use step conditions (AKA “if”): Doesn’t seem to be a good idea. Here there are clearly different jobs that should be triggered or not depending on the situation.

* Try to use actions: Seems even worse. Actions seems to be designed as reusable pieces of code that do one thing, not non-reusable-project-dependant complete tasks.


Some issue for me. This could be solvable by allowing “if” conditions at the job level and not only at the step level.


Same issue here. Having the same if syntax on the job level would cut down on the number of workflows that we need to create or having the same if on almost every single step just to exclude the job from running.

Super simple use case: we have Unit tests, Integration tests and Style linting happening each in a separate job on the same workflow to parallelize the execution. When my workflow is triggered via a pull_request, I don’t want the Style linting to run on the PR workflow but I do want it run on the Push workflow.

My only options currently are:

  1. Have two separate workflow files, one that listens to push and one that listens to pull_request but with 90% the same content duplicated.

  2. Copy and paste the same if line under every step in the job I don’t want to run and keep a single workflow file.

1 Like

Exactly the same setup here and hence the same issue. I noticed that it is actually possible to put “if:” on a job, but i have yet to make it work with anything except constants (ie true/false) :frowning:

You mention that you can do this on “if:” on a step, but i have not had much success with expressions in the “if” on step either?

I didn’t saw that you can put an if on jobs according to the documentation:

That would solve the problem as using if on steps is really not the solution for such a problem, both practically and conceptually (the only sane way to make a conditional deployment is to make a conditional job for it).

Also, I agree that making an if condition on a tag, even for steps, is not super easy. I found a way that should work but I almost had to make some reverse engineering to do so.

Same as this issue?

The guy that posted that had initially kind of the same problem. Except it seems like he solved it in a terrible way.

He just defined multiple workflows which is not a proper solution as there is no way to define that the “deploy” job must be executed only if the previous “build & test” job was successful. And that’s precisely what we want to do 99,9% of the time in a CI.


I was just able to get IF working at the job level. I may be crazy, but I could have sworn that I attempted this very thing before and I got a syntax error on the Workflow file saying it wasn’t supported at this level.

Both of the following work as expected and the entire job doesn’t even show in the workflow if the conditions are not met while the rest of the workflow runs as normal:


name: Unit tests
runs-on: ubuntu-latest

    if: contains(github.ref, 'development') || contains(github.ref, 'master')
    name: Integration tests
    runs-on: ubuntu-latest

    if: github.event_name != 'pull_request'
    name: ESLint
    runs-on: ubuntu-latest

Also tested this in my workflow and yes. It seems to be working as expected

Looks to be officially documented now too:

Kudos to the documentation team … these docs have been looking really good lately. Much easier to dig in as we start making more advanced workflows!