Run job always but only after all others completed

I want to run my End-to-End tests, but have to setup the database first and teardown after. I have 3 jobs:

  • Setup
  • Test
  • Teardown

The order matters of course, so I want the Setup to run first and Test after that, but I want Teardown to always run once Test has completed, whether that is a success, failure, skipped or cancelled.

I thought I had this doing:

jobs:
  setup:
    name: Environment Setup
    runs-on: ubuntu-latest
    steps:
      - name: Setup the state
        run: |
          echo "Setting up the state"
          sleep 5
          cat red

  test:
    needs: [setup]
    if: success()
    name: Cypress Tests
    runs-on: ubuntu-latest
    steps:
      - name: Test
        run: |
          echo "Testing"
          sleep 5

  teardown:
    needs: [test]
    if: always()
    name: Environment Teardown
    runs-on: ubuntu-latest
    steps:
      - name: Teardown
        run: |
          echo "Tearing down the state"
          sleep 5

What I’m seeing though, setup starts and on failure, both test and teardown are being run in parallel, which I was not expecting. Can anyone explain why and possibly suggest what I need to do.

Thanks in advance for any pointers.

Mark

The documentation has an example where the third job depends on both, the first and second job:

Logically, I would expect the teardown to be started only after test finished with just needs: [test]. But maybe that isn’t the case and needs: [setup, test] is required for some reason?

Could it be related to always()? Might it trigger the job early unless you explicitly wait for both other jobs?

@marksmall,

What I’m seeing though, setup starts and on failure, both test and teardown are being run in parallel

I don’t think they were running in parallel, because the test job was skipped and never started to run. The problem should be that the displayed status of the test job on the web UI was not refreshed in time with the latest status.

About the two configurations below:

jobs:
  job1:
  job2:
    needs: [job1]
  job3:
    needs: [job2]
jobs:
  job1:
  job2:
    needs: [job1]
  job3:
    needs: [job1, job2]

For the order of jobs execution, the two configurations will cause the same order: job1 > job2 > job3. They are not different for the order of jobs execution.

1 Like

Thanks for this.

I had considered both your points, but couldn’t find any proof. Others thinking along similar lines gives me more confidence. Removing the always though, skips the teardown, so that isn’t the way to go. I’m leaning more towards the UI display not updating quickly enough right now though as eventually I do see the following status:

status

@marksmall,

Keeping always() here is OK, if you want the teardown job to be executed always.
The tests job is skipped, so it should not make too much effect.