runner icon indicating copy to clipboard operation
runner copied to clipboard

Jobs skipped when NEEDS job ran successfully

Open niekvanderreest opened this issue 3 years ago • 30 comments

Describe the bug One or more jobs are skipped in a workflow when run after successfully running a job matching following conditions:

  • Job has NEEDS dependency on one or more preceding jobs. (i.e. needs: [job1, job2])
  • Job has if condition specifying behavior when NEEDS jobs are skipped. (i.e. if: always() && needs.job1.result == 'skipped')
  • Preceding job is skipped (i.e. job1)

To Reproduce Create a workflow as follows:

name: Skipped Job Test

on:
  workflow_dispatch:
  
jobs:
  Skipped-Job:
    name: skipped job
    runs-on: [self-hosted]
    if: 1 != 1
    steps:
    - name: write to console 1
      run: Write-Host "I should be skipped"

  Needs-Job:
    name: needs conditional job
    needs: Skipped-Job
    if: always() && needs.Skipped-Job.result != 'failed' # this should run eventhough needs the skipped-job
    runs-on: [self-hosted]
    steps:
      - name: write to console 2
        run: Write-Host "Needs-Job completed"
  
  Next:
    name: Next job
    needs: Needs-Job
    # if: always() && needs.Needs-Job.result == 'success' # uncommenting this condition causes the job to not be skipped
    runs-on: [self-hosted]
    steps:
      - name: write to console 3
        run: Write-Host "I should print whenever Needs-Job succeeds"

Expected behavior I'd expect the job "Next" to run, because the preceding job " Needs-Job" is completed successfully and is the only condition for this job to run (it needs Needs-Job), it is however skipped. uncommenting the 3rd line in that job is a fix, but this feels hacky and shouldn't be needed.

Runner Version and Platform

Current runner version: '2.298.2'

Running on: Windows Server 2022 Standard Version 21H2 OS build 20348.1006

niekvanderreest avatar Oct 14 '22 12:10 niekvanderreest

I believe the status is the wrong word - try ‘failure’ instead of ‘failed’.

GennaroGreg avatar Nov 02 '22 19:11 GennaroGreg

Hi @GennaroGreg,

Thanks for the reply, the status 'failed' might indeed be the wrong word, however it shouldn't matter for job "Needs-Job" as the check is if it's not equal to, and since "Skipped-Job" is always skipped the status will always be 'skipped' (right?)

I've tested just to be sure: skipped-job-failure

niekvanderreest avatar Nov 22 '22 09:11 niekvanderreest

I'm having a similar problem. Where a job earlier in the chain is skipped causes all down stream jobs to be skipped even if they don't explicitly state that they need that job to continue.

Following pseudo code demonstrates what I'm seeing.

jobs:
  get-semaphor:
    runs-on: ubuntu-latest
    steps:
       - name: get-some-semaphor
       - run: echo "semaphor=false" >> $OUTPUT
       
  check-semaphor:
    runs-on: ubntu-latest
    needs: get-semaphor
    if: needs.get-semaphor.output.semaphor == true
    steps:
      - name: Do something here
      
  do-task-a:
    runs-on: ubntu-latest
    needs: ['check-semaphor', 'get-semaphor'] 
    if: alsways && (needs.check-semaphor.result == skipped || needs.check-semaphor.result == success) && needs.get-semaphor.result == success
    steps:
      - name: do something

  # This task-b will never run if check-semaphor is skipped or fails. Even though A succeeds. 
  do-task-b-aslong-as-a-works:
    needs: do-task-a
    steps:
      - name: do something

DameonSmith avatar Dec 08 '22 21:12 DameonSmith

@DameonSmith IIRC you'd need to add if: always() && needs.do-task-a.result == success in this case. Once a job in the workflow is failed or skipped, you need to overwrite the conditional for all subsequent jobs...

mulhotavares avatar Jan 13 '23 15:01 mulhotavares

Hi @mulhotavares, thanks for the comment, I do know this works but I consider it a workaround. I could be wrong however and this could be intended behavior, do you perhaps have a link to Github documentation that explains this as intended behavior?

It feels like a bug that the run condition on job A would impact job C that has no condition on the skipped job (only on job B which is run and successful)

niekvanderreest avatar Jan 17 '23 08:01 niekvanderreest

Hi @niekvanderreest. In terms of the documentation, I haven't found that mentioned directly, but the docs do state:

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

And

success Returns true when none of the previous steps have failed or been canceled.

