Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tweak the README #587

Merged
merged 1 commit into from
Jun 18, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
298 changes: 160 additions & 138 deletions README.md
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/).