Using Coder/PHPCS in DrupalCI
This documentation needs work. See "Help improve this page" in the sidebar.
This documentation covers adding a phpcs.xml.dist file to your drupal.org contrib project.
What the test runner (AKA testbot) does
The test runner tries to run PHPCS with Coder on all projects.
If you have a patch that changes files, it will run PHPCS on only those files.
If your patch changes the phpcs.xml.dist or phpcs.xml file, it will run PHPCS against the whole project.
If your project does not have a phpcs config file, the test runner will use Composer to require the newest version of Coder, and then run PHPCS against changed files with --standard=Drupal.
And finally: If your project has a Composer-based requirement of a specific version of Coder, the test runner will install that, and then run PHPCS against either the patched files or the whole project.
Configuring the test runner
If you want to override the default options of the test runner, this can be done by editing the build.assessment.validate_codebase.phpcs
section in drupalci.yml
:
build:
assessment:
validate_codebase:
phpcs:
# Whether to sniff all files, or only the files changed in the patch.
# Defaults to false.
sniff-all-files: true
# Whether to terminate the test when coding standards violations are
# detected. Note that this will not cause the test result to be marked
# as failed, but it will terminate at the "Build successful" stage.
# Remaining tests will not run.
# Defaults to false.
halt-on-fail: true
# The version of Coder to use. If omitted, this will default to the
# version of Coder specified in composer.json, or to the latest version.
coder-version: '^8.2@stable'
How to specify Drupal coding standards
In your project's phpcs.xml(.dist) file, you should specify the sniffs you want as sniffs. Like this fragment from the Examples for Developers project:
<ruleset name="drupal_examples">
<description>Default PHP CodeSniffer configuration for Examples for Developers.</description>
<file>.</file>
<arg name="extensions" value="css,inc,install,module,php,profile,test,theme"/>
<rule ref="Drupal.Array"/>
<rule ref="Drupal.CSS"/>
<rule ref="Drupal.Classes"/>
<rule ref="Drupal.Commenting">
<exclude name="Drupal.Commenting.DocComment.MissingShort"/>
<!-- TagsNotGrouped has false positives for @code/@endcode. See
https://www.drupal.org/node/2502837 -->
<exclude name="Drupal.Commenting.DocComment.TagsNotGrouped"/>
<!-- We have to document hooks in a non-standard way in order to be
informative -->
<exclude name="Drupal.Commenting.HookComment.HookParamDoc"/>
<exclude name="Drupal.Commenting.HookComment.HookReturnDoc"/>
</rule>
Rules are specified by sniff name. This is in contrast to Drupal core, which specifies rules by file location. Don't do this. Use the sniff name.
If you still want to be able to run PHPCS locally, you can either add the dealerdirect/phpcodesniffer-composer-installer package to the composer require-dev
section, or add the following to your phpcs.xml
:
<config name="installed_paths" value="../../drupal/coder/coder_sniffer/Drupal,../../drupal/coder/coder_sniffer/DrupalPractice" />
Adding third-party sniffs
DrupalCI supports the following rulesets out of the box: Zend, Squiz, PSR2, PSR12, PSR1, PEAR, MySource, DrupalPractice and Drupal. Additional sniffs can be added by including the ruleset in composer.json
, and defining the rules in phpcs.xml
. Here is an example that adds a number of rules from the slevomat/coding-standard ruleset:
First, add the ruleset to composer.json
:
$ composer require --dev slevomat/coding-standard
Then, customize your phpcs.xml
file with the rules you'd like to include. Also, make sure to set the installed_paths
configuration to the path of the ruleset, relative to the location where PHPCS is installed (which is usually in the ./vendor/
folder).
<?xml version="1.0" encoding="UTF-8"?>
<ruleset name="my_drupal_module">
<description>PHP CodeSniffer configuration for a Drupal module.</description>
<arg name="extensions" value="php,inc,module,install,info,test,profile,theme,css,js"/>
<arg name="report" value="full"/>
<arg value="p"/>
<config name="installed_paths" value="../../drupal/coder/coder_sniffer/Drupal,../../drupal/coder/coder_sniffer/DrupalPractice,../../slevomat/coding-standard" />
<file>.</file>
<!-- Exclude third party libraries. -->
<exclude-pattern>./vendor</exclude-pattern>
<!-- Exclude unsupported file types. -->
<exclude-pattern>*.gif</exclude-pattern>
<exclude-pattern>*.less</exclude-pattern>
<exclude-pattern>*.png</exclude-pattern>
<!-- Minified files don't have to comply with coding standards. -->
<exclude-pattern>*.min.css</exclude-pattern>
<exclude-pattern>*.min.js</exclude-pattern>
<rule ref="Drupal" />
<rule ref="DrupalPractice" />
<!-- Require the strict types declaration in every PHP file. -->
<rule ref="SlevomatCodingStandard.TypeHints.DeclareStrictTypes">
<properties>
<property name="newlinesCountBetweenOpenTagAndDeclare" value="2"/>
</properties>
</rule>
<!-- Require nullable types to be declared as such. -->
<rule ref="SlevomatCodingStandard.TypeHints.NullableTypeForNullDefaultValue">
</rule>
<!-- Forbid annotations which are not included in the Drupal coding standard but are often added by IDEs. -->
<rule ref="SlevomatCodingStandard.Commenting.ForbiddenAnnotations">
<properties>
<property name="forbiddenAnnotations" type="array">
<element value="@author"/>
<element value="@created"/>
<element value="@copyright"/>
<element value="@license"/>
<element value="@package"/>
<element value="@version"/>
</property>
</properties>
</rule>
<!-- Forbid documentation auto-generated by IDEs which does not align with the Drupal documentation standards. -->
<rule ref="SlevomatCodingStandard.Commenting.ForbiddenComments">
<properties>
<property name="forbiddenCommentPatterns" type="array">
<element value="/@inheritDoc/"/>
<element value="/^Class [a-zA-z]*\.$/"/>
<element value="/^Interface [a-zA-z]*\.$/"/>
<element value="/^[a-zA-z]* constructor\.$/"/>
</property>
</properties>
</rule>
<!-- Enforce correct formatting of return types hints. -->
<rule ref="SlevomatCodingStandard.TypeHints.ReturnTypeHintSpacing"/>
<!-- Use statements should be ordered alphabetically. -->
<rule ref="SlevomatCodingStandard.Namespaces.AlphabeticallySortedUses">
<properties>
<property name="caseSensitive" value="true"/>
</properties>
</rule>
</ruleset>
Help improve this page
You can:
- Log in, click Edit, and edit this page
- Log in, click Discuss, update the Page status value, and suggest an improvement
- Log in and create a Documentation issue with your suggestion