Skip to content

Commit

Permalink
m2 cpd action
Browse files Browse the repository at this point in the history
  • Loading branch information
Shikha Mishra authored and Shikha Mishra committed Jul 13, 2021
0 parents commit 1a9e77c
Show file tree
Hide file tree
Showing 7 changed files with 291 additions and 0 deletions.
18 changes: 18 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
FROM extdn/magento-integration-tests-action:7.4-latest AS builder
RUN echo memory_limit = -1 >> /usr/local/etc/php/conf.d/custom-memory.ini
RUN composer create-project --repository=https://repo-magento-mirror.fooman.co.nz/ --no-plugins --no-install --no-interaction magento/project-community-edition /var/www/magento2ce "2.4.1"
WORKDIR "/var/www/magento2ce"
RUN composer config --unset repo.0
RUN composer config repo.foomanmirror composer https://repo-magento-mirror.fooman.co.nz/
RUN composer install --prefer-dist


FROM extdn/magento-integration-tests-action:7.4-latest
COPY --from=builder /var/www/magento2ce/ /m2/
RUN echo memory_limit = -1 >> /usr/local/etc/php/conf.d/custom-memory.ini
ADD phpunit.phpcpd.xml /m2/dev/tests/static/phpunit.phpcpd.xml
ADD PhpcpdRunner.php /m2/dev/tests/static/testsuite/Magento/Test/Php/PhpcpdRunner.php
ADD LiveCodePhpcpdRunner.php /m2/dev/tests/static/framework/Magento/TestFramework/CodingStandard/Tool/LiveCodePhpcpdRunner.php

ADD entrypoint.sh /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
174 changes: 174 additions & 0 deletions LiveCodePhpcpdRunner.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);

namespace Magento\TestFramework\CodingStandard\Tool;

use Magento\TestFramework\CodingStandard\ToolInterface;
use SebastianBergmann\FileIterator\Facade;
use SebastianBergmann\PHPCPD\Detector\Detector;
use SebastianBergmann\PHPCPD\Detector\Strategy\DefaultStrategy;
use SebastianBergmann\PHPCPD\Log\PMD;
use SebastianBergmann\PHPCPD\Log\Text;
use Symfony\Component\Finder\Finder;

/**
* PHP Copy Paste Detector tool wrapper
*/
class LiveCodePhpcpdRunner implements ToolInterface, BlacklistInterface
{
/**
* Minimum number of equal lines to identify a copy paste snippet
*/
private const MIN_LINES = 13;

/**
* Destination file to write inspection report to
*
* @var string
*/
private $reportFile;

/**
* List of paths to be excluded from tool run
*
* @var array
*/
private $blacklist;

/**
* @param string $reportFile
*/
public function __construct(string $reportFile)
{
$this->reportFile = $reportFile;
}

/**
* @inheritdoc
*/
public function setBlackList(array $blackList): void
{
$this->blacklist = $blackList;
}

/**
* Whether the tool can be run in the current environment
*
* @SuppressWarnings(PHPMD.UnusedLocalVariable)
*
* @return bool
*/
public function canRun(): bool
{
return class_exists(Detector::class)
&& class_exists(Facade::class)
&& class_exists(Finder::class);
}

/**
* Run tool for files specified
*
* @param array $whiteList Files/directories to be inspected
* @return bool
*/
public function run(array $whiteList): bool
{
$clones = (new Detector(new DefaultStrategy()))->copyPasteDetection(
(new Facade())->getFilesAsArray(
$whiteList,
'',
'',
$this->getExclude()
),
self::MIN_LINES
);

(new PMD($this->reportFile))->processClones($clones);
(new Text)->printResult($clones, false);

return count($clones) === 0;
}

/**
* Get exclude params from blacklist
*
* @return string[]
*/
private function getExclude(): array
{
$exclude = [];
$blacklistedDirs = [];
$blacklistedFileNames = [];
$blacklistedPatterns = [];
foreach ($this->blacklist as $file) {
$file = trim($file);
if (!$file) {
continue;
}
$realPath = realpath(BP . '/' . $file);
if ($realPath === false) {
$ext = pathinfo($file, PATHINFO_EXTENSION);
if ($ext != '') {
$blacklistedFileNames[] = $file;
} else {
$blacklistedPatterns[] = $file;
}
continue;
}

$exclude[] = [$realPath];
$blacklistedDirs[] = $file;
}

foreach ($blacklistedPatterns as $pattern) {
$files = $this->find($pattern, false, $blacklistedDirs);
if (empty($files)) {
continue;
}
$exclude[] = $files;
}


foreach ($blacklistedFileNames as $fileName) {
$files = $this->find($fileName, true, $blacklistedDirs);
if (empty($files)) {
continue;
}
$exclude[] = $files;
}

return array_unique(array_merge(...$exclude));
}

/**
* Find all files by pattern
*
* @param string $pattern
* @param bool $searchFiles
* @param array $excludePaths
* @return array
*/
private function find(string $pattern, bool $searchFiles, array $excludePaths): array
{
$finder = new Finder();
$finder->in(BP);
$finder->notPath($excludePaths);
if ($searchFiles) {
$finder->files();
$finder->name($pattern);
} else {
$finder->path($pattern);
}

$result = [];
foreach ($finder as $file) {
$result[] = $file->getRealPath();
}

return $result;
}
}
74 changes: 74 additions & 0 deletions PhpcpdRunner.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);

