The following example shows a command used to set an environment file, using a command of false
to simulate a command error situation that returns a non-zero exit code.
Is there a simpler way to fail the action for this failure scenario? Or a better technique when combining a call to a command that could fail whose output is needed for a later step?
name: Failure in Command Test
on:
workflow_dispatch:
jobs:
test:
steps:
- name: Failure during env var set
run: |
echo "command_output=$(false)" >> "$GITHUB_ENV"
if [[ -z "$command_output" ]];then echo "::error ::Error calling command" && exit 1; fi
If the echo
command fails to write to the file in $GITHUB_ENV
, it returns an exit code of 1. That would cause the step
to return failure and the parent job
to also complete with a failure. The lines of code after that would not run.
In your example, the subprocess -- $(false)
-- fails and returns an exit code. However, that exit code is swallowed by the echo
; it's just capturing the output. The echo
step then writes the empty response to $GITHUB_ENV
:
> cat $GITHUB_ENV
command_output=
$GITHUB_ENV
only sets the environment values for subsequent steps, so that variable is not available for the if
.
To get the error code from the subprocess, you can assign the output to a variable. If that subprocess fails, the exit code will be returned. A failure would halt the script automatically, while success would allow the script to continue to the next line.
The revised code:
command_output=$(false)
echo "command_output=${command_output}" >> "$GITHUB_ENV"
In this case, you'll get an error from the $(false)
. That will halt the script (and make the step and job fail). If the subprocess had finished successfully, the output would have been captured into the variable command_output
, which is then expanded in the echo
. It is then made available as an environment variable for future steps on that runner.