Skip to content

Commit

Permalink
Merge pull request #348 from Yoast/JRF/add-cs-menu
Browse files Browse the repository at this point in the history
Composer: implement CS menu and extra commands
  • Loading branch information
jrfnl authored Dec 16, 2023
2 parents 769d980 + 14608d2 commit 6c54b9b
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 6c54b9b

Please sign in to comment.