The following blog post describes a a framework for managing and maintaining multi-language pre-commit hooks. The described methods adding a comprehensive quality gate to your publishing workflow. If you are using SVN instead of GIT you can skip this blog post 😛
The framework was designed by Yelp three years ago. It brings many pre defined checks designed for a generated GIT pre-commit hook. Most of the checks are made to to run against python files. This is not a blocker for PHP developers. Fortunately the framework can be extended by scripts. It’s also possible to share the checks in extra remote repositories. So you can build a pre-commit kit for your purposes. The standard repository comes with some nice checks for i.e. XML or YAML files. Other stuff like checking for broken symlinks or “merge residues”. A complete list and a documentation can be found on project website.
Installation
The installation is simple. It can be done by brew or the python installer pip. Most Linux distributions come with pip already installed. Mac users can install python with pip or use brew.
On Mac:
brew install pre-commit
or with Python PIP:
pip install pre-commit
After the installation we should have a binary “pre-commit”.
Config
For configuration a YAML format is used. All the configs are validated by pre-commit. That’s a good thing. If you have a mistake in your config file it will print out a long list of syntax rules. Config entries start with a „repo“ which must be a git repository URL. The example shows the external repository provided by hootsuite.
- repo: git@github.com:hootsuite/pre-commit-php.git sha: 1.2.0 hooks: - id: php-lint - id: php-unit - id: php-cs-fixer files: \.(php)$
Hooks can also be defined locally. Add the pseudo repository name „local“:
- repo: local hooks: - id: "run-unit-tests" name: "Run Unit-Tests" entry: "./vendor/bin/phpunit" language: "script" always_run: true files: \.(php)$
Every rule must have an IDE. That’s important if you share a rule in your own repository. If the rule is provided by an external repository it must be defined in a „hooks.yaml“ file. To use the hooks in your lokal project a .pre-commit-config.yaml
file must be created.
Install the hooks
The installation of the hooks in your config can be done by running pre-commit install
. That’s all we need to do. After that all our commits are checked by the installed hooks.
It’s also possible to update the YAML file versions like „composer update“ with pre-commit autoupdate
. This fetches the newest version of the commits from remote repositories.
Test the hooks
Simply run pre-commit run --all-files
to test all hooks against the whole local working copy.
Commit your code
Congratulations! You have now a QA step between you and your CI server. If you commit some code the automatic checks should run and prevent bigger issues. To secure the complete project it’s necessary to setup the same checks on your continuous integration server. If you don’t have a CI-Server like Jenkins, Gitlab etc. and working for your own this setup is good enough.
git commit -a
Example config for a PHP library
This config provides us the following checks:
- Validate
composer.json
file with composer - Prevent large files in commits like a database dump
- Check for valid JSON and XML files
- Check if merge conflict entries are not resolved
- Check if a file has a wrong BOM
- Run php-cs-fixer and fix code against a
.php_cs
file.
Example .pre-commit-config.yaml:
- repo: local hooks: - id: validate-composer-json name: Validate Composer JSON entry: "composer validate --strict" language: system files: composer\.json - repo: git://github.com/pre-commit/pre-commit-hooks sha: 5da199bb8d60f764c0f77a20b0a1dc3a7640bcdd hooks: - id: check-added-large-files - id: php-unit - id: check-json - id: check-xml - id: check-merge-conflict - id: check-byte-order-marker - repo: git://github.com/hootsuite/pre-commit-php.git sha: 1.2.0 hooks: - id: php-cs-fixer args: - -q - --config-file=.php_cs - id: php-lint-all
Output:
If you find the concept good, we would be happy if you leave a comment.
Have fun!
PS: Thanks to David Lambauer for discovering the framework at netz98.
– Creator of n98-magerun
– Fan of football club @wormatia
– Magento user since version 0.8 beta
– 8x certified Magento developer
– PHP Top 1.000 developer (yes, I’m PHP4 certified and sooooo old)
– Chief development officer at netz98