-
Notifications
You must be signed in to change notification settings - Fork 87
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
c50d314
commit 92f7245
Showing
1 changed file
with
160 additions
and
138 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,196 +1,218 @@ | ||
# elvis [![Build Status](https://github.com/inaka/elvis/workflows/build/badge.svg)](https://github.com/inaka/elvis) | ||
# `elvis` [![CI][build-badge]][elvis] | ||
|
||
[elvis]: https://github.com/inaka/elvis | ||
[build-badge]: https://github.com/inaka/elvis/workflows/build/badge.svg | ||
|
||
![Elvis Presley dancing](https://www.reactiongifs.com/wp-content/uploads/2013/01/elvis-dance.gif) | ||
|
||
Command-line interface for Elvis, the Erlang style reviewer. | ||
`elvis`, the Erlang style reviewer, is the command-line interface for | ||
[`elvis_core`](https://github.com/inaka/elvis_core). | ||
|
||
## What is `elvis`? | ||
|
||
`elvis` is an Erlang generic style reviewer that focuses on code and configuration consistency, | ||
as well as readability, across your whole code base. By the very nature of the rules applied from | ||
`elvis_core` it can also be considered a learning tool, by trying to generalize good practices and | ||
allowing teams to adapt it to their own specific needs, while fostering discussions around code | ||
conventions. | ||
|
||
## Contact Us | ||
### Advantages of using it | ||
|
||
If you find any **bugs** or have a **problem** while using this library, please | ||
[open an issue](https://github.com/inaka/elvis/issues/new) in this repo | ||
(or a pull request :)). | ||
Some of the advantages of using `elvis` are: | ||
|
||
* enabling consistency in style across all your code base | ||
* encouraging the development team to sit down and talk about code conventions | ||
* allowing continuous monitoring of code quality | ||
* helping developers avoid repeated mistakes that can be automatically detected | ||
* providing homogenisation among different projects in a company, therefore facilitating project | ||
switching for developers, as well as allowing easier code sharing between projects | ||
* learning, since some of the conventions it proposes are themselves the distilled result of | ||
working in very large code bases | ||
|
||
## Installation | ||
|
||
1. Clone the repo | ||
2. `rebar3 compile` | ||
To use `elvis` as a standalone tool, you need to: | ||
|
||
```console | ||
git clone https://github.com/inaka/elvis | ||
cd elvis | ||
rebar3 escriptize | ||
export PATH=${PWD}/_build/default/bin:${PATH} | ||
``` | ||
|
||
(to make the env. variable export more permanent add it to your shell's configuration file, | ||
i.e. `.bashrc`, `.zshrc`, ...) | ||
|
||
Now run it by calling `elvis` (or `elvis help`), and you should get to the `Usage: elvis` | ||
instructions. | ||
|
||
## Usage | ||
|
||
In any `elvis`-enabled product, `elvis rock` will trigger a rule check. | ||
The most common use case is to `cd` into a folder containing an `elvis.config` file | ||
and executing `elvis rock`. | ||
|
||
### Script | ||
If you just execute `elvis` with no arguments or options you'll get to the usage instructions | ||
outlined in this README. | ||
|
||
`elvis` can be turned into a script by executing `rebar3 escriptize`. This will | ||
generate an `elvis` self-contained executable script, from which you can get | ||
help by typing `elvis help`. A list of available commands can be shown using the | ||
`--commands` option (i.e. `elvis --commands`). | ||
## Options | ||
|
||
To run `elvis` from the terminal use the `rock` command (i.e. `elvis | ||
rock`). There's no need to specify a configuration file path if you have an | ||
`elvis.config` file in the same location where you are executing the script, | ||
otherwise a configuration file can be specified through the use of the | ||
`--config` (or just `-c`) option. | ||
While you can get a more complete list of options by executing `elvis help`, we try to keep them | ||
documented below. | ||
|
||
```bash | ||
elvis rock --config config/elvis.config | ||
``` | ||
### `--code-path <dir>` (`-p <dir>`) | ||
|
||
In `0.3.0` a new option was introduced in order to run elvis checks only on the source files that have changed since a particular branch of commit. Example usage would be `elvis git-branch origin/HEAD`. | ||
Adds `<dir>` to the analysis' code path. | ||
|
||
## Benefits | ||
### `--commands` | ||
|
||
- Enables consistency in style across all your code base. | ||
- Encourages the development team to sit down and talk about code conventions. | ||
- Allows continuous monitoring of code quality. | ||
- Helps developers avoid repeated mistakes that can be automatically detected. | ||
- Provides homogenisation among the different projects in a company, therefore facilitating project switching for developers and as well allowing easier code sharing between projects | ||
Outputs the list of commands under stood by `elvis`. | ||
|
||
### Webhook | ||
#### `git-branch <branch | commit>` | ||
|
||
There's also a way to use `elvis` as a GitHub [webhook][webhooks] for | ||
`pull request` (PR) events by calling the `elvis_webhook:event/1` function. This will add | ||
a comment in each file and rule that is broken, analyzing only the files | ||
associated with the PR. | ||
Executes `elvis` on source files that have changed since `<branch>` or `<commit>`. | ||
|
||
#### Running the webhook on your servers | ||
#### `git-hook` | ||
|
||
Since GitHub's API needs a valid user and password to allow the creation of | ||
reviews on PRs, the parameters `github_user` and `github_password` need to be | ||
added to `elvis`'s [configuration](#configuration) and also the credentials used | ||
must be from an admin of the repo or someone with permissions for requesting changes | ||
on PRs. | ||
Executes `elvis` (with the specific configuration file) on the pre-commit hook Git-staged files. | ||
|
||
The `elvis_webhook:event/1` function takes a map containing the keys `headers` and `body`, | ||
whose values should be the map of headers and the body from the GitHub's event | ||
request. | ||
#### `install git-hook` | ||
|
||
```erlang | ||
Headers = #{<<"X-GitHub-Event">>, <<"pull_request">>}, | ||
Body = <<"{}">>, %% JSON data form GitHub's event. | ||
Request = #{headers => Headers, body => Body}, | ||
elvis:webhook(Request). | ||
``` | ||
Installs `elvis` in your current Git repository, as a pre-commit hook. | ||
|
||
### Git hook | ||
#### `rock [file...]` | ||
|
||
`elvis` can also be used as a [`git` pre-commit hook][pre-commit] | ||
using the `git-hook` command, just use something like the following as | ||
your pre-commit script: | ||
Executes `elvis` analysis on identified files. It will, by default, consider all the files | ||
in the configuration (i.e. either `elvis.config` or the path set by option `--config`). | ||
|
||
```bash | ||
#!/bin/sh | ||
# | ||
# Runs elvis rules to staged files where applicable. | ||
### `--config <file>` (`-c <file>`) | ||
|
||
elvis git-hook | ||
``` | ||
Allows providing the path to the config. file (by default `elvis.config` is assumed). | ||
|
||
As the comment states, `elvis` will search for files that match the `filter` of | ||
each rule group (see [configuration](#configuration)) among the staged files, | ||
get their staged content and run the rules specified in the configuration. | ||
If any rule fails then `elvis` exits with a non-zero code, | ||
which signals `git` that the commit shouldn't be made. | ||
### `--help` (`-h`) | ||
|
||
Make sure your pre-commit hook script is executable (i.e. by running | ||
`chmod +x pre-commit`), otherwise `git` won't be able to run it. | ||
Shows help information. | ||
|
||
### Erlang Shell | ||
### `--keep-rocking` (`-k`) | ||
|
||
If you only need to use `elvis` in the Erlang shell you might want to | ||
consider only including the [`elvis_core`](https://github.com/inaka/elvis_core) | ||
library as a dependency. | ||
Doesn't stop analysis when erroring out on a file, if given a list of files to analyse. | ||
|
||
## Configuration | ||
### `--output-format <plain | colors | parsable>` | ||
|
||
To provide a default configuration for `elvis` you should either create an | ||
`elvis.config` file located in the root directory or set the following | ||
environment values in your [configuration][config] file: | ||
Allows controlling the output format of the analysis' results. | ||
|
||
```erlang | ||
[ | ||
{ | ||
elvis, | ||
[ | ||
{config, [...]}, | ||
{output_format, plain}, | ||
The default value is `colors`. | ||
|
||
%% Only necessary for the 'webhook' functionality | ||
{github_user, "user"}, | ||
{github_password, "password"} | ||
] | ||
} | ||
]. | ||
``` | ||
`plain` will output results without colors. | ||
`parsable` will allow for consumption by systems (it's less readable for humans). | ||
|
||
The `config` and `output_format` are explained in [`elvis_core`](https://github.com/inaka/elvis_core). | ||
### `--parallel <n | auto>` (`-P <n | auto>`) | ||
|
||
The GitHub configuration parameters `github_user` and `github_password` are | ||
required only when `elvis` is used as a [webhook](#webhook). | ||
Allows analyzing files concurrently. | ||
|
||
### elvis.config | ||
Use `n` to set the desired number of parallel workers, or `auto` to have the application choose | ||
an appropriate value (based on the number of schedulers). | ||
|
||
In your `elvis.config` file you can setup which rules should be | ||
applied, on what files and in which directories to do it. | ||
### `--quiet` (`-q`) | ||
|
||
The configuration is in Erlang format, it is not that hard to write | ||
but it is easier if you use the `elvis.config` file in this reposiotry | ||
as a template. | ||
Allows suppressing all output. The exit code will still be non-`0` if there are failing rules. | ||
|
||
In the `elvis.config` file you create an elvis config where for a set | ||
of directories, you want to run a ruleset (or specific rules) on a set | ||
of files. | ||
### `--verbose` (`-V`) | ||
|
||
For example, configure to check all erlang files under the `src` | ||
directory using the ruleset `erl_files`: | ||
Allows verbose output. | ||
|
||
```erlang | ||
[ | ||
{ | ||
elvis, | ||
[ | ||
{config, | ||
[#{dirs => ["src"], | ||
filter => "*.erl", | ||
ruleset => erl_files | ||
} | ||
] | ||
} | ||
] | ||
} | ||
]. | ||
### `--version` (`-v`) | ||
|
||
Outputs the application's version. | ||
|
||
## Configuration | ||
|
||
`elvis` is configured via `elvis_core`'s `elvis.config` as detailed under | ||
[`elvis_core / Configuration`](https://github.com/inaka/elvis_core?tab=readme-ov-file#configuration). | ||
|
||
### Rules | ||
|
||
A reference of all rules implemented in `elvis` can be found in `elvis_core`'s [RULES.md](https://github.com/inaka/elvis_core/blob/main/RULES.md). | ||
|
||
### User-defined rules | ||
|
||
If you have implemented `elvis` rule that are in your local repository or in one of | ||
your dependencies, you can add these rule to your `elvis.config` file and | ||
tell `elvis` where to find the `.beam` that contains the compiled rule using | ||
the `--code-path` option. | ||
|
||
For example, if the rule is in one of your dependencies, you can run `elvis rock -p deps/elvis_rules/ebin -c elvis.config`. | ||
|
||
## As a Git hook | ||
|
||
`elvis` can be used as a [`git` pre-commit hook](https://git-scm.com/book/en/Customizing-Git-Git-Hooks#Client-Side-Hooks) | ||
using the `git-hook` command (installable via `install git-hook`) as: | ||
|
||
```sh | ||
#!/bin/sh | ||
elvis git-hook | ||
``` | ||
|
||
You can use four different rulesets `erl_files`, `makefiles`, `rebar_config` or `elvis_config`. | ||
This will have `elvis` execute on staged files, as per its configuration. | ||
|
||
## Implemented Rules | ||
If any rule fails, `elvis` exits with a non-zero code, which signals to `git` that the commit | ||
shouldn't be made. | ||
|
||
A reference of all rules implemented in Elvis can be found in this `elvis_core`'s [RULES.md](https://github.com/inaka/elvis_core/blob/main/RULES.md). | ||
**Note**: your pre-commit hook script should be executable (i.e. by running | ||
`chmod +x .git/hooks/pre-commit`), otherwise `git` won't be able to execute it. | ||
|
||
## User Defined Rules | ||
## As a webhook | ||
|
||
If you have implemented an Elvis rule that's in your local repo or in one of | ||
your dependencies, you can add this rule to your `elvis.config` file and | ||
tell Elvis where to find the `.beam` that contains the compiled rule using | ||
the `--code-path` (`-p`) option. | ||
### Webhook | ||
|
||
For example if the rule is in one of your deps, you could run Elvis in the | ||
following way: | ||
`elvis` can be used as a GitHub [webhook](https://developer.github.com/v3/repos/hooks/) for | ||
`pull request` (PR) events, by calling the `elvis_webhook:event/1` function. This will add | ||
a comment in each file and rule that is broken, analyzing only the files associated with the PR. | ||
|
||
#### Running the webhook on your servers | ||
|
||
```shell | ||
elvis rock -p deps/elvis_rules/ebin -c elvis.config | ||
Since GitHub's API needs a valid username and password to allow the creation of | ||
reviews on PRs, parameters `github_user` and `github_password` need to be | ||
added to `elvis`'s configuration file (mind you that the credentials used | ||
must be from an admin. of the repo or someone with permissions for requesting changes | ||
to PRs). | ||
|
||
The `elvis_webhook:event/1` function takes a map containing the keys `headers` and `body`, | ||
whose values should be the map of headers and the body from the GitHub's event | ||
request. | ||
|
||
```erlang | ||
Headers = #{<<"X-GitHub-Event">>, <<"pull_request">>}, | ||
Body = <<"{}">>, %% JSON data from GitHub's event. | ||
Request = #{headers => Headers, body => Body}, | ||
elvis:webhook(Request). | ||
``` | ||
|
||
## Dependencies | ||
The extension to the configuration is as follows: | ||
|
||
```erlang | ||
[ | ||
{elvis, [ | ||
{config, [...]}, | ||
%% webhook configuration parameters | ||
{github_user, "user"}, | ||
{github_password, "password"} | ||
]} | ||
]. | ||
``` | ||
|
||
## Documentation | ||
|
||
You can generate local documentation with `rebar3 ex_doc` and then access it with `open doc/index.html`. | ||
|
||
## Contributing | ||
|
||
`elvis` is a FOSS application, and as such contributions are welcome. Be sure to read | ||
the [contributing guide](CONTRIBUTING.md) for more detailed information. | ||
|
||
- Erlang/OTP 24+ | ||
- git | ||
## License | ||
|
||
## References | ||
`elvis` is licensed under the [Apache License, Version 2.0](LICENSE). | ||
|
||
Inspired on [HoundCI][houndci] | ||
## Inspiration | ||
|
||
[houndci]: https://houndci.com/ | ||
[pre-commit]: https://git-scm.com/book/en/Customizing-Git-Git-Hooks#Client-Side-Hooks | ||
[config]: https://www.erlang.org/doc/man/config.html | ||
[webhooks]: https://developer.github.com/v3/repos/hooks/ | ||
`elvis` got some of its inspiration from [HoundCI](https://houndci.com/). |