diff options
Diffstat (limited to 'CONTRIBUTING.md')
-rw-r--r-- | CONTRIBUTING.md | 146 |
1 files changed, 146 insertions, 0 deletions
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..2b83c82 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,146 @@ +# Contributing + +## Local development + +- The complete test suite depends on having at least the following installed + (possibly not a complete list) + - git (A sufficiently newer version is required to run pre-push tests) + - python2 (Required by a test which checks different python versions) + - python3 (Required by a test which checks different python versions) + - tox (or virtualenv) + - ruby + gem + - docker + +### Setting up an environment + +This is useful for running specific tests. The easiest way to set this up +is to run: + +1. `tox --devenv venv` (note: requires tox>=3.13) +2. `. venv/bin/activate` + +This will create and put you into a virtualenv which has an editable +installation of pre-commit. Hack away! Running `pre-commit` will reflect +your changes immediately. + +### Running a specific test + +Running a specific test with the environment activated is as easy as: +`pytest tests -k test_the_name_of_your_test` + +### Running all the tests + +Running all the tests can be done by running `tox -e py37` (or your +interpreter version of choice). These often take a long time and consume +significant cpu while running the slower node / ruby integration tests. + +Alternatively, with the environment activated you can run all of the tests +using: +`pytest tests` + +### Setting up the hooks + +With the environment activated simply run `pre-commit install`. + +## Documentation + +Documentation is hosted at https://pre-commit.com + +This website is controlled through +https://github.com/pre-commit/pre-commit.github.io + +## Adding support for a new hook language + +pre-commit already supports many [programming languages](https://pre-commit.com/#supported-languages) +to write hook executables with. + +When adding support for a language, you must first decide what level of support +to implement. The current implemented languages are at varying levels: + +- 0th class - pre-commit does not require any dependencies for these languages + as they're not actually languages (current examples: fail, pygrep) +- 1st class - pre-commit will bootstrap a full interpreter requiring nothing to + be installed globally (current examples: node, ruby) +- 2nd class - pre-commit requires the user to install the language globally but + will install tools in an isolated fashion (current examples: python, go, rust, + swift, docker). +- 3rd class - pre-commit requires the user to install both the tool and the + language globally (current examples: script, system) + +"third class" is usually the easiest to implement first and is perfectly +acceptable. + +Ideally the language works on the supported platforms for pre-commit (linux, +windows, macos) but it's ok to skip one or more platforms (for example, swift +doesn't run on windows). + +When writing your new language, it's often useful to look at other examples in +the `pre_commit/languages` directory. + +It might also be useful to look at a recent pull request which added a +language, for example: + +- [rust](https://github.com/pre-commit/pre-commit/pull/751) +- [fail](https://github.com/pre-commit/pre-commit/pull/812) +- [swift](https://github.com/pre-commit/pre-commit/pull/467) + +### `language` api + +here are the apis that should be implemented for a language + +Note that these are also documented in [`pre_commit/languages/all.py`](https://github.com/pre-commit/pre-commit/blob/master/pre_commit/languages/all.py) + +#### `ENVIRONMENT_DIR` + +a short string which will be used for the prefix of where packages will be +installed. For example, python uses `py_env` and installs a `virtualenv` at +that location. + +this will be `None` for 0th / 3rd class languages as they don't have an install +step. + +#### `get_default_version` + +This is used to retrieve the default `language_version` for a language. If +one cannot be determined, return `'default'`. + +You generally don't need to implement this on a first pass and can just use: + +```python +get_default_version = helpers.basic_default_version +``` + +`python` is currently the only language which implements this api + +#### `healthy` + +This is used to check whether the installed environment is considered healthy. +This function should return `True` or `False`. + +You generally don't need to implement this on a first pass and can just use: + +```python +healthy = helpers.basic_healthy +``` + +`python` is currently the only language which implements this api, for python +it is checking whether some common dlls are still available. + +#### `install_environment` + +this is the trickiest one to implement and where all the smart parts happen. + +this api should do the following things + +- (0th / 3rd class): `install_environment = helpers.no_install` +- (1st class): install a language runtime into the hook's directory +- (2nd class): install the package at `.` into the `ENVIRONMENT_DIR` +- (2nd class, optional): install packages listed in `additional_dependencies` + into `ENVIRONMENT_DIR` (not a required feature for a first pass) + +#### `run_hook` + +This is usually the easiest to implement, most of them look the same as the +`node` hook implementation: + +https://github.com/pre-commit/pre-commit/blob/160238220f022035c8ef869c9a8642f622c02118/pre_commit/languages/node.py#L72-L74 |