Code review is too valuable to spend on formatting. If a reviewer’s comments are about indentation, missing type hints or a forbidden function, the process has already failed. Those checks belong to a machine, and they should run before the code ever reaches a pull request.
GrumPHP in one paragraph
GrumPHP is a Composer package that installs Git hooks into a project. When a developer commits, it runs a configured set of tasks against the changed files: linting, coding standards, static analysis and so on. If any task fails, the commit is rejected with the reason. Because it is installed through Composer, every developer who runs composer install gets the same checks automatically.
A starting configuration for Magento
composer require --dev phpro/grumphp magento/magento-coding-standard
# grumphp.yml
grumphp:
tasks:
phplint: ~
phpcs:
standard: Magento2
triggered_by: [php, phtml]
whitelist_patterns:
- /^app\/code\/(.*)/
composer: ~
Scoping the checks to app/code matters on Magento: you want to enforce standards on your own modules, not report thousands of issues in vendor code you don’t own. Static analysis such as PHPStan can be added as another task once the team is comfortable.
Rolling it out without a revolt
- Check only what changed. On an existing codebase, checking every file on day one produces a wall of errors nobody will fix. Checking staged files means code gets better as it’s touched.
- Ship it as a shared package. A team-wide configuration package keeps the rules identical across projects and updates them in one place.
- Explain the rules. Developers accept a rule they understand far more readily than one that just blocks them.
Hooks can be skipped, so check again in the pipeline
Anyone can bypass a Git hook with git commit --no-verify. The hook is there for fast feedback, not enforcement. Run the same checks in the CI pipeline as well, and make a failure block the merge:
vendor/bin/grumphp run
What reviewers get back
Once the machine handles style and obvious mistakes, review can focus on what humans are good at: is this the right approach, does it handle failure, will the next developer understand it? That’s where code quality is really decided.