diff --git a/.github/workflows/code-analysis.yaml b/.github/workflows/code-analysis.yaml new file mode 100644 index 0000000..4782236 --- /dev/null +++ b/.github/workflows/code-analysis.yaml @@ -0,0 +1,53 @@ +name: Code Analysis + +on: + pull_request: null + push: + branches: + - main + +jobs: + code_analysis: + strategy: + fail-fast: false + matrix: + actions: + - + name: 'PHPStan' + run: composer phpstan + + - + name: 'Check Active Classes' + run: vendor/bin/class-leak check bin src tests --ansi --skip-path=Fixture --skip-path=Source + + - + name: 'Unit tests' + run: vendor/bin/phpunit + + - + name: "Finalize classes" + run: vendor/bin/swiss-knife finalize-classes bin src tests --dry-run --ansi + + - + name: 'Composer dependency Analyser' + run: vendor/bin/composer-dependency-analyser + + - + name: 'Validate Composer' + run: composer validate + + name: ${{ matrix.actions.name }} + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + # see https://github.com/shivammathur/setup-php + - uses: shivammathur/setup-php@v2 + with: + php-version: 8.2 + coverage: none + + - uses: "ramsey/composer-install@v2" + + - run: ${{ matrix.actions.run }} diff --git a/bin/handyman.php b/bin/handyman.php index 04d7bc2..0d9d5cd 100644 --- a/bin/handyman.php +++ b/bin/handyman.php @@ -1,7 +1,6 @@ ignoreErrorsOnPackage('nikic/php-parser', [ErrorType::DEV_DEPENDENCY_IN_PROD]); diff --git a/composer.json b/composer.json index 41dac56..4fb9980 100644 --- a/composer.json +++ b/composer.json @@ -1,6 +1,7 @@ { "name": "tomasvotruba/handyman", "type": "phpstan-extension", + "license": "MIT", "description": "Automate repeated steps when coming to a PHP project or create new package", "require": { "php": "^8.2", @@ -9,7 +10,8 @@ "symfony/process": "^7.1", "symfony/finder": "^7.1", "nette/utils": "^4.0", - "phpstan/phpstan": "^1.12" + "phpstan/phpstan": "^1.12", + "webmozart/assert": "^1.11" }, "require-dev": { "rector/rector": "^1.2", @@ -20,7 +22,7 @@ "symplify/easy-coding-standard": "^12.3", "shipmonk/composer-dependency-analyser": "^1.7", "tomasvotruba/type-coverage": "^1.0", - "tomasvotruba/class-leak": "^1.0", + "tomasvotruba/class-leak": "^1.1", "tomasvotruba/unused-public": "^1.0", "tracy/tracy": "^2.10", "nikic/php-parser": "^4.19" diff --git a/phpunit.xml b/phpunit.xml index 548a391..2e3d6c4 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -9,6 +9,7 @@ tests + tests/PHPStan/Rule/PublicStaticDataProviderRule/Fixture diff --git a/src/Command/GithubCommand.php b/src/Command/GithubCommand.php index 96b89b5..6797afd 100644 --- a/src/Command/GithubCommand.php +++ b/src/Command/GithubCommand.php @@ -4,12 +4,12 @@ namespace TomasVotruba\Handyman\Command; -use Nette\Utils\FileSystem; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Style\SymfonyStyle; use TomasVotruba\Handyman\FileSystem\TemplateFileSystem; +use TomasVotruba\Handyman\ValueObject\ComposerJson; final class GithubCommand extends Command { @@ -27,17 +27,22 @@ protected function configure(): void protected function execute(InputInterface $input, OutputInterface $output): int { - $codeAnalysisFilePath = getcwd() . '/.github/workflows/code-analysis.yaml'; - if (! file_exists($codeAnalysisFilePath)) { - $fileContents = TemplateFileSystem::renderFilePathWithVariables( - __DIR__ . '/../../templates/github-workflows/code-analysis.yaml', - [] + $projectFilePath = getcwd() . '/.github/workflows/code-analysis.yaml'; + + if (! file_exists($projectFilePath)) { + $projectComposerJson = new ComposerJson(getcwd() . '/composer.json'); + + TemplateFileSystem::renderFilePathWithVariables( + __DIR__ . '/../../templates/.github/workflows/code_analysis.yaml', + [ + '__PHP_VERSION__' => $projectComposerJson->getPhpVersionString(), + ], + $projectFilePath ); - FileSystem::write($codeAnalysisFilePath, $fileContents); - $this->symfonyStyle->success('Created .github/workflows/code-analysis.yaml'); + $this->symfonyStyle->success('Created .github/workflows/code_analysis.yaml'); } else { - $this->symfonyStyle->success('Config .github/workflows/code-analysis.yaml already exists'); + $this->symfonyStyle->success('Config .github/workflows/code_analysis.yaml already exists'); } return self::SUCCESS; diff --git a/src/FileSystem/TemplateFileSystem.php b/src/FileSystem/TemplateFileSystem.php index 708124e..b79328d 100644 --- a/src/FileSystem/TemplateFileSystem.php +++ b/src/FileSystem/TemplateFileSystem.php @@ -5,15 +5,28 @@ namespace TomasVotruba\Handyman\FileSystem; use Nette\Utils\FileSystem; +use Webmozart\Assert\Assert; final class TemplateFileSystem { /** * @param array $variables */ - public static function renderFilePathWithVariables(string $sourceFilePath, array $variables): string - { - $fileContents = FileSystem::read($sourceFilePath); - return str_replace(array_keys($variables), array_values($variables), $fileContents); + public static function renderFilePathWithVariables( + string $sourceFilePath, + array $variables, + ?string $targetFilePath = null + ): string { + Assert::fileExists($sourceFilePath); + + $templateContents = FileSystem::read($sourceFilePath); + $fileContents = str_replace(array_keys($variables), array_values($variables), $templateContents); + + // save file contents directly + if (is_string($targetFilePath)) { + FileSystem::write($targetFilePath, $fileContents); + } + + return $fileContents; } } diff --git a/src/ValueObject/ComposerJson.php b/src/ValueObject/ComposerJson.php new file mode 100644 index 0000000..7ee7b12 --- /dev/null +++ b/src/ValueObject/ComposerJson.php @@ -0,0 +1,40 @@ + + */ + private array $json = []; + + public function __construct(string $composerJsonFilePath) + { + Assert::fileExists($composerJsonFilePath); + $this->composerJsonFilePath = $composerJsonFilePath; + + $this->json = Json::decode(FileSystem::read($this->composerJsonFilePath), true); + } + + public function getPhpVersionString(): string + { + $requirePhp = $this->json['require']['php'] ?? null; + Assert::string($requirePhp); + + $match = Strings::match($requirePhp, '#(?\d\.\d)#'); + Assert::isArray($match); + Assert::keyExists($match, 'version'); + + return $match['version']; + } +} diff --git a/stubs/Doctrine/ORM/EntityManager.php b/stubs/Doctrine/ORM/EntityManager.php new file mode 100644 index 0000000..5c6b827 --- /dev/null +++ b/stubs/Doctrine/ORM/EntityManager.php @@ -0,0 +1,11 @@ +