Skip to content

Commit 1a9e77c

Browse files
Shikha MishraShikha Mishra
authored andcommitted
m2 cpd action
0 parents  commit 1a9e77c

File tree

7 files changed

+291
-0
lines changed

7 files changed

+291
-0
lines changed

Dockerfile

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
FROM extdn/magento-integration-tests-action:7.4-latest AS builder
2+
RUN echo memory_limit = -1 >> /usr/local/etc/php/conf.d/custom-memory.ini
3+
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"
4+
WORKDIR "/var/www/magento2ce"
5+
RUN composer config --unset repo.0
6+
RUN composer config repo.foomanmirror composer https://repo-magento-mirror.fooman.co.nz/
7+
RUN composer install --prefer-dist
8+
9+
10+
FROM extdn/magento-integration-tests-action:7.4-latest
11+
COPY --from=builder /var/www/magento2ce/ /m2/
12+
RUN echo memory_limit = -1 >> /usr/local/etc/php/conf.d/custom-memory.ini
13+
ADD phpunit.phpcpd.xml /m2/dev/tests/static/phpunit.phpcpd.xml
14+
ADD PhpcpdRunner.php /m2/dev/tests/static/testsuite/Magento/Test/Php/PhpcpdRunner.php
15+
ADD LiveCodePhpcpdRunner.php /m2/dev/tests/static/framework/Magento/TestFramework/CodingStandard/Tool/LiveCodePhpcpdRunner.php
16+
17+
ADD entrypoint.sh /entrypoint.sh
18+
ENTRYPOINT ["/entrypoint.sh"]

LiveCodePhpcpdRunner.php

Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\TestFramework\CodingStandard\Tool;
9+
10+
use Magento\TestFramework\CodingStandard\ToolInterface;
11+
use SebastianBergmann\FileIterator\Facade;
12+
use SebastianBergmann\PHPCPD\Detector\Detector;
13+
use SebastianBergmann\PHPCPD\Detector\Strategy\DefaultStrategy;
14+
use SebastianBergmann\PHPCPD\Log\PMD;
15+
use SebastianBergmann\PHPCPD\Log\Text;
16+
use Symfony\Component\Finder\Finder;
17+
18+
/**
19+
* PHP Copy Paste Detector tool wrapper
20+
*/
21+
class LiveCodePhpcpdRunner implements ToolInterface, BlacklistInterface
22+
{
23+
/**
24+
* Minimum number of equal lines to identify a copy paste snippet
25+
*/
26+
private const MIN_LINES = 13;
27+
28+
/**
29+
* Destination file to write inspection report to
30+
*
31+
* @var string
32+
*/
33+
private $reportFile;
34+
35+
/**
36+
* List of paths to be excluded from tool run
37+
*
38+
* @var array
39+
*/
40+
private $blacklist;
41+
42+
/**
43+
* @param string $reportFile
44+
*/
45+
public function __construct(string $reportFile)
46+
{
47+
$this->reportFile = $reportFile;
48+
}
49+
50+
/**
51+
* @inheritdoc
52+
*/
53+
public function setBlackList(array $blackList): void
54+
{
55+
$this->blacklist = $blackList;
56+
}
57+
58+
/**
59+
* Whether the tool can be run in the current environment
60+
*
61+
* @SuppressWarnings(PHPMD.UnusedLocalVariable)
62+
*
63+
* @return bool
64+
*/
65+
public function canRun(): bool
66+
{
67+
return class_exists(Detector::class)
68+
&& class_exists(Facade::class)
69+
&& class_exists(Finder::class);
70+
}
71+
72+
/**
73+
* Run tool for files specified
74+
*
75+
* @param array $whiteList Files/directories to be inspected
76+
* @return bool
77+
*/
78+
public function run(array $whiteList): bool
79+
{
80+
$clones = (new Detector(new DefaultStrategy()))->copyPasteDetection(
81+
(new Facade())->getFilesAsArray(
82+
$whiteList,
83+
'',
84+
'',
85+
$this->getExclude()
86+
),
87+
self::MIN_LINES
88+
);
89+
90+
(new PMD($this->reportFile))->processClones($clones);
91+
(new Text)->printResult($clones, false);
92+
93+
return count($clones) === 0;
94+
}
95+
96+
/**
97+
* Get exclude params from blacklist
98+
*
99+
* @return string[]
100+
*/
101+
private function getExclude(): array
102+
{
103+
$exclude = [];
104+
$blacklistedDirs = [];
105+
$blacklistedFileNames = [];
106+
$blacklistedPatterns = [];
107+
foreach ($this->blacklist as $file) {
108+
$file = trim($file);
109+
if (!$file) {
110+
continue;
111+
}
112+
$realPath = realpath(BP . '/' . $file);
113+
if ($realPath === false) {
114+
$ext = pathinfo($file, PATHINFO_EXTENSION);
115+
if ($ext != '') {
116+
$blacklistedFileNames[] = $file;
117+
} else {
118+
$blacklistedPatterns[] = $file;
119+
}
120+
continue;
121+
}
122+
123+
$exclude[] = [$realPath];
124+
$blacklistedDirs[] = $file;
125+
}
126+
127+
foreach ($blacklistedPatterns as $pattern) {
128+
$files = $this->find($pattern, false, $blacklistedDirs);
129+
if (empty($files)) {
130+
continue;
131+
}
132+
$exclude[] = $files;
133+
}
134+
135+
136+
foreach ($blacklistedFileNames as $fileName) {
137+
$files = $this->find($fileName, true, $blacklistedDirs);
138+
if (empty($files)) {
139+
continue;
140+
}
141+
$exclude[] = $files;
142+
}
143+
144+
return array_unique(array_merge(...$exclude));
145+
}
146+
147+
/**
148+
* Find all files by pattern
149+
*
150+
* @param string $pattern
151+
* @param bool $searchFiles
152+
* @param array $excludePaths
153+
* @return array
154+
*/
155+
private function find(string $pattern, bool $searchFiles, array $excludePaths): array
156+
{
157+
$finder = new Finder();
158+
$finder->in(BP);
159+
$finder->notPath($excludePaths);
160+
if ($searchFiles) {
161+
$finder->files();
162+
$finder->name($pattern);
163+
} else {
164+
$finder->path($pattern);
165+
}
166+
167+
$result = [];
168+
foreach ($finder as $file) {
169+
$result[] = $file->getRealPath();
170+
}
171+
172+
return $result;
173+
}
174+
}

