How to Enforce Drupal Coding Standards via Git

code on monitors

The Drupal community maintains its own evergreen coding standards that differ from those of the broader PHP community (e.g., PSR-2). It's encouraged to pore through the standards line-by-line and memorize each for perfect real-time compliance, but for those with better things to do, fear not! The standards will come to you. When starting new projects, just add a composer dependency on vijaycs85/drupal-quality-checker. This tool uses GrumPHP to add a pre-commit hook that checks new code for violations of the Drupal coding standards and outputs helpful information to aid the developer in resolving each one.

What is GrumPHP?

GrumPHP is a clever tool that automatically adds git pre-commit and commit-msg hooks to your local environment to check coding standards before committing. Since git hooks depend on your local git repository configuration and are not part of the codebase, GrumPHP uses Composer to modify the .git/hooks/pre-commit file on your disk.

Let’s review some of the “gotchas” you might run into.

Grrr, I can’t commit my WIP code because it violates Drupal coding standards!

When warranted, use the --no-verify (-n) flag to skip the checks.

git commit -n

But don’t forget to go back and fix them later! Use the --amend flag to “re-do” the commit (before pushing) to trigger GrumPHP to check for errors.

git commit --amend

If you've already pushed your changes to a shared branch and want GrumPHP to check your code, use the commands explained in the "GrumPHP doesn't do anything?" section below.

I can't commit commented-out code, seriously?

Generally speaking, don't commit commented-out code. Instead, rely on the powerful mechanisms provided by git for pulling lines from the VCS history. "What about new code that I have yet to commit but want to keep around for later?" Well, go ahead and commit it (with --no-verify, to skip the checks), then revert the commit (git revert). And voila, now it's available to you in the VCS history.

Sometimes, though, this is just not practical or desirable, and there remain legitimate cases for committing commented-out code. What are your options?

  1. Use @code ... @endcode tags in docblock comments. When adding code samples to functions, files, or class docblocks, using the @code ... @endcode tags prevent PHPCS from throwing a warning.
  2. Prevent coding standards checks on specific lines, code blocks, or entire files. See the next section for details.

But really, deeply, truly, the standards are wrong here, I swear!

If you disagree with or don’t want to follow the standards for whatever reason, here’s how you can whitelist specific lines and files.

Whitelist a single line:

<?php
// @codingStandardsIgnoreLine
$honeyBadger = new HoneyBadger();

// Or on the same line.
$honeyBadger = new HoneyBadger(); // @codingStandardsIgnoreLine

Whitelist a code block:

<?php
// @codingStandardsIgnoreStart
$honeyBadger = new HoneyBadger();
if ($honeyBadger.cares()) throw new Exception();
// @codingStandardsIgnoreEnd

Whitelist an entire file:

<?php
// @codingStandardsIgnoreFile
class HoneyBadger {
  public function cares() { return FALSE; }
}

OMG, so many errors

If you write a lot of code/make many changes before committing, you may end up with a miles-long list of violations to fix—a real pain when you thought you were done and ready to push! So rather than depending on this git pre-commit check, make your life easier by taking care of the issues as you go. And no, you don’t need to memorize all the Drupal coding standards by heart; there are plugins for every major code editor to help you out. They provide real-time, inline feedback as soon as you write code that doesn’t pass muster; much easier than bouncing back and forth between the error list in your git client and the code, hunting for files and line numbers. Furthermore, your editor can generate the full list of violations and link you straight to the offending lines.

To get started, follow the steps in this Drupal.org documentation page: Installing Coder Sniffer. When the documentation talks about installing PHPCS and the Drupal standards globally, you can instead point it to your project-local version, if you wish:

  • PHP_CodeSniffer command: /path/to/repo/vendor/bin/phpcs
  • Drupal coding standard “sniffs”: /path/to/repo/vendor/drupal/coder/coder_sniffer/Drupal

GrumPHP doesn't do anything?

If GrumPHP shows all green checkmarks when you know there are violations, you may have an issue with the configuration, or your project may not be compatible with GrumPHP. For example, certain project structure hierarchies are not yet supported. Good luck with that! Just kidding, here’s some help.

Furthermore, note that the GrumPHP pre-commit script only checks your added/changed files for violations, not all the code in your project. Generally, this is a good thing, as you don’t want to fix unrelated code in your pull request. But if you do want to run a complete check of all the code in the repository or a specific directory, you can use your code editor to generate a report or one of these command-line tools:

php path/to/repo/vendor/bin/grumphp run

If you need to customize the list of files to include or ignore:

path/to/repo/vendor/bin/phpcs \
  --standard=Drupal           \
  --ignore=*.css              \
  web/modules/custom          \
  web/themes

Extra Credit

The tools described so far help with accidentally committing code that violates Drupal standards, but it doesn’t prevent it entirely. To do that, you’ll want to add a test to your Continuous Integration (CI) workflow that flags pull requests with code that violates a standard.

CI tooling is outside the scope of this post, but lots of good resources exist. Check out this excellent blog post to help you get started: Continuous Integration for Drupal 8 with CircleCI.

Conclusion

Are you ready to get started? It’s as simple as running this command:

composer require vijaycs85/drupal-quality-checker

There’s also a newer kid on the block: drupol/drupal-conventions. I can’t vouch for it as I’ve not yet tried it on a project, but it looks promising and includes a “fixer” config to automatically fix small/unambiguous issues for you.

composer require drupol/drupal-conventions

I hope this has been a helpful post to all. If you have suggestions, improvements, or corrections, please comment below or @ me on drupal.org, thanks!

Published in

Hawkeye Tenderwolf

Photo of Hawkeye Tenderwolf
Hawkeye Tenderwolf takes great pleasure in writing and reviewing elegant, object-oriented code.