From 30cdf17f8a9eb602bf0cecf8484e0b7671ae7a1b Mon Sep 17 00:00:00 2001 From: Jesse Rushlow <40327885+jrushlow@users.noreply.github.com> Date: Fri, 5 Apr 2024 13:54:34 -0400 Subject: [PATCH] minor #1498 [ci] implement phpstan for static analysis of the codebase --- .github/workflows/ci-linux.yaml | 43 ----------- .github/workflows/ci-static-analysis.yaml | 81 +++++++++++++++++++++ phpstan.dist.neon | 26 +++++++ src/Maker/MakeEntity.php | 2 +- src/Maker/MakeUser.php | 1 + tests/Maker/FunctionalTest.php | 2 +- tests/Maker/MakeEntityTest.php | 1 + tests/Maker/MakeFormTest.php | 4 +- tests/Maker/MakeMessageTest.php | 6 +- tests/Maker/MakeMessengerMiddlewareTest.php | 2 +- tests/Maker/MakeSerializerEncoderTest.php | 2 +- tests/Maker/MakeTwigExtensionTest.php | 2 +- tests/Maker/MakeUnitTestTest.php | 2 +- tests/Maker/MakeValidatorTest.php | 2 +- tests/Maker/MakeVoterTest.php | 2 +- tools/phpstan/composer.json | 14 ++++ tools/phpstan/includes/.gitignore | 3 + tools/phpstan/includes/composer.json | 22 ++++++ 18 files changed, 161 insertions(+), 56 deletions(-) create mode 100644 .github/workflows/ci-static-analysis.yaml create mode 100644 phpstan.dist.neon create mode 100644 tools/phpstan/composer.json create mode 100644 tools/phpstan/includes/.gitignore create mode 100644 tools/phpstan/includes/composer.json diff --git a/.github/workflows/ci-linux.yaml b/.github/workflows/ci-linux.yaml index b771d6ee8..3fb00b6b8 100644 --- a/.github/workflows/ci-linux.yaml +++ b/.github/workflows/ci-linux.yaml @@ -13,49 +13,6 @@ env: SYMFONY_PHPUNIT_DIR: "$HOME/symfony-bridge/.phpunit" jobs: - coding-standards: - name: "Coding Standards (${{ matrix.php-version }})" - - runs-on: ubuntu-latest - - strategy: - fail-fast: false - matrix: - php-version: - - '8.1' - - steps: - - - name: Checkout code - uses: "actions/checkout@v3" - - - - name: Install PHP - uses: "shivammathur/setup-php@v2" - with: - coverage: "none" - php-version: "${{ matrix.php-version }}" - - - - name: Validate composer.json - run: "composer validate --strict --no-check-lock" - - - - name: Composer install - uses: "ramsey/composer-install@v2" - with: - composer-options: "--no-scripts" - - - - name: Composer install php-cs-fixer - uses: "ramsey/composer-install@v2" - with: - composer-options: "--no-scripts --working-dir=tools/php-cs-fixer" - - - - name: Run PHP-CS-Fixer - run: "tools/php-cs-fixer/vendor/bin/php-cs-fixer fix --dry-run --diff" - test: name: "PHP ${{ matrix.php-version }} + @${{ matrix.symfony-version }} ${{ matrix.dependency-versions }} deps" diff --git a/.github/workflows/ci-static-analysis.yaml b/.github/workflows/ci-static-analysis.yaml new file mode 100644 index 000000000..1ff990c56 --- /dev/null +++ b/.github/workflows/ci-static-analysis.yaml @@ -0,0 +1,81 @@ +name: "CI Static Analysis" + +on: + pull_request: + push: + branches: + - 'main' + schedule: + - cron: '0 0 * * *' + +env: + PHPUNIT_FLAGS: "-v" + SYMFONY_PHPUNIT_DIR: "$HOME/symfony-bridge/.phpunit" + +jobs: + coding-standards: + name: "Coding Standards" + + runs-on: ubuntu-latest + + steps: + - + name: Checkout code + uses: "actions/checkout@v3" + + - + name: Install PHP + uses: "shivammathur/setup-php@v2" + + - + name: Validate composer.json + run: "composer validate --strict --no-check-lock" + + - + name: Composer install + uses: "ramsey/composer-install@v2" + with: + composer-options: "--no-scripts" + + - + name: Composer install php-cs-fixer + uses: "ramsey/composer-install@v2" + with: + composer-options: "--no-scripts --working-dir=tools/php-cs-fixer" + + - + name: Run PHP-CS-Fixer + run: "tools/php-cs-fixer/vendor/bin/php-cs-fixer fix --dry-run --diff" + + phpstan: + name: PHPStan + + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: "actions/checkout@v4" + + - name: Install PHP + uses: "shivammathur/setup-php@v2" + + - name: Install Composer Dependencies + uses: "ramsey/composer-install@v2" + with: + composer-options: "--no-scripts" + + - name: Install PHPStan + uses: "ramsey/composer-install@v2" + with: + composer-options: "--no-scripts --working-dir=tools/phpstan" + + - name: Install Optional Dependencies + uses: "ramsey/composer-install@v2" + with: + composer-options: "--no-scripts --working-dir=tools/phpstan/includes" + + - name: Install PHPUnit + run: "vendor/bin/simple-phpunit --version" + + - name: Run PHPStan + run: "tools/phpstan/vendor/bin/phpstan analyze --memory-limit=1G --error-format=github" diff --git a/phpstan.dist.neon b/phpstan.dist.neon new file mode 100644 index 000000000..50fff5457 --- /dev/null +++ b/phpstan.dist.neon @@ -0,0 +1,26 @@ +parameters: + level: 6 + bootstrapFiles: + - vendor/autoload.php + - tools/phpstan/includes/vendor/autoload.php + paths: + - src/Maker + - tests/Command + - tests/Docker + - tests/Maker + excludePaths: + - tests/Doctrine/fixtures + - tests/fixtures + - tests/Security/fixtures + - tests/Security/yaml_fixtures + - tests/tmp + - tests/Util/fixtures + - tests/Util/yaml_fixtures + ignoreErrors: + - + message: '#Property .+phpCompatUtil is never read, only written\.#' + path: src/Maker/* + + - + message: '#Class Symfony\\Bundle\\MakerBundle\\Maker\\LegacyApiTestCase not found#' + path: src/Maker/* diff --git a/src/Maker/MakeEntity.php b/src/Maker/MakeEntity.php index 421e875bc..b93b8d42a 100644 --- a/src/Maker/MakeEntity.php +++ b/src/Maker/MakeEntity.php @@ -306,7 +306,7 @@ public function generate(InputInterface $input, ConsoleStyle $io, Generator $gen } foreach ($fileManagerOperations as $path => $manipulatorOrMessage) { - if (\is_string($manipulatorOrMessage)) { + if (\is_string($manipulatorOrMessage)) { /* @phpstan-ignore-line - https://github.com/symfony/maker-bundle/issues/1509 */ $io->comment($manipulatorOrMessage); } else { $this->fileManager->dumpFile($path, $manipulatorOrMessage->getSourceCode()); diff --git a/src/Maker/MakeUser.php b/src/Maker/MakeUser.php index 04e83ce34..a62a20886 100644 --- a/src/Maker/MakeUser.php +++ b/src/Maker/MakeUser.php @@ -220,6 +220,7 @@ public function generate(InputInterface $input, ConsoleStyle $io, Generator $gen } else { $nextSteps[] = sprintf( 'Open %s to finish implementing your user provider.', + /* @phpstan-ignore-next-line - $customProviderPath is defined in this else statement */ $this->fileManager->relativizePath($customProviderPath) ); } diff --git a/tests/Maker/FunctionalTest.php b/tests/Maker/FunctionalTest.php index 2dc050f21..ace91d6a9 100644 --- a/tests/Maker/FunctionalTest.php +++ b/tests/Maker/FunctionalTest.php @@ -24,7 +24,7 @@ class FunctionalTest extends TestCase * Smoke test to make sure the DI autowiring works and all makers * are registered and have the correct arguments. */ - public function testWiring() + public function testWiring(): void { $kernel = new MakerTestKernel('dev', true); diff --git a/tests/Maker/MakeEntityTest.php b/tests/Maker/MakeEntityTest.php index 2b5605b39..49bb908e7 100644 --- a/tests/Maker/MakeEntityTest.php +++ b/tests/Maker/MakeEntityTest.php @@ -673,6 +673,7 @@ public function getTestDetails(): \Generator ]; } + /** @param array $data */ private function runEntityTest(MakerTestRunner $runner, array $data = []): void { $runner->renderTemplateFile( diff --git a/tests/Maker/MakeFormTest.php b/tests/Maker/MakeFormTest.php index 17511eed8..d707da0b9 100644 --- a/tests/Maker/MakeFormTest.php +++ b/tests/Maker/MakeFormTest.php @@ -22,7 +22,7 @@ protected function getMakerClass(): string return MakeForm::class; } - public function getTestDetails() + public function getTestDetails(): \Generator { yield 'it_generates_basic_form' => [$this->createMakerTest() ->run(function (MakerTestRunner $runner) { @@ -204,7 +204,7 @@ public function getTestDetails() ]; } - private function runFormTest(MakerTestRunner $runner, string $filename) + private function runFormTest(MakerTestRunner $runner, string $filename): void { $runner->copy( 'make-form/tests/'.$filename, diff --git a/tests/Maker/MakeMessageTest.php b/tests/Maker/MakeMessageTest.php index c1b8290a7..0fa8dd95e 100644 --- a/tests/Maker/MakeMessageTest.php +++ b/tests/Maker/MakeMessageTest.php @@ -40,7 +40,7 @@ private function createMakeMessageTest(): MakerTestDetails }); } - public function getTestDetails() + public function getTestDetails(): \Generator { yield 'it_generates_basic_message' => [$this->createMakeMessageTest() ->run(function (MakerTestRunner $runner) { @@ -94,7 +94,7 @@ public function getTestDetails() ]; } - private function runMessageTest(MakerTestRunner $runner, string $filename) + private function runMessageTest(MakerTestRunner $runner, string $filename): void { $runner->copy( 'make-message/tests/'.$filename, @@ -104,7 +104,7 @@ private function runMessageTest(MakerTestRunner $runner, string $filename) $runner->runTests(); } - private function configureTransports(MakerTestRunner $runner) + private function configureTransports(MakerTestRunner $runner): void { $runner->writeFile( 'config/packages/messenger.yaml', diff --git a/tests/Maker/MakeMessengerMiddlewareTest.php b/tests/Maker/MakeMessengerMiddlewareTest.php index 02aa0988d..d594a0bb8 100644 --- a/tests/Maker/MakeMessengerMiddlewareTest.php +++ b/tests/Maker/MakeMessengerMiddlewareTest.php @@ -22,7 +22,7 @@ protected function getMakerClass(): string return MakeMessengerMiddleware::class; } - public function getTestDetails() + public function getTestDetails(): \Generator { yield 'it_generates_messenger_middleware' => [$this->createMakerTest() ->run(function (MakerTestRunner $runner) { diff --git a/tests/Maker/MakeSerializerEncoderTest.php b/tests/Maker/MakeSerializerEncoderTest.php index bd530c2ab..73bee89af 100644 --- a/tests/Maker/MakeSerializerEncoderTest.php +++ b/tests/Maker/MakeSerializerEncoderTest.php @@ -22,7 +22,7 @@ protected function getMakerClass(): string return MakeSerializerEncoder::class; } - public function getTestDetails() + public function getTestDetails(): \Generator { yield 'it_makes_serializer_encoder' => [$this->createMakerTest() // serializer-pack 1.1 requires symfony/property-info >= 5.4 diff --git a/tests/Maker/MakeTwigExtensionTest.php b/tests/Maker/MakeTwigExtensionTest.php index 458d59b9a..8ff96297e 100644 --- a/tests/Maker/MakeTwigExtensionTest.php +++ b/tests/Maker/MakeTwigExtensionTest.php @@ -22,7 +22,7 @@ protected function getMakerClass(): string return MakeTwigExtension::class; } - public function getTestDetails() + public function getTestDetails(): \Generator { yield 'it_makes_twig_extension' => [$this->createMakerTest() ->run(function (MakerTestRunner $runner) { diff --git a/tests/Maker/MakeUnitTestTest.php b/tests/Maker/MakeUnitTestTest.php index c84069694..43a48f8ec 100644 --- a/tests/Maker/MakeUnitTestTest.php +++ b/tests/Maker/MakeUnitTestTest.php @@ -25,7 +25,7 @@ protected function getMakerClass(): string return MakeUnitTest::class; } - public function getTestDetails() + public function getTestDetails(): \Generator { yield 'it_makes_unit_test' => [$this->createMakerTest() ->run(function (MakerTestRunner $runner) { diff --git a/tests/Maker/MakeValidatorTest.php b/tests/Maker/MakeValidatorTest.php index 9ef973c0d..0ca11939c 100644 --- a/tests/Maker/MakeValidatorTest.php +++ b/tests/Maker/MakeValidatorTest.php @@ -22,7 +22,7 @@ protected function getMakerClass(): string return MakeValidator::class; } - public function getTestDetails() + public function getTestDetails(): \Generator { yield 'it_makes_validator' => [$this->createMakerTest() ->run(function (MakerTestRunner $runner) { diff --git a/tests/Maker/MakeVoterTest.php b/tests/Maker/MakeVoterTest.php index 3efec8b3a..c10af66d7 100644 --- a/tests/Maker/MakeVoterTest.php +++ b/tests/Maker/MakeVoterTest.php @@ -22,7 +22,7 @@ protected function getMakerClass(): string return MakeVoter::class; } - public function getTestDetails() + public function getTestDetails(): \Generator { yield 'it_makes_voter' => [$this->createMakerTest() ->run(function (MakerTestRunner $runner) { diff --git a/tools/phpstan/composer.json b/tools/phpstan/composer.json new file mode 100644 index 000000000..b976ba47b --- /dev/null +++ b/tools/phpstan/composer.json @@ -0,0 +1,14 @@ +{ + "require": { + "phpstan/phpstan": "^1.10", + "phpstan/extension-installer": "^1.3", + "phpstan/phpstan-symfony": "^1.3", + "phpstan/phpstan-doctrine": "^1.3", + "phpstan/phpstan-phpunit": "^1.3" + }, + "config": { + "allow-plugins": { + "phpstan/extension-installer": true + } + } +} diff --git a/tools/phpstan/includes/.gitignore b/tools/phpstan/includes/.gitignore new file mode 100644 index 000000000..ed3675727 --- /dev/null +++ b/tools/phpstan/includes/.gitignore @@ -0,0 +1,3 @@ +* +!.gitignore +!composer.json diff --git a/tools/phpstan/includes/composer.json b/tools/phpstan/includes/composer.json new file mode 100644 index 000000000..90b10f0bb --- /dev/null +++ b/tools/phpstan/includes/composer.json @@ -0,0 +1,22 @@ +{ + "require": { + "api-platform/core": "^3.2", + "doctrine/doctrine-bundle": "^2.12", + "doctrine/doctrine-fixtures-bundle": "^3.5", + "symfony/form": "^7.0", + "symfony/mailer": "^7.0", + "symfony/messenger": "^7.0", + "symfony/orm-pack": "^2.4", + "symfony/scheduler": "^7.0", + "symfony/security-bundle": "^7.0", + "symfony/test-pack": "^1.1", + "symfony/twig-bundle": "^7.0", + "symfony/ux-live-component": "^2.16", + "symfony/ux-turbo": "^2.16", + "symfony/validator": "^7.0", + "symfonycasts/reset-password-bundle": "^1.21", + "symfonycasts/verify-email-bundle": "^1.17", + "symfony/webpack-encore-bundle": "^2.1", + "symfony/panther": "^2.1" + } +}