pre-commit - framework for managing git hooks

Beefy IDE helps us a lot with producing good quality code by validating formatting, running some checking scripts, and so on. This kind of help is limited to how well you configure your IDE, but how can we propagate those checks for everyone or create our own custom checks with a few lines of bash script or even include it to our CI/CD systems? Here comes the pre-commit itself described as: a framework for managing and maintaining multi-language pre-commit hooks. Using pre-commit you can prepare your own hooks (ie. bash script), expose it as git repository and refer to it in your projects at different git hook levels. The big advantage of pre-commit is a huge hooks repository for most use cases and you can run pre-commit without waiting for git hook. Documentation is pretty extensive so I won’t gonna copy/paste, but rather concentrate on a sample use-case. If you are using GitHub, when you first push your changes you will get a help URL to create PR, but every next push you won’t get the URL to already created PR. So let’s prepare git hooks at pre-push level to get URL of the existing PR. The first prepare git repository for our new pre-commit hook, the content look like this:

❯ ls -la
drwxr-xr-x   - wit 10 Apr 09:34 .git
.rw-r--r-- 154 wit 10 Apr 08:42 .pre-commit-hooks.yaml
drwxr-xr-x   - wit 10 Apr 08:26 hooks
❯ cat .pre-commit-hooks.yaml
- id: gh-pr-url
  name: gh-pr-url
  description: Get github PR url
  entry: hooks/gh-pr-url.sh
  language: script
  require_serial: true
  stages: [push]
❯ cat hooks/gh-pr-url.sh
#!/usr/bin/env bash

set -e

if ! command -v jq >/dev/null; then
	echo "no jq installed"
  exit 0
fi

if ! command -v gh >/dev/null; then
	echo "no github cli installed"
  exit 0
fi

if git remote -v | grep -q "github.com"; then
	PAGER="" gh pr view --json url  | jq -r .url || exit 0
else
	echo "not github repo"
fi

I choose Github CLI to view PR from the current working directory git repository and parse it using jq. Now we can refer to this hook in our project:

❯ cat .pre-commit-config.yaml
repos:
- hooks:
  - id: gh-pr-url
    stages: [push]
    verbose: true
  repo: <url>
  rev: <revision_or_tag>

then check it right beforing installing git hook:

❯ pre-commit run -v --hook-stage push -a
gh-pr-url................................................................Passed
- hook id: gh-pr-url
- duration: 0.01s

<PR_url>

if it’s working as expected, we can install it:

❯ pre-commit install --install-hooks -t pre-push
pre-commit installed at .git/hooks/pre-push

and check it in practice:

❯ git commit -m 'test'
[master 9ab3954] test
 1 file changed, 1 insertion(+)
❯ git push origin master
gh-pr-url................................................................Passed
- hook id: gh-pr-url
- duration: 0.52s

<PR_url>

Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 8 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 299 bytes | 299.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
...

comments powered by Disqus

powered by Hugo and Noteworthy theme