(both quotes from this: https://docs.github.com/en/actions/learn-github-actions/expressions#job-status-check-functions)

So it is respecting both of those statementes, but I agree this looks awkward. Anyways, I was just trying to help, especially as others could find this in Google like I did. 😄

mulhotavares avatar Jan 17 '23 14:01 mulhotavares

Experienced this as well. Unless explicitly documented, this feels like a bug. Current behavior is unintuitive as well as cumbersome to develop, since one has to push the if clause to all descendent jobs just because of one skipped ancestor.

ywilkof avatar Jan 20 '23 09:01 ywilkof

This is really weird behaviour. As noted here this definitely seems to be a bug (why are we all just running into this now? did everyone suddenly decide to use job ifs?).

A job being skipped seems to be treated as failed, so success() doesn't work for follow on jobs. As documented in the discussion, you should instead use ! failure() which works a treat, but you then have to propagate it to all descendant jobs even if they don't directly depend on the skipped job, which is very confusing.

You should fix success() to not include skipped jobs, as skipped really should mean "this wasn't needed", not "this failed". And needs checks should only occur on the explicitly listed jobs, not ancestors of those jobs.

kgreav avatar Jan 23 '23 10:01 kgreav

I have a workflow skips or cancels as soon as it is executed

jjoseph456 avatar Jan 23 '23 20:01 jjoseph456

@jjoseph456 , I think your workflow has an execution order issue, the first job has a needs specifying the second job. Switching position of first and second job should fix this.

I'm no expert at this field, most of the workflow I worked on have a strict order of execution.

niekvanderreest avatar Jan 23 '23 20:01 niekvanderreest

@niekvanderreest thanks will try that

jjoseph456 avatar Jan 23 '23 21:01 jjoseph456

I'm having a similar problem. Where a job earlier in the chain is skipped causes all down stream jobs to be skipped even if they don't explicitly state that they need that job to continue.

Following pseudo code demonstrates what I'm seeing.

jobs:
  get-semaphor:
    runs-on: ubuntu-latest
    steps:
       - name: get-some-semaphor
       - run: echo "semaphor=false" >> $OUTPUT
       
  check-semaphor:
    runs-on: ubntu-latest
    needs: get-semaphor
    if: needs.get-semaphor.output.semaphor == true
    steps:
      - name: Do something here
      
  do-task-a:
    runs-on: ubntu-latest
    needs: ['check-semaphor', 'get-semaphor'] 
    if: alsways && (needs.check-semaphor.result == skipped || needs.check-semaphor.result == success) && needs.get-semaphor.result == success
    steps:
      - name: do something

  # This task-b will never run if check-semaphor is skipped or fails. Even though A succeeds. 
  do-task-b-aslong-as-a-works:
    needs: do-task-a
    steps:
      - name: do something

having the same issue, once always() used in job1, the next job that needs it will not be executed even if the job1 succeeds

povisenko avatar Jan 27 '23 12:01 povisenko

I'm having the similar problem, can someone help?

name: Release
on:
   push:
      branches:
         - main
   pull_request:
      branches:
         - main
      type: [closed]
jobs:
   release:
      if: github.event.pull_request.merged == true
      name: Release
      runs-on: ubuntu-20.04
      steps:
         - name: Checkout source code
           uses: actions/checkout@v3
         - name: Cache node_modules
           uses: actions/cache@v2
           with:
              path: ~/.npm
              key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
              restore-keys: ${{ runner.os }}-node-
         - name: Install the dependencies
           run: npm ci --legacy-peer-deps
         - name: Run release
           run: npm run release --ci
         - name: End message
           run: echo "All done!"

Jonath-z avatar Apr 21 '23 15:04 Jonath-z

Hello, I had the same problem. The workaround proposed by @mulhotavares is working, but I agree with @niekvanderreest saying this is a workaround and should be solved.

The documentation says that a success() condition is applied by default, and that this function Returns true when none of the previous steps have failed or been canceled. --> so it should return true when the job is skipped.

Moreover, the uses of success() and needs.job-id.result == success are inconsistent, because success() can return false when needs.job-id.result == success returns true, wherease it looks like the same meaning. See below :

  # This is working : the job3 is executed
  job3:
    needs: [job1, job2]
    if: always() && (needs.job1.result == 'success' || needs.job2.result == 'success')

versus

  # This is not working : the job3 is skipped (documentation says that a success() function is applied by default
  job3:
    needs: [job1, job2]
    if: (needs.job1.result == 'success' || needs.job2.result == 'success')

gcharondkt avatar May 04 '23 09:05 gcharondkt

Hello, does anyone have any news on this subject?

a-audusseau avatar Dec 11 '23 17:12 a-audusseau

Any news on this?

igorcezar avatar Mar 25 '24 23:03 igorcezar

FWIW, I have found that it works well to use an if statement like the following for all jobs that are dependent, either directly or indirectly, on one or more jobs that may be skipped:

if: ${{ !failure() && !cancelled() }}

OldSneerJaw avatar Jun 07 '24 23:06 OldSneerJaw

I've had some success working around this by using sub-workflows, move the optional job into the sub-workflow and then the main workflow can use the needs as normal and not need the horrible if conditions on all subsequent jobs. The jobs in the sub-workflow still need the if statements on subsequent jobs but it can still reduce the amount needed depending on your workflows. I think the sub-worlflow still needs at least on successful (not skipped) job to run within it but I've not tested this

rob1256 avatar Jun 10 '24 12:06 rob1256

I cannot believe this is still an active issue. I just ran into this again.

mw-root avatar Jul 08 '24 20:07 mw-root

any solutions for this yet apart from introducing sub-workflows? the if conditionals are becoming even more inflated if there are multiple jobs that can be potentially skipped..

rrashi avatar Jul 17 '24 20:07 rrashi

Bumping up for visibility as I ran into a similar issue today and came here searching!

sarthak-mnscorp avatar Jul 30 '24 16:07 sarthak-mnscorp

I ran into this today and it's really annoying.. i'm coming across strange characteristics of gh actions more and more often...

mrclrchtr avatar Aug 02 '24 17:08 mrclrchtr

I'm having the same problem here, we haven't had any updates on this yet?

fbmaya avatar Aug 07 '24 03:08 fbmaya