Skip to content

Commit

Permalink
Composer: implement CS menu and extra commands
Browse files Browse the repository at this point in the history
This adds a number of extra CS-related Composer scripts and handler functions.

This:
* Uses the same menu as is already in use in the Free, Premium and several other plugins for predictability.
* Where necessary, adjusts existing Composer scripts to, again, be in line with what is already in use in Free and Premium.

This also adds the _ability_ to run CS with a Threshold. As the codebase is currently clean, this ability is not activated for CI for the time being, though it is likely that it will be activated once YoastCS 3.0 will be used.

Note: this change does mean that, in contrast to before, running `check-cs` will now return only errors.
While this is new for this package, it is in line with the expected behaviour for the script as used in other packages.
  • Loading branch information
jrfnl committed Dec 16, 2023
1 parent 769d980 commit 14608d2
Show file tree
Hide file tree
Showing 4 changed files with 218 additions and 2 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/cs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ jobs:
# @link https://github.com/staabm/annotate-pull-request-from-checkstyle/
- name: Check PHP code style
id: phpcs
run: composer check-cs -- --no-cache --report-full --report-checkstyle=./phpcs-report.xml
run: composer check-cs-warnings -- --no-cache --report-full --report-checkstyle=./phpcs-report.xml

- name: Show PHPCS results in PR
if: ${{ always() && steps.phpcs.outcome == 'failure' }}
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ on:
- '.github/workflows/deploy.yml'
- '.github/workflows/test.yml'
- 'config/**'
- '!config/composer/actions.php'
- 'css/**'
- 'js/**'
pull_request:
Expand All @@ -58,6 +59,7 @@ on:
- '.github/workflows/deploy.yml'
- '.github/workflows/test.yml'
- 'config/**'
- '!config/composer/actions.php'
- 'css/**'
- 'js/**'
# Allow manually triggering the workflow.
Expand Down
27 changes: 26 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@
]
},
"autoload-dev": {
"classmap": [
"config/"
],
"psr-4": {
"Yoast\\WP\\Duplicate_Post\\Tests\\": "tests/"
}
Expand All @@ -53,9 +56,26 @@
"lint": [
"@php ./vendor/php-parallel-lint/php-parallel-lint/parallel-lint . -e php --show-deprecated --exclude vendor --exclude node_modules --exclude .git"
],
"cs": [
"Yoast\\WP\\Duplicate_Post\\Config\\Composer\\Actions::check_coding_standards"
],
"check-cs-thresholds": [
"@putenv YOASTCS_THRESHOLD_ERRORS=0",
"@putenv YOASTCS_THRESHOLD_WARNINGS=0",
"Yoast\\WP\\Duplicate_Post\\Config\\Composer\\Actions::check_cs_thresholds"
],
"check-cs": [
"@check-cs-warnings -n"
],
"check-cs-warnings": [
"@php ./vendor/squizlabs/php_codesniffer/bin/phpcs"
],
"check-staged-cs": [
"@check-cs-warnings --filter=GitStaged"
],
"check-branch-cs": [
"Yoast\\WP\\Duplicate_Post\\Config\\Composer\\Actions::check_branch_cs"
],
"fix-cs": [
"@php ./vendor/squizlabs/php_codesniffer/bin/phpcbf"
],
Expand All @@ -80,7 +100,12 @@
},
"scripts-descriptions": {
"lint": "Check the PHP files for parse errors.",
"check-cs": "Check the PHP files for code style violations and best practices.",
"cs": "See a menu with the code style checking script options.",
"check-cs-thresholds": "Check the PHP files for code style violations and best practices and verify the number of issues does not exceed predefined thresholds.",
"check-cs": "Check the PHP files for code style violations and best practices, ignoring warnings.",
"check-cs-warnings": "Check the PHP files for code style violations and best practices, including warnings.",
"check-staged-cs": "Check the staged PHP files for code style violations and best practices.",
"check-branch-cs": "Check the PHP files changed in the current branch for code style violations and best practices.",
"fix-cs": "Auto-fix code style violations in the PHP files.",
"test": "Run the unit tests without code coverage.",
"coverage": "Run the unit tests with code coverage.",
Expand Down
189 changes: 189 additions & 0 deletions config/composer/actions.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
<?php

namespace Yoast\WP\Duplicate_Post\Config\Composer;

use Composer\Script\Event;

/**
* Class to handle Composer actions and events.
*
* @phpcs:disable WordPress.Security.EscapeOutput -- This file is not distributed, so this is fine.
* @phpcs:disable WordPress.PHP.DiscouragedPHPFunctions -- This file is not distributed, so this is fine.
*/
class Actions {

/**
* Provides a coding standards option choice.
*
* @param Event $event Composer event.
*
* @return void
*/
public static function check_coding_standards( Event $event ) {
$io = $event->getIO();

$choices = [
'1' => [
'label' => 'Check staged files for coding standard warnings & errors.',
'command' => 'check-staged-cs',
],
'2' => [
'label' => 'Check current branch\'s changed files for coding standard warnings & errors.',
'command' => 'check-branch-cs',
],
'3' => [
'label' => 'Check for all coding standard errors.',
'command' => 'check-cs',
],
'4' => [
'label' => 'Check for all coding standard warnings & errors.',
'command' => 'check-cs-warnings',
],
'5' => [
'label' => 'Fix auto-fixable coding standards.',
'command' => 'fix-cs',
],
'6' => [
'label' => 'Verify coding standard violations are below thresholds.',
'command' => 'check-cs-thresholds',
],
];

$args = $event->getArguments();
if ( empty( $args ) ) {
foreach ( $choices as $choice => $data ) {
$io->write( \sprintf( '%d. %s', $choice, $data['label'] ) );
}

$choice = $io->ask( 'What do you want to do? ' );
}
else {
$choice = $args[0];
}

if ( isset( $choices[ $choice ] ) ) {
$event_dispatcher = $event->getComposer()->getEventDispatcher();
$event_dispatcher->dispatchScript( $choices[ $choice ]['command'] );
}
else {
$io->write( 'Unknown choice.' );
}
}

/**
* Runs PHPCS on the files changed in the current branch.
*
* Used by the composer check-branch-cs command.
*
* @codeCoverageIgnore
*
* @param Event $event Composer event that triggered this script.
*
* @return void
*/
public static function check_branch_cs( Event $event ) {
$branch = 'trunk';

$args = $event->getArguments();
if ( ! empty( $args ) ) {
$branch = $args[0];
}

exit( self::check_cs_for_changed_files( $branch ) );
}

/**
* Runs PHPCS on changed files compared to some git reference.
*
* @codeCoverageIgnore
*
* @param string $compare The git reference.
*
* @return int Exit code passed from the coding standards check.
*/
private static function check_cs_for_changed_files( $compare ) {
\exec( 'git diff --name-only --diff-filter=d ' . \escapeshellarg( $compare ), $files );

$php_files = self::filter_files( $files, '.php' );
if ( empty( $php_files ) ) {
echo 'No files to compare! Exiting.' . \PHP_EOL;

return 0;
}

/*
* In CI, generate both the normal report as well as the checkstyle report.
* The normal report will be shown in the actions output and ensures human readable (and colorized!) results there.
* The checkstyle report is used to show the results inline in the GitHub code view.
*/
$extra_args = ( \getenv( 'CI' ) === false ) ? '' : ' --colors --no-cache --report-full --report-checkstyle=./phpcs-report.xml';
$command = \sprintf(
'composer check-cs-warnings -- %s %s',
\implode( ' ', \array_map( 'escapeshellarg', $php_files ) ),
$extra_args
);
\system( $command, $exit_code );

return $exit_code;
}

/**
* Checks if the CS errors and warnings are below or at thresholds.
*
* @return void
*/
public static function check_cs_thresholds() {
$in_ci = \getenv( 'CI' );

echo 'Running coding standards checks, this may take some time.', \PHP_EOL;

$command = 'composer check-cs-warnings -- -mq --report="YoastCS\\Yoast\\Reports\\Threshold"';
if ( $in_ci !== false ) {
// Always show the results in CI in color.
$command .= ' --colors';
}
// phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged -- Non-WP context, this is fine.
@\exec( $command, $phpcs_output, $return );

$phpcs_output = \implode( \PHP_EOL, $phpcs_output );
echo $phpcs_output;

$above_threshold = true;
if ( \strpos( $phpcs_output, 'Coding standards checks have passed!' ) !== false ) {
$above_threshold = false;
}

/*
* Don't run the branch check in CI/GH Actions as it prevents the errors from being shown inline.
* The GH Actions script will run this via a separate script step.
*/
if ( $above_threshold === true && $in_ci === false ) {
echo \PHP_EOL;
echo 'Running check-branch-cs.', \PHP_EOL;
echo 'This might show problems on untouched lines. Focus on the lines you\'ve changed first.', \PHP_EOL;
echo \PHP_EOL;

// phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged -- Non-WP context, this is fine.
@\passthru( 'composer check-branch-cs' );
}

exit( ( $above_threshold === true || $return > 2 ) ? $return : 0 );
}

/**
* Filter files on extension.
*
* @param array<string> $files List of files.
* @param string $extension Extension to filter on.
*
* @return array<string> Filtered list of files.
*/
private static function filter_files( array $files, string $extension ): array {
return \array_filter(
$files,
static function ( $file ) use ( $extension ) {
return \substr( $file, ( 0 - \strlen( $extension ) ) ) === $extension;
}
);
}
}

0 comments on commit 14608d2

Please sign in to comment.