How to run a github-actions step, even if the previous step fails, while still failing the job

GithubGithub Actions

Github Problem Overview


I'm trying to follow an example Github has for testing my build with github actions, and then compressing the test results and uploading them as an artifact. https://help.github.com/en/actions/automating-your-workflow-with-github-actions/persisting-workflow-data-using-artifacts#uploading-build-and-test-artifacts

I'm having trouble with what to do when my tests fail though. This is my action. When my tests pass everything works great, my results are zipped an exported as an artifact, but if my tests fail, it stops the rest of the steps in the job, so my results never get published.
github-ci-result
I tried adding the continue-on-error: true https://help.github.com/en/actions/automating-your-workflow-with-github-actions/workflow-syntax-for-github-actions#jobsjob_idstepscontinue-on-error
This makes it continue after it fails and uploads my test results. but then the job is marked as passed, even though my test step failed. Is there some way to have it upload my artifact even if a step fails, while still marking the overall job as failed?

name: CI
on:
  pull_request:
    branches:
    - master
  push:
    branches:
      - master
      
jobs:
  build-and-test:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v1    
    - name: Test App
      run: ./gradlew test

    - name: Archive Rest Results
      uses: actions/upload-artifact@v1
      with:
        name: test-results
        path: app/build/reports/tests

Github Solutions


Solution 1 - Github

You can add

if: always()

to your step to have it run even if a previous step fails https://help.github.com/en/actions/automating-your-workflow-with-github-actions/contexts-and-expression-syntax-for-github-actions#job-status-check-functions

so for a single step it would look like this:

steps:
- name: Build App
  run: ./build.sh

- name: Archive Test Results
  if: always()
  uses: actions/upload-artifact@v1
  with:
    name: test-results
    path: app/build

Or you can add it to a job:

jobs:
  job1:
  job2:
    needs: job1
  job3:
    if: always()
    needs: [job1, job2]

Solution 2 - Github

Other way, you can add continue-on-error: true. Look like

- name: Job fail
  continue-on-error: true
  run |
    exit 1
- name: Next job
  run |
    echo Hello

Read more in here.

Solution 3 - Github

Addon: if you have following sitution. 2 steps i.e. build > deploy and in some cases i.e. workflow_dispatch with input parameters you might want to skip build and proceed with deploy. At the same time you might want deploy to be skipped, when build failed.
Logically that would be something like skipped or not failed as deploy conditional.
if: always() will not work, cause it will always trigger deploy, even if build failed.
Solution is pretty simple:
if: ${{ !failure() }}
Mind that you cannot skip brackets when negating in if:, cause it reports syntax error.

Solution 4 - Github

you can add || true to your command. example:

 jobs:
  build-and-test:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v1    
    - name: Test App
      run: ./gradlew test || true

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionTomer ShemeshView Question on Stackoverflow
Solution 1 - GithubTomer ShemeshView Answer on Stackoverflow
Solution 2 - GithubKhai VuView Answer on Stackoverflow
Solution 3 - GithubshemekhView Answer on Stackoverflow
Solution 4 - GithubPawan JenuView Answer on Stackoverflow