namespace Magento\Test\Php;

use Magento\Framework\App\Utility\Files;
use Magento\TestFramework\CodingStandard\Tool\LiveCodePhpcpdRunner;
use PHPMD\TextUI\Command;

/**
* Set of tests for static code analysis, e.g. code style, code complexity, copy paste detecting, etc.
*/
class PhpcpdRunner extends \PHPUnit\Framework\TestCase
{
/**
* @var string
*/
protected static $reportDir = '';

/**
* @var string
*/
protected static $pathToSource = '';

/**
* Setup basics for all tests
*
* @return void
*/
public static function setUpBeforeClass(): void
{
self::$pathToSource = BP;
self::$reportDir = self::$pathToSource . '/dev/tests/static/report';
if (!is_dir(self::$reportDir)) {
mkdir(self::$reportDir);
}
}

/**
* Test code quality using phpcpd
*/
public function testCopyPaste()
{
$reportFile = self::$reportDir . '/phpcpd_report.xml';
$copyPasteDetector = new LiveCodePhpcpdRunner($reportFile);

if (!$copyPasteDetector->canRun()) {
$this->markTestSkipped('PHP Copy/Paste Detector is not available.');
}

$blackList = [];
foreach (glob(__DIR__ . '/_files/phpcpd/blacklist/*.txt') as $list) {
$blackList[] = file($list, FILE_IGNORE_NEW_LINES);
}
$blackList = array_merge([], ...$blackList);

$copyPasteDetector->setBlackList($blackList);

$result = $copyPasteDetector->run([BP]);

$output = file_exists($reportFile) ? file_get_contents($reportFile) : '';

$this->assertTrue(
$result,
"PHP Copy/Paste Detector has found error(s):" . PHP_EOL . $output
);
}

}

1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Magento2 CPD action
8 changes: 8 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
name: 'Magento 2 Copy Paste Detector'
description: 'performs php static code analysis with the Magento 2 Copy Paste Detector ruleset'
runs:
using: 'docker'
image: 'Dockerfile'
branding:
icon: 'code'
color: 'green'
2 changes: 2 additions & 0 deletions entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#!/bin/sh -l
sh -c "cd /m2/dev/tests/static && /m2/vendor/bin/phpunit -c /m2/dev/tests/static/phpunit.phpmd.xml $*"
14 changes: 14 additions & 0 deletions phpunit.phpcpd.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/6.2/phpunit.xsd"
colors="true"
columns="max"
beStrictAboutTestsThatDoNotTestAnything="false"
bootstrap="./framework/bootstrap.php"
>
<testsuites>
<testsuite name="phpmd-m2">
<file>testsuite/Magento/Test/Php/PhpcpdRunner.php</file>
</testsuite>
</testsuites>
</phpunit>

0 comments on commit 1a9e77c

Please sign in to comment.