PhpcpdRunner.php

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\Test\Php;
9+
10+
use Magento\Framework\App\Utility\Files;
11+
use Magento\TestFramework\CodingStandard\Tool\LiveCodePhpcpdRunner;
12+
use PHPMD\TextUI\Command;
13+
14+
/**
15+
* Set of tests for static code analysis, e.g. code style, code complexity, copy paste detecting, etc.
16+
*/
17+
class PhpcpdRunner extends \PHPUnit\Framework\TestCase
18+
{
19+
/**
20+
* @var string
21+
*/
22+
protected static $reportDir = '';
23+
24+
/**
25+
* @var string
26+
*/
27+
protected static $pathToSource = '';
28+
29+
/**
30+
* Setup basics for all tests
31+
*
32+
* @return void
33+
*/
34+
public static function setUpBeforeClass(): void
35+
{
36+
self::$pathToSource = BP;
37+
self::$reportDir = self::$pathToSource . '/dev/tests/static/report';
38+
if (!is_dir(self::$reportDir)) {
39+
mkdir(self::$reportDir);
40+
}
41+
}
42+
43+
/**
44+
* Test code quality using phpcpd
45+
*/
46+
public function testCopyPaste()
47+
{
48+
$reportFile = self::$reportDir . '/phpcpd_report.xml';
49+
$copyPasteDetector = new LiveCodePhpcpdRunner($reportFile);
50+
51+
if (!$copyPasteDetector->canRun()) {
52+
$this->markTestSkipped('PHP Copy/Paste Detector is not available.');
53+
}
54+
55+
$blackList = [];
56+
foreach (glob(__DIR__ . '/_files/phpcpd/blacklist/*.txt') as $list) {
57+
$blackList[] = file($list, FILE_IGNORE_NEW_LINES);
58+
}
59+
$blackList = array_merge([], ...$blackList);
60+
61+
$copyPasteDetector->setBlackList($blackList);
62+
63+
$result = $copyPasteDetector->run([BP]);
64+
65+
$output = file_exists($reportFile) ? file_get_contents($reportFile) : '';
66+
67+
$this->assertTrue(
68+
$result,
69+
"PHP Copy/Paste Detector has found error(s):" . PHP_EOL . $output
70+
);
71+
}
72+
73+
}
74+

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Magento2 CPD action

action.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
name: 'Magento 2 Copy Paste Detector'
2+
description: 'performs php static code analysis with the Magento 2 Copy Paste Detector ruleset'
3+
runs:
4+
using: 'docker'
5+
image: 'Dockerfile'
6+
branding:
7+
icon: 'code'
8+
color: 'green'

entrypoint.sh

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
#!/bin/sh -l
2+
sh -c "cd /m2/dev/tests/static && /m2/vendor/bin/phpunit -c /m2/dev/tests/static/phpunit.phpmd.xml $*"

phpunit.phpcpd.xml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/6.2/phpunit.xsd"
4+
colors="true"
5+
columns="max"
6+
beStrictAboutTestsThatDoNotTestAnything="false"
7+
bootstrap="./framework/bootstrap.php"
8+
>
9+
<testsuites>
10+
<testsuite name="phpmd-m2">
11+
<file>testsuite/Magento/Test/Php/PhpcpdRunner.php</file>
12+
</testsuite>
13+
</testsuites>
14+
</phpunit>

0 commit comments

Comments
 (0)