6

TL; DR: Running jobs a,b in parallel. If a fails, stop the execution of b, while it's still running.

My company uses GitHub Actions to deploy our code.

The first step in our deployment is building dockers and pushing them to DockerHub.

We wrote a test for our code, which we want to run in parallel with building the dockers.

Both of these are separate jobs, and we have a few more jobs depending on the success of the first two.

Right now, if the test job fails, the other job continues to run, but obviously, the next one won't run, because the test job failed.

What I would like to do is cancel the docker building job while it's running, if the test failed.

Is that possible? After searching the web, StackOverflow and the GitHub Actions page, I haven't found a way to do that.

Thanks!

Gil Cohen
  • 61
  • 1
  • 2
  • If I understand correctly, the issue with having it run in parallel is that you can deploy code that isn't fully tested (i.e., if it fails after the docker push then it's too late). I think you still want to do them one after another. – astrochun May 11 '21 at 14:49
  • Also it would help to see your GitHub action to see what you've tried. – astrochun May 11 '21 at 14:53
  • Your workflow only has jobs a and b? There's a way to cancel the whole workflow using the API, but I am not sure that's what you want. You can cancel the workflow if something goes wrong with job a, which means job b and the following jobs will also be stopped. – soltex May 11 '21 at 15:07
  • I guess you could separate those 2 jobs in different workflows. Then, if your test workflow failed, you could add a new job to this one that would cancel the other workflow using the [cancel-a-workflow-run](https://docs.github.com/en/rest/reference/actions#cancel-a-workflow-run) service on Github API. – GuiFalourd May 11 '21 at 16:35
  • 1
    Thanks everyone! But this isn't the way we wanted to solve it. Thanks anyway – Gil Cohen May 13 '21 at 06:25
  • @GilCohen Have you solved it? – Bharel Jul 31 '22 at 05:45

3 Answers3

3

You can specify the needs option and refer to the job name. See: https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions#jobsjob_idneeds

An example could be something like:

jobs:
  build:
    ...
  deploy:
    needs: build
    ...
astrochun
  • 1,642
  • 2
  • 7
  • 18
  • 4
    I'm using `needs`, but it would make the second job to wait for the first job to finish, and I want to run both in parallel, and if one fails, to stop the other. – Gil Cohen May 11 '21 at 14:50
  • See my comment above about doing this in parallel. I don't recommend it. You might ship untested code which you would then need to remove. Standard DevOps, in my opinion, will tell you to run your unit and end-to-end tests before shipping it. – astrochun May 11 '21 at 14:52
  • 1
    Thanks for the advice, but we have other jobs after the build and the tests that will prevent bad code from actually deploying. We want to save time by running them in parallel. Thanks anyway! – Gil Cohen May 11 '21 at 14:58
  • I see. The only way I can think of right now to have parallel jobs is to have separate GitHub Action workflow and to build them to depend on one another. I can't provide a complete answer right now but maybe later. Please provide your GitHub action workflows. – astrochun May 11 '21 at 15:10
2

Since you are working on an enterprise project, I would prefer to avoid using unverified actions from public repositories no matter how many stars they have. I think you can add a step to the end of each job a, b. This step will only run if previous steps failed. If it is failed then it will send a cancel-workflow api call.

- if: failure()
  name: Check Job Status
  uses: actions/github-script@v6
  env: 
     RUN_ID: ${{ github.run_id }}
     GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
  with:
     script: |
       const runId = process.env.RUN_ID
       const [owner, repo] = process.env.GITHUB_REPOSITORY.split("/");
       const resp = await github.rest.actions.cancelWorkflowRun({
         owner,
         repo,
         runId
       }) 

Note: You may need to add another custom github_pat since this api-call may require higher permissions than default actions. I also suggest you to take a look at this post , I found it quite useful.

orhunozbal
  • 23
  • 4
1

You can use the Cancel this build action.

The basic idea is to add it as a final step in each of your jobs that you want to cause a short-circuit in case of failure:

jobs
  job_a:
    steps:
      - run: |
          echo 'I am failing'
          exit 1
      - name: Cancelling parallel jobs
        if: failure()
        uses: andymckay/cancel-action@0.2
  job_b:
    steps:
      - run: echo 'long task'

This will basically cancel job_b or any other in the same workflow whenever job_a fails.

robertohuertasm
  • 846
  • 9
  • 17