/ex_check

One task to efficiently run all code analysis & testing tools in an Elixir project. Born out of ❤️ to Elixir and pragmatism.

Primary LanguageElixirMIT LicenseMIT

ex_check ex_check

License Build status (GitHub Actions) Build status (Travis CI) Hex version Downloads

Demo

Run all code checking tools with a single convenient mix check command.


Takes seconds to setup, saves hours in the long term.

Sports powerful features to enable ultimate flexibility.

Takes care of the little details, so you don't have to.

  • Compiles the project and collects compilation warnings in one go
  • Ensures that output from tools is still ANSI formatted & colorized

Read more in the introductory "One task to rule all Elixir analysis & testing tools" article.

Getting started

Add ex_check dependency in mix.exs:

def deps do
  [
    {:ex_check, "~> 0.12.0", only: [:dev], runtime: false}
  ]
end

Fetch the dependency:

mix deps.get

Run the check:

mix check

That's it - mix check will detect and run all the available tools.

Configuring tools

If you want to take advantage of curated tools, add following dependencies in mix.exs:

def deps do
  [
    {:credo, ">= 0.0.0", only: [:dev], runtime: false},
    {:dialyxir, ">= 0.0.0", only: [:dev], runtime: false},
    {:ex_doc, ">= 0.0.0", only: [:dev], runtime: false},
    {:sobelow, ">= 0.0.0", only: [:dev], runtime: false}
  ]
end

You may also generate .check.exs to adjust the check:

mix check.gen.config

Among others, this allows to permamently disable specific tools and avoid the skipped notices.

[
  tools: [
    {:dialyzer, false},
    {:sobelow, false}
  ]
]

Avoiding duplicate builds

If, as suggested above, you've added ex_check and curated tools to only: [:dev], you're keeping the test environment reserved for ex_unit. While a clean setup, it comes at the expense of Mix having to compile your app twice - in order to prepare :test build just for ex_unit and :dev build for other tools. This costs precious time both on local machine and on the CI. It may also cause issues if you set MIX_ENV=test, which is a common practice on the CI.

You may avoid this issue by running mix check and all the tools it depends on in the test environment. In such case you may want to have the following config in mix.exs:

def project do
  [
    # ...
    preferred_cli_env: [
      check: :test,
      credo: :test,
      dialyzer: :test,
      sobelow: :test
    ]
  ]
end

def deps do
  [
    {:credo, ">= 0.0.0", only: [:test], runtime: false},
    {:dialyxir, ">= 0.0.0", only: [:test], runtime: false},
    {:ex_check, "~> 0.12.0", only: [:test], runtime: false},
    {:ex_doc, ">= 0.0.0", only: [:dev, :test], runtime: false},
    {:sobelow, ">= 0.0.0", only: [:test], runtime: false}
  ]
end

And the following in .check.exs:

[
  tools: [
    {:compiler, env: %{"MIX_ENV" => "test"}},
    {:formatter, env: %{"MIX_ENV" => "test"}},
    {:ex_doc, env: %{"MIX_ENV" => "test"}}
  ]
]

Above setup will consistently check the project using just the test build, both locally and on the CI.

Documentation

Learn more about the tools included in the check as well as its workflow, configuration and options on HexDocs or by running mix help check.

Want to write your own code check? Get yourself started by reading the "Writing your first Elixir code check" article.

Continuous Integration

With mix check you can consistently run the same set of checks locally and on the CI. CI configuration also becomes trivial and comes out of the box with parallelism and error output from all checks at once regardless of which ones have failed.

Like on a local machine, all you have to do in order to use ex_check on CI is run mix check instead of mix test. This repo features working CI configs for following providers:

Yes, ex_check uses itself on the CI. Yay for recursion!

Changelog

See CHANGELOG.md.

License

See LICENSE.md.