Every single Elixir project all around should use it. Besides fancy mix
task
to report project styling issues, it has bindings to most of modern editors,
like neovim
,
emacs
through alchemist.el and even Atom
.
The greatest thing about credo
is it provides the meaningful shell return codes,
making it quite easy to plug it as a linter into git
hooks toolchain. Letβs do it:
Include credo
dependency into mix.exs
project file
defp deps do
[
...
{:credo, "~> 0.7", only: [:dev, :test]},
...
]
end
if you are reading this article from the future, immediately run
$ mix deps.update credo
to get the up-to-date version. Itβs safe, since weβd use it in non-prod environments only. Letβs try it in action.
Running credo
for the first time
$ mix credo
Checking 36 source files ...
Software Design
β
β [D] β Found a FIXME tag in a comment: # FIXME FIXME FIXME
β lib/my_app/file1.ex:194 (MyApp.File1.fun1)
β [D] β Found a TODO tag in a comment: # Todo: should round here?
β lib/my_app/file2.ex:53 (MyApp.File2.fun2)
Code Readability
β
β [R] β Modules should have a @moduledoc tag.
β lib/my_app/file1.ex:4:13 (MyApp.File1)
β [R] β Modules should have a @moduledoc tag.
β lib/my_app/file3.ex:3:11 (MyApp.File3)
Refactoring opportunities
β
β [F] β Function body is nested too deep (max depth is 2, was 4).
β lib/my_app/file1.ex:179:21 (MyApp.File1.fun1)
Warnings - please take a look
β
β [W] β Prefer lazy Logger calls.
β lib/my_app/file1.ex:91 (MyApp.File1.fun3)
β [W] β Prefer lazy Logger calls.
β lib/my_app/file1.ex:82 (MyApp.File1.fun2)
β [W] β Prefer lazy Logger calls.
β lib/my_app/file1.ex:169 (MyApp.File1.fun3)
Please report incorrect results: https://github.com/rrrene/credo/issues
Analysis took 1.1 seconds (0.02s to load, 1.1s running checks)
220 mods/funs, found 3 warnings,
1 refactoring opportunity,
2 code readability issues,
2 software design suggestions.
Here we go. First run report is always depressive and driving me bonkers.
I was writing this code today morning, itβs, you know, kinda perfect. I hope
youβll get zero warnings and at most one TODO
tag found, but I never get there.
First run turns me into a couple of hours of refactoring. The good thing is
from now on itβs fairly easy to keep the project in clean state, that
satisfies even such a captious judge as credo
.
Configure credo
The very straightforward way to make everything tuned would be to:
cd config
# wget https://raw.githubusercontent.com/rrrene/credo/master/.credo.exs
mix credo gen.config
vim .credo.exs
cd -
The file is self-documented. Just go tweak it.
Making it happen recurrently
Well, I knew one guy who had put running linters into crontab
at 2AM.
He started every morning with few cups of coffee and several hours of
refactoring. I am not as brave. I use git hooks to lint my code (save for editor
plugins.)
Letβs configure our .git/config
in the first place. Just add
the following section to it:
[credo]
terminate = 16
The above will terminate the commit when there are warnings. Check how credo
calculates an exit status for details.
OK, now we are to create a hook itself. You might just put this in your
.git/hooks/pre-commit
local hook (create this file if itβs not existing yet):
#!/bin/sh
#
# Linter Elixir files using Credo.
# Called by "git receive-pack" with arguments: refname sha1-old sha1-new
#
# Config
# ------
# credo.terminate
# The credo exit status level to be considered as βnot passedββto prevent
# git commit until fixed.
# Config
terminate_on=$(git config --int credo.terminate)
if [[ -z "$terminate_on" ]]; then terminate_on=16; fi
# test it :: run tests before commit (silently)
mix test 2>&1 >/dev/null
TEST_RES=$?
if [ $TEST_RES -ne 0 ]
then
echo ""
echo "β ==================================== β"
echo "β Some tests are failed. β" >&2
echo "β Please fix them before committing. β" >&2
echo "β ==================================== β"
echo ""
exit $TEST_RES
fi
echo ""
echo "β
============================== β
"
echo "β
Tests passed successfully. β
"
echo "β
============================== β
"
echo ""
# lint it :: credo checks before commit
mix credo
CREDO_RES=$?
if [ $CREDO_RES -ge $(terminate_on) ]; then
echo ""
echo "β ============================================= β"
echo "β Credo found critical problems with your code β" >&2
echo "β and commit can not proceed. Please examine β" >&2
echo "β log above and fix issues before committing. β" >&2
echo "β ============================================= β"
echo ""
exit $CREDO_RES
fi
if [ $CREDO_RES -le 9 ]; then CREDO_RES=" $CREDO_RES"; fi
echo ""
echo "β
============================== β
"
echo "β
Credo passed successfully. β
"
echo "β
Exit value is: (total: $CREDO_RES). β
"
echo "β
============================== β
"
echo ""
# Finished
exit 0
Before credo
we also run tests. If you are like me and want to commit
code even while all the tests are failing (hopefully providing the comment
like β:bomb: [BROKEN] Evening commit! Do not use at home or school!β,)
just supply --no-verify
option to git commit
.
And yes, we are done. Try to git commit
and youβll see as your code will
be tested and credoβed for you automagically.