diff --git a/.gitattributes b/.gitattributes index 195d20e..f7e494e 100644 --- a/.gitattributes +++ b/.gitattributes @@ -5,4 +5,3 @@ /*baseline* export-ignore /composer.lock export-ignore /Makefile export-ignore -/package.json export-ignore diff --git a/infection.json.dist b/infection.json.dist new file mode 100644 index 0000000..9906e55 --- /dev/null +++ b/infection.json.dist @@ -0,0 +1,17 @@ +{ + "source": { + "directories": [ + "src" + ] + }, + "logs": { + "text": "var/phpqa/infection.log" + }, + "minCoveredMsi": 100, + "mutators": { + "@default": true, + "IdenticalEqual": false, + "NotIdenticalNotEqual": false, + "MBString": false + } +} diff --git a/phpstan.baseline.neon b/phpstan.baseline.neon deleted file mode 100644 index b61515a..0000000 --- a/phpstan.baseline.neon +++ /dev/null @@ -1,46 +0,0 @@ -parameters: - ignoreErrors: - - - message: "#^Method Sigwin\\\\Infra\\\\Test\\\\Functional\\\\MakefileTestCase\\:\\:dryRun\\(\\) has parameter \\$args with no value type specified in iterable type array\\.$#" - count: 1 - path: tests/functional/MakefileTestCase.php - - - - message: "#^Method Sigwin\\\\Infra\\\\Test\\\\Functional\\\\MakefileTestCase\\:\\:dryRun\\(\\) return type has no value type specified in iterable type array\\.$#" - count: 1 - path: tests/functional/MakefileTestCase.php - - - - message: "#^Method Sigwin\\\\Infra\\\\Test\\\\Functional\\\\MakefileTestCase\\:\\:execute\\(\\) has parameter \\$args with no value type specified in iterable type array\\.$#" - count: 1 - path: tests/functional/MakefileTestCase.php - - - - message: "#^Method Sigwin\\\\Infra\\\\Test\\\\Functional\\\\MakefileTestCase\\:\\:generateHelpExecutionPath\\(\\) has parameter \\$additionalFiles with no value type specified in iterable type array\\.$#" - count: 1 - path: tests/functional/MakefileTestCase.php - - - - message: "#^Method Sigwin\\\\Infra\\\\Test\\\\Functional\\\\MakefileTestCase\\:\\:generateHelpExecutionPath\\(\\) has parameter \\$files with no value type specified in iterable type array\\.$#" - count: 1 - path: tests/functional/MakefileTestCase.php - - - - message: "#^Method Sigwin\\\\Infra\\\\Test\\\\Functional\\\\MakefileTestCase\\:\\:generateHelpList\\(\\) has parameter \\$commands with no value type specified in iterable type array\\.$#" - count: 1 - path: tests/functional/MakefileTestCase.php - - - - message: "#^Method Sigwin\\\\Infra\\\\Test\\\\Functional\\\\MakefileTestCase\\:\\:generatePermissionsExecutionPath\\(\\) has parameter \\$dirs with no value type specified in iterable type array\\.$#" - count: 1 - path: tests/functional/MakefileTestCase.php - - - - message: "#^Method Sigwin\\\\Infra\\\\Test\\\\Functional\\\\MakefileTestCase\\:\\:generatePermissionsExecutionPath\\(\\) return type has no value type specified in iterable type array\\.$#" - count: 1 - path: tests/functional/MakefileTestCase.php - - - - message: "#^Method Sigwin\\\\Infra\\\\Test\\\\Functional\\\\MakefileTestCase\\:\\:testMakefileCommandsWork\\(\\) has parameter \\$expected with no value type specified in iterable type array\\.$#" - count: 1 - path: tests/functional/MakefileTestCase.php diff --git a/phpstan.neon.dist b/phpstan.neon.dist index cc73114..452a2f8 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -3,7 +3,6 @@ includes: - /tools/.composer/vendor-bin/phpstan/vendor/phpstan/phpstan-strict-rules/rules.neon - /tools/.composer/vendor-bin/phpstan/vendor/phpstan/phpstan-phpunit/extension.neon - /tools/.composer/vendor-bin/phpstan/vendor/phpstan/phpstan-symfony/extension.neon - - phpstan.baseline.neon parameters: tmpDir: %currentWorkingDirectory%/var/phpqa/phpstan level: max diff --git a/psalm.baseline.xml b/psalm.baseline.xml deleted file mode 100644 index 4c39daa..0000000 --- a/psalm.baseline.xml +++ /dev/null @@ -1,135 +0,0 @@ - - - - - $command - $dir - $dir - $dir - $dir - $dir - $dir - $dir - $dir - $dir - $files - - - $files - $files - - - - $command - $dir - - - array_values - - - - - - - - - - - - - - - - - - $helpOverride - - - - - - - - - - - - - - - - - iterable - - - >]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - $helpOverride - - - - - - - - - - - $helpOverride - - - - - - - diff --git a/psalm.xml.dist b/psalm.xml.dist index 80924f6..dedde2f 100644 --- a/psalm.xml.dist +++ b/psalm.xml.dist @@ -4,7 +4,6 @@ checkForThrowsInGlobalScope="true" ensureArrayIntOffsetsExist="true" ensureArrayStringOffsetsExist="true" - errorBaseline="psalm.baseline.xml" errorLevel="1" findUnusedBaselineEntry="true" findUnusedCode="true" diff --git a/resources/Lighthouse/common.mk b/resources/Lighthouse/common.mk index 4e3254d..c320f5f 100644 --- a/resources/Lighthouse/common.mk +++ b/resources/Lighthouse/common.mk @@ -1,4 +1,4 @@ -LIGHTHOUSE_DOCKER_IMAGE ?= cypress/browsers:node-20.9.0-chrome-118.0.5993.88-1-ff-118.0.2-edge-118.0.2088.46-1 +LIGHTHOUSE_DOCKER_IMAGE ?= cypress/browsers:node-20.10.0-chrome-118.0.5993.88-1-ff-118.0.2-edge-118.0.2088.46-1 LIGHTHOUSE_DOCKER_COMMAND ?= docker run --init --interactive ${DOCKER_TTY} --rm --env HOME=/tmp ${DOCKER_USER} --volume "${DOCKER_CWD}:/public" --workdir "/public" ${LIGHTHOUSE_DOCKER_IMAGE} analyze/lighthouse: ## Analyze built files using Lighthouse diff --git a/resources/PHP/common.mk b/resources/PHP/common.mk index ae2136a..a1433d5 100644 --- a/resources/PHP/common.mk +++ b/resources/PHP/common.mk @@ -8,7 +8,7 @@ PHP_VERSION=8.3 endif ifndef PHPQA_DOCKER_IMAGE -PHPQA_DOCKER_IMAGE=jakzal/phpqa:1.93.0-php${PHP_VERSION}-alpine +PHPQA_DOCKER_IMAGE=jakzal/phpqa:1.95.1-php${PHP_VERSION}-alpine endif ifndef PHPQA_DOCKER_COMMAND diff --git a/resources/Visual/common.mk b/resources/Visual/common.mk index 8e59ad8..b95bf69 100644 --- a/resources/Visual/common.mk +++ b/resources/Visual/common.mk @@ -3,7 +3,7 @@ $(error BASE_URL must be defined before loading Visual/common.mk) endif PROJECT_ROOT = ${DOCKER_CWD} -BACKSTOP_DOCKER_IMAGE ?= backstopjs/backstopjs:6.2.2 +BACKSTOP_DOCKER_IMAGE ?= backstopjs/backstopjs:6.3.3 BACKSTOP_DOCKER_COMMAND ?= docker run --init --interactive ${TTY} --shm-size 256MB --cap-add=SYS_ADMIN --rm --env PROJECT_ROOT=${PROJECT_ROOT} --env BASE_URL=${BASE_URL} ${DOCKER_USER} --tmpfs /tmp --volume "${PROJECT_ROOT}:${PROJECT_ROOT}" --workdir "${PROJECT_ROOT}" ${BACKSTOP_DOCKER_IMAGE} --config backstop.config.js visual/test: ${BACKSTOP_DOCKER_COMMAND} test diff --git a/tests/functional/MakefileTestCase.php b/tests/functional/MakefileTestCase.php index 267b4ca..295de8f 100644 --- a/tests/functional/MakefileTestCase.php +++ b/tests/functional/MakefileTestCase.php @@ -100,7 +100,7 @@ public function testHelpIsTheDefaultCommand(): void public function testMakefileHasInit(): void { $expected = array_map(static fn (string $path): string => sprintf('if [ -d "$ROOT/resources/%1$s" ]; then cp -a $ROOT/resources/%1$s/. .; fi', $path), $this->getExpectedInitPaths()); - $expected = array_merge(...array_values(array_map(static fn ($value) => [$value, 'if [ -f .gitattributes.dist ]; then mv .gitattributes.dist .gitattributes; fi'], $expected))); + $expected = array_merge(...array_map(static fn ($value) => [$value, 'if [ -f .gitattributes.dist ]; then mv .gitattributes.dist .gitattributes; fi'], $expected)); $actual = self::dryRun('init'); self::assertSame($expected, $actual); @@ -109,6 +109,7 @@ public function testMakefileHasInit(): void /** * @dataProvider provideMakefileCommandsWorkCases * + * @param list $expected * @param array $env */ public function testMakefileCommandsWork(string $command, array $expected, array $env): void @@ -131,17 +132,24 @@ protected function getExpectedHelp(): string return $this->generateHelpList(array_keys(static::getExpectedHelpCommandsExecutionPath([]))); } + /** + * @param list $commands + */ protected function generateHelpList(array $commands): string { $help = []; sort($commands); foreach ($commands as $command) { - $help[] = sprintf('%1$s[45m%2$s%1$s[0m %3$s', "\e", str_pad($command, 20), $this->helpOverride[$command] ?? $this->help[$command] ?? ''); + $help[] = sprintf('%1$s[45m%2$s%1$s[0m %3$s', "\e", mb_str_pad($command, 20), $this->helpOverride[$command] ?? $this->help[$command] ?? ''); } return implode("\n", $help)."\n"; } + /** + * @param list $files + * @param list $additionalFiles + */ protected static function generateHelpExecutionPath(array $files = [], array $additionalFiles = []): string { $files = array_merge($files, [ @@ -154,7 +162,10 @@ protected static function generateHelpExecutionPath(array $files = [], array $ad $command = match (\PHP_OS_FAMILY) { 'Darwin' => 'grep --no-filename --extended-regexp \'^ *[-a-zA-Z0-9_/]+ *:.*## \' '.implode(' ', $files).' | awk \'BEGIN {FS = ":.*?## "}; {printf "\033[45m%-20s\033[0m %s\n", $1, $2}\' | sort', 'Linux' => 'grep -h -E \'^ *[-a-zA-Z0-9_/]+ *:.*## \' '.implode(' ', $files).' | awk \'BEGIN {FS = ":.*?## "}; {printf "\033[45m%-20s\033[0m %s\n", $1, $2}\' | sort', - 'Windows' => 'Select-String -Pattern \'^ *(?[-a-zA-Z0-9_/]+) *:.*## *(?.+)\' '.implode(',', array_map(static function (string $item, int $index): string { + 'Windows' => 'Select-String -Pattern \'^ *(?[-a-zA-Z0-9_/]+) *:.*## *(?.+)\' '.implode(',', array_map(static function (false|string $item, int $index): string { + if ($item === false) { + throw new \LogicException('Invalid item'); + } if ($index === 0) { return $item; } @@ -167,6 +178,11 @@ protected static function generateHelpExecutionPath(array $files = [], array $ad return self::normalize($command); } + /** + * @param list $dirs + * + * @return list + */ protected static function generatePermissionsExecutionPath(array $dirs): array { $commands = []; @@ -221,7 +237,13 @@ protected static function getMakefilePath(): string } /** + * @param list $args * @param null|array $env + * + * @return list + * + * @psalm-suppress MoreSpecificReturnType + * @psalm-suppress LessSpecificReturnStatement */ protected static function dryRun( ?string $makeCommand = null, @@ -236,6 +258,7 @@ protected static function dryRun( } /** + * @param list $args * @param null|array $env */ protected static function execute( diff --git a/tests/functional/PHP/PharTest.php b/tests/functional/PHP/PharTest.php index a214908..77f8490 100644 --- a/tests/functional/PHP/PharTest.php +++ b/tests/functional/PHP/PharTest.php @@ -26,6 +26,9 @@ final class PharTest extends MakefileTestCase { use PhpTrait; + /** + * @var array + */ protected array $helpOverride = [ 'phar/build' => 'Build PHAR file', ]; diff --git a/tests/functional/PHP/PhpTrait.php b/tests/functional/PHP/PhpTrait.php index 858db7b..d9d51f7 100644 --- a/tests/functional/PHP/PhpTrait.php +++ b/tests/functional/PHP/PhpTrait.php @@ -15,6 +15,9 @@ trait PhpTrait { + /** + * @return iterable> + */ protected static function getEnvs(): iterable { yield ['PHP_VERSION' => '8.1']; @@ -28,13 +31,44 @@ protected static function getEnvs(): iterable /** * @param null|array $env * - * @return array> + * @return array{ + * analyze: list, + * prepareAndAnalyze: list, + * "box: build": list, + * "build: dev": list, + * "build: prod": list, + * "composer: install": list, + * "composer: install-lowest": list, + * "composer: install-highest": list, + * "docker compose: start app dev": list, + * "docker compose: start app prod": list, + * "docker compose: start app test": list, + * "docker compose: start app": list, + * "docker compose: start library test": list, + * "docker compose: stop Pimcore app": list, + * "docker compose: stop Pimcore library": list, + * "permissions: Pimcore": list, + * "setup: Pimcore app test": list, + * "setup: Pimcore library test": list, + * "shell: app": list, + * "shell: app library": list, + * "shell: PHP": list, + * "test: unit": list, + * "test: functional app": list, + * "test: functional library": list, + * "mkdir: composer": list, + * "mkdir: phpqa": list, + * "touch: .env": list, + * "touch: composer.lock": list, + * "clean: Pimcore application": list, + * "clean: library": list + * } */ private static function paths(?array $env): array { // defaults which are also defined in the Makefile $phpVersion = $env['PHP_VERSION'] ?? '8.3'; - $phpqaDockerImage = $env['PHPQA_DOCKER_IMAGE'] ?? 'jakzal/phpqa:1.93.0-php%1$s-alpine'; + $phpqaDockerImage = $env['PHPQA_DOCKER_IMAGE'] ?? 'jakzal/phpqa:1.95.1-php%1$s-alpine'; return [ 'analyze' => [ diff --git a/tests/functional/YASSG/CompatTest.php b/tests/functional/YASSG/CompatTest.php index 6a8488f..d954087 100644 --- a/tests/functional/YASSG/CompatTest.php +++ b/tests/functional/YASSG/CompatTest.php @@ -27,6 +27,9 @@ final class CompatTest extends MakefileTestCase { use PhpTrait; + /** + * @var array + */ protected array $helpOverride = [ 'start' => 'Start app in APP_ENV mode (defaults to "dev")', ]; @@ -118,7 +121,7 @@ public function testDevComposeWorks(): void private static function generateDockerBackstopExecutionPath(string $command): string { return sprintf( - 'docker run --init --interactive --shm-size 256MB --cap-add=SYS_ADMIN --rm --env PROJECT_ROOT=$ROOT --env BASE_URL=file://localhost$ROOT/public %2$s --tmpfs /tmp --volume "$ROOT:$ROOT" --workdir "$ROOT" backstopjs/backstopjs:6.2.2 --config backstop.config.js %1$s', + 'docker run --init --interactive --shm-size 256MB --cap-add=SYS_ADMIN --rm --env PROJECT_ROOT=$ROOT --env BASE_URL=file://localhost$ROOT/public %2$s --tmpfs /tmp --volume "$ROOT:$ROOT" --workdir "$ROOT" backstopjs/backstopjs:6.3.3 --config backstop.config.js %1$s', $command, self::generateDockerComposeExecutionUser() ); @@ -127,7 +130,7 @@ private static function generateDockerBackstopExecutionPath(string $command): st private static function generateDockerLighthouseExecutionPath(string $command): string { return sprintf( - 'docker run --init --interactive --rm --env HOME=/tmp %2$s --volume "$ROOT:/public" --workdir "/public" cypress/browsers:node-20.9.0-chrome-118.0.5993.88-1-ff-118.0.2-edge-118.0.2088.46-1 %1$s', + 'docker run --init --interactive --rm --env HOME=/tmp %2$s --volume "$ROOT:/public" --workdir "/public" cypress/browsers:node-20.10.0-chrome-118.0.5993.88-1-ff-118.0.2-edge-118.0.2088.46-1 %1$s', $command, self::generateDockerComposeExecutionUser() ); diff --git a/tests/functional/YASSG/DefaultTest.php b/tests/functional/YASSG/DefaultTest.php index 6dc8089..865bc48 100644 --- a/tests/functional/YASSG/DefaultTest.php +++ b/tests/functional/YASSG/DefaultTest.php @@ -27,6 +27,9 @@ final class DefaultTest extends MakefileTestCase { use PhpTrait; + /** + * @var array + */ protected array $helpOverride = [ 'start' => 'Start app in APP_ENV mode (defaults to "dev")', 'build/docker' => 'Build app for "APP_ENV" target (defaults to "prod") fully in Docker',