diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..b57e18d --- /dev/null +++ b/Dockerfile @@ -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"] \ No newline at end of file diff --git a/LiveCodePhpcpdRunner.php b/LiveCodePhpcpdRunner.php new file mode 100644 index 0000000..94a74c8 --- /dev/null +++ b/LiveCodePhpcpdRunner.php @@ -0,0 +1,174 @@ +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; + } +} \ No newline at end of file diff --git a/PhpcpdRunner.php b/PhpcpdRunner.php new file mode 100644 index 0000000..388981d --- /dev/null +++ b/PhpcpdRunner.php @@ -0,0 +1,74 @@ +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 + ); + } + +} + diff --git a/README.md b/README.md new file mode 100644 index 0000000..c9a7ff1 --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +Magento2 CPD action \ No newline at end of file diff --git a/action.yml b/action.yml new file mode 100644 index 0000000..961e56c --- /dev/null +++ b/action.yml @@ -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' \ No newline at end of file diff --git a/entrypoint.sh b/entrypoint.sh new file mode 100644 index 0000000..e44ba91 --- /dev/null +++ b/entrypoint.sh @@ -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 $*" \ No newline at end of file diff --git a/phpunit.phpcpd.xml b/phpunit.phpcpd.xml new file mode 100644 index 0000000..380d081 --- /dev/null +++ b/phpunit.phpcpd.xml @@ -0,0 +1,14 @@ + + + + + testsuite/Magento/Test/Php/PhpcpdRunner.php + + + \ No newline at end of file