|
| 1 | +# About `pre-commit` |
| 2 | + |
| 3 | +[pre-commit hooks](https://pre-commit.com/) are a subset of git hooks. git hooks are scripts that run automatically every time a particular event occurs in a git repository. A “pre-commit hook” runs before a commit takes place. |
| 4 | + |
| 5 | +--- |
| 6 | + |
| 7 | +## What problems `pre-commit` solve? |
| 8 | + |
| 9 | +pre-commit hooks are very useful in identifying simple issues before submission to code review - mostly at the time of commit. |
| 10 | +These hooks are run on every commit to automatically point out issues in the code, such as code linting, trailing whitespace in the file, running test cases and type checking, etc |
| 11 | +Pointing out these issues before code review allows a code reviewer to focus more on the application logic & architecture rather than petty issues. |
| 12 | + |
| 13 | +So you can fix these issues before committing the changes and sending them for code review. |
| 14 | + |
| 15 | +--- |
| 16 | + |
| 17 | +## `pre-commit` hooks used at PM |
| 18 | + |
| 19 | +- Following are the pre-commit hooks used in PM, and a few projects may have additional hooks. |
| 20 | + - [Basic pre-commit-hooks](https://github.com/pre-commit/pre-commit-hooks): Some out-of-the-box hooks for pre-commit. |
| 21 | + - [trailing-whitespace](https://github.com/pre-commit/pre-commit-hooks#trailing-whitespace) |
| 22 | + - [end-of-file-fixer](https://github.com/pre-commit/pre-commit-hooks#end-of-file-fixer) |
| 23 | + - [requirements-txt-fixer](https://github.com/pre-commit/pre-commit-hooks#requirements-txt-fixer) |
| 24 | + - [detect-private-key](https://github.com/pre-commit/pre-commit-hooks#detect-private-key) |
| 25 | + - [detect-aws-credentials](https://github.com/pre-commit/pre-commit-hooks#detect-aws-credentials) |
| 26 | + - [check-ast](https://github.com/pre-commit/pre-commit-hooks#check-ast) |
| 27 | + - [check-merge-conflict](https://github.com/pre-commit/pre-commit-hooks#check-toml) |
| 28 | + - [check-toml](https://github.com/pre-commit/pre-commit-hooks#check-toml) |
| 29 | + - [check-yaml](https://github.com/pre-commit/pre-commit-hooks#check-yaml) |
| 30 | + - [check-added-large-files](https://github.com/pre-commit/pre-commit-hooks#check-added-large-files) |
| 31 | + - [no-commit-to-branch](https://github.com/pre-commit/pre-commit-hooks#no-commit-to-branch) |
| 32 | + |
| 33 | + - [autoflake](https://github.com/myint/autoflake): Removes unused imports and unused variables. |
| 34 | + |
| 35 | + - [Black](https://github.com/psf/black): PEP 8 compliant opinionated Python code formatter. It reformats entire files in place. |
| 36 | + |
| 37 | + - [black_nbconvert](https://github.com/dfm/black_nbconvert): Black formatter for `ipynb` files or [Jupyter notebooks](https://jupyter-notebook.readthedocs.io/en/stable/). |
| 38 | + |
| 39 | + - [docker-compose-check](https://github.com/IamTheFij/docker-pre-commit#docker-compose-check): Verifies that docker-compose files are valid. |
| 40 | + |
| 41 | + - [flake8](https://github.com/pycqa/flake8): Python code linter that wraps [PyFlakes](https://github.com/PyCQA/pyflakes), [pycodestyle](https://github.com/PyCQA/pycodestyle) and Ned Batchelder's [McCabe](https://github.com/PyCQA/mccabe) script. |
| 42 | + - [flake8-copyright](https://github.com/savoirfairelinux/flake8-copyright): Additional dependency for flake8 that checks for copyright notices in all python files. |
| 43 | + |
| 44 | + - [Interrogate](https://github.com/econchick/interrogate): Checks code base for missing docstrings. |
| 45 | + |
| 46 | + - [isort](https://github.com/pre-commit/mirrors-isort): Sort Python imports. |
| 47 | + |
| 48 | + - [Mypy](https://github.com/pre-commit/mirrors-mypy): [mypy](https://github.com/python/mypy) type checks for Python with additional dependencies. |
| 49 | + |
| 50 | + - [pytest-check](https://github.com/predictionmachine/pm-coding-template/blob/8a538d6dc35a0559bdf92fda02d118e1608a7d93/.pre-commit-config.yaml#L113): Running pytest locally. |
| 51 | + |
| 52 | +--- |
| 53 | + |
| 54 | +## Installation & usage |
| 55 | + |
| 56 | +### 1. Install `pre-commit`: |
| 57 | + |
| 58 | +- Using [`pip`](https://pip.pypa.io/en/stable/) : |
| 59 | + |
| 60 | + ```shell |
| 61 | + $ pip install pre-commit |
| 62 | + ``` |
| 63 | + |
| 64 | +- Using [homebrew](https://brew.sh/) |
| 65 | + |
| 66 | + ```shell |
| 67 | + $ brew install pre-commit |
| 68 | + ``` |
| 69 | + |
| 70 | +- Using [conda](https://conda.io/) (via [conda-forge](https://conda-forge.org/)): |
| 71 | + |
| 72 | +### 2. Install `pre-commit` hooks: |
| 73 | + |
| 74 | +- The pre-commit hook configurations are defined in [`.pre-commit-config.yaml`](https://github.com/predictionmachine/pm-coding-template/blob/main/.pre-commit-config.yaml) file. |
| 75 | +- To install the hooks, run: |
| 76 | + |
| 77 | + ```shell |
| 78 | + $ pre-commit install |
| 79 | + ``` |
| 80 | + |
| 81 | +### 3. Update hook version: |
| 82 | + |
| 83 | +- To update hook version, periodically run: |
| 84 | + |
| 85 | + ```shell |
| 86 | + $ pre-commit autoupdate |
| 87 | + ``` |
| 88 | + |
| 89 | +### 4. Running `pre-commit` hooks on files: |
| 90 | + |
| 91 | +- To run hooks on all the files, run: |
| 92 | + |
| 93 | + ```shell |
| 94 | + $ pre-commit run --all-files |
| 95 | + ``` |
| 96 | + |
| 97 | +- To run hooks on specifc file (single file), run: |
| 98 | + |
| 99 | + ```shell |
| 100 | + $ pre-commit run --files /path_of_the_file |
| 101 | + ``` |
| 102 | + |
| 103 | +- To skip `pre-commit` hook on commit, run: |
| 104 | + |
| 105 | + ```shell |
| 106 | + $ git commit -m "change_type: your message" --no-verify |
| 107 | + ``` |
| 108 | + |
| 109 | +- Skipping a hook: |
| 110 | + |
| 111 | + - To skip a specific hook (or set of hook) temporarily, use `SKIP` environment variable with hook id when doing a commit. |
| 112 | + - The `SKIP` environment variable is a comma separated list of hook ids. This allows you to skip a single hook instead of `--no-verify` ing the entire commit. |
| 113 | + - Syntax: |
| 114 | + |
| 115 | + ```shell |
| 116 | + $ SKIP=hook_id,hook_id_2 git commit -m "commit message" |
| 117 | + ``` |
| 118 | + |
| 119 | + - Example: |
| 120 | + |
| 121 | + ```shell |
| 122 | + $ SKIP=flake8 git commit -m "doc: update readme" |
| 123 | + ``` |
| 124 | + |
| 125 | +- `mypy` hook needs the typing dependencies installed, which mirrors `requirement-dev.txt`, for example: |
| 126 | + |
| 127 | + ```shell |
| 128 | + - repo: https://github.com/pre-commit/mirrors-mypy |
| 129 | + rev: 'v0.910' |
| 130 | + hooks: |
| 131 | + - id: mypy |
| 132 | + # verbose: true |
| 133 | + # args: [--ignore-missing-imports] |
| 134 | + additional_dependencies: |
| 135 | + # - boto3-stubs[s3]>=1.18 |
| 136 | + # - mypy-boto3-s3>=1.18 |
| 137 | + # - types-orjson>=0.1.1 |
| 138 | + - types-pytz>=2021.1.0 |
| 139 | + # - types-requests>=2.25.0 |
| 140 | + ``` |
| 141 | + |
| 142 | +- `flake8` hook needs an additional dependency ([flake8-copyright](https://github.com/savoirfairelinux/flake8-copyright)) that checks for copyright notices in all python files. |
| 143 | +- Other hooks that need the dependencies should be configured in `.pre-commit-config.yaml` config file. |
| 144 | +- Checkout pre-commit [doc](https://pre-commit.com/#command-line-interface) to know more about CLI options. |
0 commit comments