How to get non-zero exit status with lintr::lint() in order to fail a build

512 Views Asked by At

I am trying to help our group of developers obtain similar code styles by using the lintr package when writing R code. To automate this step, I want our builds to fail if there are any mistakes (bad styles) in the code. We are using Jenkins for our build pipeline if that matters.

I know that we could use the expect_lint_free function, but we are not making packages, only script files. The output from the lint function looks fine, but the build passes even when the linter returns improvement proposals. How do I get a non-zero exit status that will make the Jenkins build fail?

The (simplified) code run on the command line

Rscript -e "lintr::lint('my_script.R')"

returns no error but lots of proposals.

Note: I am not interested in "Create an R package" solutions at the moment.

3

There are 3 best solutions below

0
On BEST ANSWER

The lintr::lint() function returns results in a list with class "lints". You have issues if its length is greater than zero, so you can do

Rscript -e "quit(save = 'no', status = length(lintr::lint('my_script.R')))"
0
On

While the solution by @user2554330 works and exits with a non-zero exit code, it suppresses the output from lintr. However, you'd generally like to see where it fails when it does. You can achieve this like so:

Rscript -e "errors <- lintr::lint('my_script.R'); print(errors); quit(save = 'no', status = length(errors))"

Or for all .r files:

Rscript -e "errors <- lintr::lint_dir(); print(errors); quit(save = 'no', status = length(errors))"
0
On

Kind of an old question but lintr has a built-in solution to throw non-zero exit status if there are lints returned. I found this in the package vignette (vignette("lintr")): error_on_lint. This configuration is FALSE by default. If you are using the default configuration approach of using a .lintr file (see: lintr::use_lintr()) you can simply add a line like this: error_on_lint: TRUE

Once you have setup .lintr with error_on_lint: TRUE configuration, then (for example) running:

> Rscript -e "lintr::lint_dir()"
R\hello.R:3:44: style: [trailing_whitespace_linter] Trailing whitespace is superfluous.
# This is an example function named 'hello'
                                           ^
> echo $?
31

I found this is only useful for non-interactive work (like your Jenkins build step). Otherwise, it will restart your R session if there are lints, and it won't even say what they were.

One last thought: you mentioned running this in a Jenkins build step. You could use a git hook like pre-commit to lint your code before making commits. Could prevent messy commits cleaning up code, as well as time, if the prior build steps are slow.