Reputation: 1139
I'm trying to find a way to achieve the following functionality: Whenever a step fails, it will show that it failed (will provide correct feedback) but will still continue to other steps.
At the moment, failure causes the step to stop:
I've seen the most popular suggestion is to use continue-on-error, but that seems to make the step's conclusion 'Success', and will not show it failed unless you go into the logs.
In the screenshot above, the "Secrets" step failed, and yet it appears to be successful unless entering the logs.
When reading this thread, I came to suspect this feature might not exist yet in GH actions.
I've also tried using conditionals for each step, and/or for the job.
For example, I've tried:
if: ${{ success() }} || ${{ failure() }}
- this simply did not provide the needed functionality, the step failed and the next step did not start.
if: succeeded() || failed()
- took this syntax from the GitHub community thread above, but it generated a syntax error (which makes sense, since it isn't compatible with the syntax specified here).
To conclude, I'm looking for a way to make steps that fail indicate they failed, and still make the workflow continue to the next step.
Upvotes: 74
Views: 64775
Reputation: 7164
You can use if: {{ !cancelled() }}
on the steps you want to continue to run and perhaps include an extra condition if there is something like an install step that is still critical e.g.:
jobs:
lint-and-format:
runs-on: ubuntu-24.04
steps:
- name: Install linting and formatting dependencies
id: install
run: |
npm install eslint prettier
- name: Lint JavaScript files
if: ${{ !cancelled() && steps.install.conclusion == 'success' }}
run: |
npx eslint
- name: Check JavaScript formatting
if: ${{ !cancelled() && steps.install.conclusion == 'success' }}
run: |
npx prettier -c .
(As the runs.steps[*].if
documentation warns the !
in !cancelled
must be contained in {{}}
/ ''
/ ""
/ ()
because it's reserved YAML notation)
if: {{ !cancelled }}
is preferable to
if: always()
because if your task has a critical failure it can stop early rather than being forced to run until the timeout. The GitHub documentation for always()
even recommends {{ !cancelled }}
):
Avoid using
always
for any task that could suffer from a critical failure, for example: getting sources, otherwise the workflow may hang until it times out. If you want to run a job or step regardless of its success or failure, use the recommended alternative:if: ${{ !cancelled() }}
continue-on-error
within a step because if the step fails it will not cause the job to still be considered successful (see this comment about continue-on-error
within a job vs within a step)if: {{ success() || failure() }}
because it means the same thing and is shorterSee the answers on How to run a github-actions step, even if the previous step fails, while still failing the job for further discussion of different approaches.
Upvotes: 0
Reputation: 11
I would suggest you take a look to this discussion solution. I was trying to do something similarly related: Running a step (discord notification) whenever the build fail AND avoiding the subsequent steps from running (failing the job altogether).
In my code workflow:
simple_deployment_pipeline:
runs-on: ubuntu-20.04
steps:
... some previous steps
- name: build
id: buildStep
run: npm run build
- name: Discord notification if build fails
if: ${{ failure() && steps.buildStep.outcome == 'failure'}}
...do something
It is similar to your solution but missing the part where, besides checking the failure of the step until that point, it checks the step's outcome.
If the job fails, correct feedback is returned (check the image link)
Hope that helps!
Upvotes: 1
Reputation: 5229
The continue-on-error
is indeed popular, and part of the reason is perhaps that you can set it for each step, or for the whole job. I’m not sure you are aware of this, and this solution was the answer I was looking for.
This will continue all steps, if either fails:
Job:
MyRun:
runs-on: ubuntu-latest
continue-on-error: true
steps:
- name: Step One
run: curl --fail -o dates.csv https://doesnotexist.com/dates.csv
- name: Step Two
run: date >> dates.csv
This will only continue if “Step One” fails, it will break and stop if e.g. “Step Two” fails:
Job:
MyRun:
runs-on: ubuntu-latest
steps:
- name: Step One
run: curl --fail -o dates.csv https://doesnotexist.com/dates.csv
continue-on-error: true
- name: Step Two
run: date >> dates.csv
NOTE: If you have a failing build step it depends on where you put continue-on-error whether you get a red or green icon for that failed job:
continue-on-error: true
in the job's metadata, you'll get a red icon (Example 1)Upvotes: 35
Reputation: 16081
Just in case this helps someone else, and because I struggled to find the right answer to this myself.
It turns out the answer is sort of staring you in the face, but it's just confusing because of the way the documentation phrases things, I think.
But, in short, all you need to do is set
strategy:
fail-fast: false
at the top level. there is no need to set continue-on-error
at each step, that's a distraction.
Upvotes: -2
Reputation: 2473
Just adding on to this old conversation:
The behavior has changed. My job marked with continue-on-error: true
does show a "failure" icon, not a faux "success" icon. The workflow continues on afterward.
If a job punts to an external workflow via uses:
, the continue-on-error
must go in the jobs in the external file. It cannot go on the job in the main workflow.
That is, the following gives a syntax error:
jobs:
my_continue_on_error_job:
uses: ./.github/workflows/other_workflow.yml
continue-on-error: true
It fails with:
The workflow is not valid. .github/workflows/main_workflow.yml (Line: 201, Col: 5): Unexpected value 'continue-on-error'
It worked when I moved the continue-on-error
into the jobs in the other_workflow.
Upvotes: 12
Reputation: 1139
To my surprise, and thanks to @smac89 for suggesting it - adding if: always()
seems to do the trick.
I'm still wondering why if: ${{ success() }} || ${{ failure() }}
failed, but the solution seems to work for the moment.
Thank you for the help!
Upvotes: 39