Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Composer: implement CS menu and extra commands #212

Merged
merged 1 commit into from
Dec 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#
/.cache export-ignore
/.github export-ignore
/config export-ignore
/grunt export-ignore
/svn-assets export-ignore
.gitattributes export-ignore
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/cs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,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
29 changes: 28 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@
"src/"
]
},
"autoload-dev": {
"classmap": [
"config/"
]
},
"config": {
"allow-plugins": {
"dealerdirect/phpcodesniffer-composer-installer": true
Expand All @@ -37,16 +42,38 @@
"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\\Test_Helper\\Config\\Composer\\Actions::check_coding_standards"
],
"check-cs-thresholds": [
"@putenv YOASTCS_THRESHOLD_ERRORS=0",
"@putenv YOASTCS_THRESHOLD_WARNINGS=0",
"Yoast\\WP\\Test_Helper\\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\\Test_Helper\\Config\\Composer\\Actions::check_branch_cs"
],
"fix-cs": [
"@php ./vendor/squizlabs/php_codesniffer/bin/phpcbf"
]
},
"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."
}
}
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\Test_Helper\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 = 'develop';

$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;
}
);
}
}