-
Notifications
You must be signed in to change notification settings - Fork 0
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
0 parents
commit c882ad9
Showing
4 changed files
with
124 additions
and
0 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 |
---|---|---|
@@ -0,0 +1,30 @@ | ||
# Git hooks with Python | ||
|
||
This is a demonstration on how to write and set up a simple git hook with Python as scripting language and [Poetry](https://python-poetry.org/docs/basic-usage/) as dependency management tool. | ||
|
||
The goal is to have the hook run in an isolated environment (a.k.a. virtualenv) each time, thus not interfering with other libraries or versions already installed on your system. | ||
|
||
## Requirements | ||
|
||
The only requirement besides a proper installation of Python 3+ is the Poetry tool. In Mac OS X you can install Poetry with Homebrew: | ||
|
||
```bash | ||
$ brew install poetry | ||
``` | ||
|
||
For other systems you may want to check the [documentation](https://python-poetry.org/docs/#installation). | ||
|
||
## Install | ||
|
||
First grab the tarball with the git hook from the [Releases](https://github.com/mperezi/git-hook-python/releases) section and then issue the following commands: | ||
|
||
```bash | ||
$ cd <my-project>/ | ||
$ tar xvzf version-enforcer-0.1.0.tgz | ||
x .git/hooks/version-enforcer/ | ||
x .git/hooks/version-enforcer/enforce.py | ||
x .git/hooks/version-enforcer/pyproject.toml | ||
x .git/hooks/pre-push | ||
$ (cd .git/hooks/version-enforcer && poetry install) | ||
``` | ||
|
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 |
---|---|---|
@@ -0,0 +1,5 @@ | ||
#!/usr/bin/env bash | ||
|
||
HOOKS_DIR=$(dirname "${BASH_SOURCE[0]}") | ||
cd "${HOOKS_DIR}/version-enforcer" && \ | ||
poetry run python enforce.py "$@" |
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 |
---|---|---|
@@ -0,0 +1,72 @@ | ||
#!/usr/bin/env python3 | ||
|
||
import errno | ||
import logging | ||
import os | ||
import subprocess | ||
import sys | ||
import yaml | ||
from colorama import Fore, Style | ||
from simple_term_menu import TerminalMenu | ||
|
||
OPENAPI_REST_YML = 'rest/openapi-rest.ym' | ||
METADATA_YML = 'rest/metadata.yml' | ||
|
||
logger = logging.getLogger(__name__) | ||
|
||
|
||
def bold(s): | ||
return f'{Style.BRIGHT}{s}{Style.RESET_ALL}' | ||
|
||
|
||
def red(s): | ||
return f'{Fore.RED}{s}{Style.RESET_ALL}' | ||
|
||
|
||
def green(s): | ||
return f'{Fore.GREEN}{s}{Style.RESET_ALL}' | ||
|
||
|
||
def yellow(s): | ||
return f'{Fore.YELLOW}{s}{Style.RESET_ALL}' | ||
|
||
|
||
def abort_push(): | ||
print('Go change your version as desired and commit again before pushing') | ||
print(f'{red("Push aborted!")}') | ||
sys.exit(1) | ||
|
||
|
||
def ask_confirmation(metadata_ver, openapi_ver): | ||
print(f'Version in metadata file [{yellow(metadata_ver)}] ' + | ||
f'is different from OpenAPI definition [{yellow(openapi_ver)}]') | ||
print(f'{green("?")} {bold("You OK with that?")}') | ||
if TerminalMenu(["[y] Yes", "[n] No"]).show() == 1: | ||
abort_push() | ||
|
||
|
||
def file_content_at_rev(path, rev): | ||
git_cmd = ['git', 'show', f'{rev}:{path}'] | ||
p = subprocess.run(git_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) | ||
if len(p.stderr) > 0: | ||
raise FileNotFoundError(errno.ENOENT, os.strerror(errno.ENOENT), path) | ||
return p.stdout | ||
|
||
|
||
def enforce(rev): | ||
try: | ||
metadata = yaml.load(file_content_at_rev(METADATA_YML, rev), Loader=yaml.FullLoader) | ||
metadata_ver = metadata['api']['version'] | ||
|
||
openapi_rest = yaml.load(file_content_at_rev(OPENAPI_REST_YML, rev), Loader=yaml.FullLoader) | ||
openapi_ver = openapi_rest['info']['version'] | ||
|
||
if metadata_ver != openapi_ver: | ||
ask_confirmation(metadata_ver, openapi_ver) | ||
except FileNotFoundError as ex: | ||
logger.warning(ex) | ||
|
||
|
||
if __name__ == '__main__': | ||
_, local_sha, *_ = sys.stdin.readline().split() | ||
enforce(local_sha) |
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 |
---|---|---|
@@ -0,0 +1,17 @@ | ||
[tool.poetry] | ||
name = "version-enforcer" | ||
version = "0.1.0" | ||
description = "Check that the version set in the openapi spec matches the metadata version" | ||
authors = ["mperezi <mperezibars@gmail.com>"] | ||
|
||
[tool.poetry.dependencies] | ||
python = "^3.6" | ||
PyYAML = "^5.3.1" | ||
colorama = "^0.4.4" | ||
simple-term-menu = "^0.10.4" | ||
|
||
[tool.poetry.dev-dependencies] | ||
|
||
[build-system] | ||
requires = ["poetry-core>=1.0.0"] | ||
build-backend = "poetry.core.masonry.api" |