Skip to content
Advertisement

Avoid early exit from command in gitlab CI script pipeline while still capturing exit status

I am trying to generate a badge from PyLint output in a Gitlab CI script. Eventually, the job should fail if PyLint has a non-zero exit code. But before it does so, I want the badge to be created. So I have tried the following:

JavaScript

This works fine if the PyLint exit code is 0:

JavaScript

However, when PyLint exits with non-zero, the script is aborted after the first line:

JavaScript

To clarify: I want the job to fail, but I want to make sure the script always runs all the lines. Only the exit command in the last line should determine the job status.

This runs in a container that uses the Bash.

I expected the tee command to always exit with 0 so that the first script line should never fail. But that does not seem to be the case.

I have tried appending a || true call to the first line, but then the following line, SUCCESS=${PIPESTATUS[0]}, is always 0; perhaps this refers to the root cause.

Also, I have tried to append the export call (now second line) to the first line, separated by a semicolon. Again, no difference even though I also expected the export call always to exit with 0.

My question is hence: why can the first line of the script exit with a non-zero code? How do I prevent this?

Or maybe: is there an easier way to achieve the same goal?

Advertisement

Answer

Gitlab sets a bunch of “helpful” shell options you don’t actually want. Among these is errexit, aka set -e, and pipefail (which is generally a good idea, but in conjunction with set -e means your script exits if any component of a pipeline fails).

To work around this one:

JavaScript

We’re sitting SUCCESS directly here (no need for export), so you don’t need to refer to PIPESTATUS later. Branching on the return value of a command marks that command as “checked”, so it isn’t treated as a failure for purposes of errexit.


BTW, for background on set -e and why it’s something you really don’t want, see BashFAQ #105.

As another aside, all-caps variable names are used for variables meaningful to the shell or POSIX-specified tools, whereas names with at least one lowercase character are reserved for application use and guaranteed not to collide. See https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html, keeping in mind that setting a shell variable will overwrite any preexisting like-named environment variable.

User contributions licensed under: CC BY-SA
9 People found this is helpful
Advertisement