Skip to content

Instantly share code, notes, and snippets.

@SXHRYU
Last active April 19, 2023 10:38
Show Gist options
  • Save SXHRYU/33543ae204e9b5c8029b6488485a9fcc to your computer and use it in GitHub Desktop.
Save SXHRYU/33543ae204e9b5c8029b6488485a9fcc to your computer and use it in GitHub Desktop.
This is a gist of a pre-commit git hook using raw bash (not https://pre-commit.com/). It must be placed in `.git/hooks/pre-commit`. This gist enters `config` directory with `pyproject.toml` (which has `[mypy]` and `[flake8]` configs). From there it calls both `mypy` and `flake8`. Then it sets up environment variables for `pytest` and calls it.
#!/bin/sh
##########################################################################################################
# I've used this pre-commit hook in my FastAPI app. It launches `bash` session (even on Windows) from the root dir of your project.
# Meaning if you have a following project structure:
###############################
# app/ #
# .git #
# __pycache__ #
# .mypy_cache #
# config/ #
# pyproject.toml #
# mysite/ #
# manage.py #
# mysite/ #
# __init__.py #
# settings.py #
# urls.py #
# asgi.py #
# wsgi.py #
# tests/ #
# tests_main.py #
# tests_sql.py #
###############################
# and run:
# ls -a
# the output will be '.git, __pycache__, .mypy_cache, config/, mysite/, tests/'.
# The `bash` session syntax is the same as of normal `bash` in *nix systems.
# By default this file was named `pre-commit.sample` and the original file can be found at
# https://github.com/git/git/blob/master/templates/hooks--pre-commit.sample
# Everything down below is my script.
##########################################################################################################
#
# An example hook script to verify what is about to be committed.
# Called by "git commit" with no arguments. The hook should
# exit with non-zero status after issuing an appropriate message if
# it wants to stop the commit.
#
# To enable this hook, rename this file to "pre-commit".
# Catch changed files
# git diff --cached --name-only --diff-filter=ACMR
cd config
mypy ..
mypy_status=$?
if [ $mypy_status != 0 ]
then
exit $mypy_status
fi
flake8 ..
flake8_status=$?
if [ $flake8_status != 0 ]
then
exit $flake8_status
fi
black --check $(git diff --cached --name-only --diff-filter=ACMR)
black_status=$?
if [ $black_status != 0 ]
then
exit $black_status
fi
cd ..
export DB_USER="user"
export DB_PASSWORD="password"
export DB_HOST="host"
export DB_PORT="port"
export DB_NAME="name"
export DB_USER_test="user_test"
export DB_PASSWORD_test="password_test"
export DB_HOST_test="host_test"
export DB_PORT_test="port_test"
export DB_NAME_test="name_test"
pytest -v --durations=0 --cache-clear
pytest_status=$?
if [ pytest_status != 0 ]
then
exit $pytest_status
fi
rm -rf .pytest_cache/
@SXHRYU
Copy link
Author

SXHRYU commented Jan 5, 2023

rev. 2
Updated description, because it didn't fit in.

Extra comment:
Exits on mypy/flake8/pytest fails (exit code of any != 0)

@SXHRYU
Copy link
Author

SXHRYU commented Apr 17, 2023

rev. 3
Updated description, because it had an error (had tox.ini instead of pyproject.toml.

@SXHRYU
Copy link
Author

SXHRYU commented Apr 19, 2023

rev. 4 & 5
Added useful script (5 - fix)

@SXHRYU
Copy link
Author

SXHRYU commented Apr 19, 2023

rev. 6
Added example of operation only on changed files

Extra comment:
For more information on --diff-filter check out:
https://git-scm.com/docs/git-diff#Documentation/git-diff.txt---diff-filterACDMRTUXB82308203

@SXHRYU
Copy link
Author

SXHRYU commented Apr 19, 2023

rev. 7
Made a more concise example with black.

Extra comment:
I've done this because black is a popular pre-commit hook, which has --check option flag. A user may forget to put this flag so having it in an example is useful.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment