question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Job-level "if" condition not evaluated correctly if job in "needs" property is skipped

See original GitHub issue

Describe the bug If a job needs a prior job which has been skipped, the if condition for the dependent job may behave unexpectedly under some conditions. (unsure if condition is evaluated incorrectly or if it’s not evaluated at all)

To Reproduce Steps to reproduce the behavior: Given a workflow such as this (where job_b needs to complete or be skipped before subsequent jobs run, but subsequent jobs don’t depend upon any outputs from job_b)

on: push

jobs:
  job_a:
    runs-on: ubuntu-latest
    outputs:
      truthy_string: ${{ steps.a.outputs.always }}
      null_value: ${{ steps.b.outputs.never }}
    steps:
      - id: a
        run: echo "::set-output name=always::something"
      - id: b
        run: echo "We opt not to set any output at this time"
  job_b:
    runs-on: ubuntu-latest
    needs: job_a
    if: needs.job_a.outputs.null_value
    steps:
      - run: echo "We've ensured this job will be skipped"
  job_c:
    runs-on: ubuntu-latest
    needs: [job_a, job_b]
    if: needs.job_a.outputs.truthy_string
    steps:
      - run: echo "This won't run, even though the IF condition evaluates true."
  job_d:
    runs-on: ubuntu-latest
    needs: [job_a, job_b]
    if: always() && needs.job_a.outputs.truthy_string
    steps:
      - run: echo "This will run, even though we've only changed the condition from `true` to `true && true`"

Examining the output of this workflow, job_a will always run, job_b will always be skipped, job_c will always be skipped, and job_d will run. The only difference between job_c and job_d is the addition of always() && to the if condition.

Expected behavior If a job-level conditional evaluates to true, the job should run after all needs’d jobs have completed or been skipped. Both job_c and job_d should run. The always() && should not be required for job_c, since it doesn’t change the ultimate true/false result of the conditional.

OR documentation should be updated to indicate this is expected behavior. The current docks simply says of job needs (emphasis added):

Identifies any jobs that must complete successfully before this job will run. It can be a string or array of strings. If a job fails, all jobs that need it are skipped unless the jobs use a conditional statement that causes the job to continue. This is relatively ambiguous, but the plain interpretation is that a conditional statement that evaluates to true should cause the job to continue. As seen with job_c in the sample, that isn’t always the case.

Runner Version and Platform

Version of your runner? Unsure - I’m only running via Github Actions, not using a self-hosted runner.

OS of the machine running the runner? OSX/Windows/Linux/… Linux: ubuntu-latest

What’s not working?

Jobs are being skipped even when the job-level conditional evaluates to true.

Job Log Output

Because the job is skipped entirely, there is no job-level output, even if the appropriate DEBUG secret is set.

Runner and Worker’s Diagnostic Logs

As above, there is no additional output, even if the appropriate DEBUG secret is set.

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Reactions:125
  • Comments:36 (1 by maintainers)

github_iconTop GitHub Comments

187reactions
andreykaipovcommented, May 29, 2021

In a similar case, I had a conditional job Z I wanted to run at the end of all other jobs A, B, C. However, when any of A, B, or C were skipped, my Z job also got skipped. Adding always() did make it run, but even when the previous jobs failed, so I had to also check the results of my previous jobs:

jobs:
  ...
  Z:
    runs-on: ubuntu-latest
    needs: [A, B, C]
    if: |
      always() &&
      (needs.A.result == 'success' || needs.A.result == 'skipped') &&
      (needs.B.result == 'success' || needs.B.result == 'skipped') &&
      (needs.C.result == 'success' || needs.C.result == 'skipped') &&
      my_original_conditional()
    steps:
    - name: blah
      ...

Very verbose and I’m probably not using workflows as intended, but it works! 😅

35reactions
MetRonniecommented, Nov 12, 2021

I think this meant to be a feature actually, but it’s too subtle in my opinion - it left me scratching my head for an hour over why my workflow step wasn’t running. From https://docs.github.com/en/actions/learn-github-actions/expressions#job-status-check-functions:

A default status check of success() is applied unless you include one of these functions.

I would have expected the default value of if: success() to be replaced with if: <your_condition>, but it’s actually if: success() && <your_condition> unless your condition includes one of the status functions

Read more comments on GitHub >

github_iconTop Results From Across the Web

Github action job fire when previous job skipped
It seems like you encounter this issue - Job-level "if" condition not evaluated correctly if job in "needs" property is skipped.
Read more >
Azure DevOps condition at stage / job level referencing $ ...
The deployment stage references a template and if I put the condition at the job level in the template, the condition is again...
Read more >
A job with needs keyword is run even if ...
In a general way, it happen if a job in a previous stage of a needed one fail, leading it to be marked...
Read more >
Expressions - Azure Pipelines
Expressions are used to define conditions for a step, job, ... If you create pipelines using YAML, then pipeline variables are available.
Read more >
GitLab CI/CD Pipeline Configuration Reference
Define stages in a pipeline. Defines a job stage (default: test ). Limit when jobs are created. Also available: only:refs , only:kubernetes ,...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found