Skip to content

Commit

Permalink
Change PHPStan configuration (#36)
Browse files Browse the repository at this point in the history
* Remove "Just-in-Time" configuration
* Add dynamic configuration
* Add extension to workflow
* Add phpstan.neon
* Raise infection version
  • Loading branch information
rdss-sknott authored Jun 21, 2024
1 parent 2fbe969 commit e6898c6
Show file tree
Hide file tree
Showing 25 changed files with 428 additions and 347 deletions.
7 changes: 4 additions & 3 deletions .github/workflows/continuous-integration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,10 @@ jobs:
${{ runner.os }}-codestyle-${{ env.cache-name }}-
- name: Setup PHP and Composer
uses: shivammathur/setup-php@e04e1d97f0c0481c6e1ba40f8a538454fe5d7709
uses: shivammathur/setup-php@a4e22b60bbb9c1021113f2860347b0759f66fe5d
with:
php-version: '8.2'
extensions: gd
tools: cs2pr, composer
env:
fail-fast: true
Expand Down Expand Up @@ -117,7 +118,7 @@ jobs:
${{ runner.os }}-tests-${{ env.cache-name }}-
- name: Setup PHP and Composer
uses: shivammathur/setup-php@e04e1d97f0c0481c6e1ba40f8a538454fe5d7709
uses: shivammathur/setup-php@a4e22b60bbb9c1021113f2860347b0759f66fe5d
with:
php-version: '8.2'
tools: composer:${{ matrix.composer_version }}
Expand Down Expand Up @@ -145,4 +146,4 @@ jobs:
- name: Check infections
if: ${{ matrix.composer_parameters == '--prefer-stable' }}
run: |
composer infection
composer ci
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
.idea
.phpunit.result.cache
/vendor
config/phpstan/phpstan.neon
composer.lock
node_modules
package-lock.json
Expand Down
20 changes: 15 additions & 5 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
"amphp/phpunit-util": "^2.0.0",
"amphp/process": "^v1.1.4",
"brianium/paratest": "^6.11.0",
"infection/infection": ">=0.27.9",
"infection/infection": ">=0.27.11",
"mockery/mockery": "^1.6.7",
"phpunit/phpunit": "^9.6.16",
"roave/security-advisories": "dev-latest",
Expand Down Expand Up @@ -80,13 +80,23 @@
"scripts": {
"post-update-cmd": "npm update",
"post-install-cmd": "npm install",
"ci": [
"@test-prepare",
"@test",
"@infection-command"
],
"test-mkdirs": "mkdir -p tmp/phpunit",
"test-paratest-command": "paratest -p$(getconf _NPROCESSORS_ONLN)",
"test-prepare": "mkdir -p tmp/phpunit",
"test": [
"mkdir -p tmp/phpunit",
"paratest -p$(getconf _NPROCESSORS_ONLN)"
"@test-prepare",
"@test-paratest-command"
],
"infection-command": "infection -n --threads=$(getconf _NPROCESSORS_ONLN) --skip-initial-tests --coverage=tmp/phpunit --no-progress",
"infection": [
"@test",
"infection -n --threads=$(getconf _NPROCESSORS_ONLN) --skip-initial-tests --coverage=tmp/phpunit --no-progress"
"@test-prepare",
"@test --testsuite=InfectionRelevant",
"@infection-command"
]
},
"config": {
Expand Down
25 changes: 25 additions & 0 deletions config/phpstan/phpstan.config.drop.in.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

declare(strict_types=1);

use Zooroyal\CodingStandard\CommandLine\ApplicationLifeCycle\ContainerFactory;
use Zooroyal\CodingStandard\CommandLine\StaticCodeAnalysis\PHPStan\PHPStanConfigGenerator;

$autoloadFiles = [
__DIR__ . '/../../../../autoload.php',
__DIR__ . '/../../vendor/autoload.php',
];

foreach ($autoloadFiles as $autoloadFile) {
if (file_exists($autoloadFile)) {
require_once $autoloadFile;
break;
}
}
$config = ContainerFactory::getContainerInstance()
->get(PHPStanConfigGenerator::class)
->addDynamicConfigValues([]);

echo 'Coding-Standard config loaded!' . PHP_EOL;

return $config;
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
includes:
- phpstan.config.drop.in.php

parameters:
level: 5
Expand Down
14 changes: 12 additions & 2 deletions infection.json.dist
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"timeout": 20,
"minMsi": 86,
"minMsi": 87,
"minCoveredMsi": 94,
"source": {
"directories": [
Expand All @@ -16,6 +16,16 @@
"github": true
},
"mutators": {
"@default": true
"@default": true,
"DecrementInteger": {
"ignoreSourceCodeByRegex": [
".*json_decode\\([^,\\\\)]+, (true|false), 512[^\\\\)]*\\).*"
]
},
"IncrementInteger": {
"ignoreSourceCodeByRegex": [
".*json_decode\\([^,\\\\)]+, (true|false), 512[^\\\\)]*\\).*"
]
}
}
}
6 changes: 5 additions & 1 deletion phpunit.xml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,16 @@
<testsuites>
<testsuite name="AllUnitTests">
<directory>./tests/Unit/</directory>
<exclude>./tests/Functional/Plugin/Fixtures/ComposerTest/vendor*</exclude>
</testsuite>
<testsuite name="AllFunctionalTests">
<directory>./tests/Functional/</directory>
<exclude>./tests/Functional/Plugin/Fixtures/ComposerTest/vendor*</exclude>
</testsuite>
<testsuite name="InfectionRelevant">
<directory>./tests/Unit/</directory>
<directory>./tests/Functional/</directory>
<exclude>./tests/Functional/Plugin/Fixtures/ComposerTest/vendor*</exclude>
</testsuite>
<testsuite name="AllSystemTests">
<directory>./tests/System/</directory>
</testsuite>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,35 +4,37 @@

namespace Zooroyal\CodingStandard\CommandLine\StaticCodeAnalysis\Generic\TerminalCommand\PhpVersion;

use JsonException;
use Safe\Exceptions\FilesystemException;
use Zooroyal\CodingStandard\CommandLine\EnhancedFileInfo\EnhancedFileInfoFactory;
use Zooroyal\CodingStandard\CommandLine\EnhancedFileInfo\EnhancedFileInfo;
use Zooroyal\CodingStandard\CommandLine\Environment\Environment;
use Zooroyal\CodingStandard\CommandLine\FileSearch\FileSearchInterface;

use function Safe\file_get_contents;

class ComposerInterpreter
{
private const SEARCH_DEPTH_MIN = 1;
private const SEARCH_DEPTH_MAX = 4;

private ?string $cachedMinimalViablePhpVersion = null;
private string $cachedMinimalRootPackagePhpVersion;

public function __construct(
private readonly Environment $environment,
private readonly EnhancedFileInfoFactory $enhancedFileInfoFactory,
private readonly ConstraintToVersionConverter $constraintToVersionConverter,
private readonly FileSearchInterface $fileSearch,
) {
}

/**
* Get local php-version-constraints from root composer.json.
*
* @throws FilesystemException
* @throws JsonException
* Reads the php version constraint from the root composer.json. Does not look at PHP version constraints in
* dependencies.
*/
public function getLocalPhpVersionConstraint(): string
private function readConstraintFromRootComposerFile(): string
{
$rootDirectory = $this->environment->getRootDirectory();
$path = $rootDirectory->getRealPath();
$composerFile = $this->enhancedFileInfoFactory->buildFromPath($path . '/composer.json');
$composerConfig = json_decode(
file_get_contents($composerFile->getRealPath()),
file_get_contents($path . '/composer.json'),
associative: true,
flags: JSON_THROW_ON_ERROR,
);
Expand All @@ -41,9 +43,77 @@ public function getLocalPhpVersionConstraint(): string
?? $composerConfig['require']['php']
?? '*';

$phpVersionConstraintExtracted = $this->constraintToVersionConverter
return $phpVersionConstraint;
}

/**
* Get local php-version-constraints from root composer.json.
*/
public function getMinimalRootPackagePhpVersion(): string
{
if (isset($this->cachedMinimalRootPackagePhpVersion)) {
return $this->cachedMinimalRootPackagePhpVersion;
}

$phpVersionConstraint = $this->readConstraintFromRootComposerFile();
$this->cachedMinimalRootPackagePhpVersion = $this->constraintToVersionConverter
->extractActualPhpVersion($phpVersionConstraint);

return $phpVersionConstraintExtracted;
return $this->cachedMinimalRootPackagePhpVersion;
}

/**
* Get the minimal viable PHP version from all composer files in the project. This is the lowest common PHP version
* and our best guess for the minimal PHP version required to run the project.
*/
public function getMinimalViablePhpVersion(): string
{
if ($this->cachedMinimalViablePhpVersion === null) {
$composerFiles = $this->gatherComposerFiles();
$this->cachedMinimalViablePhpVersion = $this->searchMinimalViablePhpVersion($composerFiles);
}

return $this->cachedMinimalViablePhpVersion;
}

/**
* Finds all composer files in the project.
*
* @return array<EnhancedFileInfo>
*/
private function gatherComposerFiles(): array
{
$rootDirectory = $this->environment->getRootDirectory();

$foundComposerFiles = $this->fileSearch->listFolderFiles(
fileName: 'composer.json',
path: $rootDirectory,
minDepth: self::SEARCH_DEPTH_MIN,
maxDepth: self::SEARCH_DEPTH_MAX,
);

return $foundComposerFiles;
}

/**
* Combines Constraints of given composer files and returns the lowest possible php version.
*
* @param array<EnhancedFileInfo> $composerFiles
*/
private function searchMinimalViablePhpVersion(array $composerFiles): string
{
$minimalViablePhpVersion = $this->getMinimalRootPackagePhpVersion();

foreach ($composerFiles as $composerFile) {
$contents = file_get_contents($composerFile->getRealPath());
$composerConfig = json_decode($contents, true, 512, JSON_THROW_ON_ERROR);

$phpVersionConstraint = $composerConfig['require']['php'] ?? '*';
$minPhpVersionPackage = $this->constraintToVersionConverter->extractActualPhpVersion($phpVersionConstraint);
$minimalViablePhpVersion = version_compare($minimalViablePhpVersion, $minPhpVersionPackage, '<')
? $minPhpVersionPackage
: $minimalViablePhpVersion;
}
return $minimalViablePhpVersion;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public function __construct()
'7.4.' => '33',
'8.0.' => '30',
'8.1.' => '28',
'8.2.' => (explode('.', phpversion()))[2],
'8.2.' => '19',
];

foreach ($phpVersionRanges as $phpVersionString => $phpMaxPatchVersion) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,8 @@

class MinimalVersionDecorator extends TerminalCommandDecorator
{
private ?string $cachedMinPhpVersion = null;

public function __construct(
private readonly ConstraintToVersionConverter $constraintToVersionConverter,
private readonly ComposerInterpreter $composerInterpreter,
) {
public function __construct(private readonly ComposerInterpreter $composerInterpreter)
{
}

public function decorate(DecorateEvent $event): void
Expand All @@ -26,17 +22,11 @@ public function decorate(DecorateEvent $event): void
return;
}

if ($this->cachedMinPhpVersion === null) {
$phpVersionConstraint = $this->composerInterpreter->getLocalPhpVersionConstraint();

$this->cachedMinPhpVersion = $this->constraintToVersionConverter
->extractActualPhpVersion($phpVersionConstraint);
}

$terminalCommand->setMinimalPhpVersion($this->cachedMinPhpVersion);
$minimalPhpVersion = $this->composerInterpreter->getMinimalRootPackagePhpVersion();
$terminalCommand->setMinimalPhpVersion($minimalPhpVersion);

$event->getOutput()->writeln(
'<info>Targeted minimal PHP version is ' . $this->cachedMinPhpVersion . '</info>' . PHP_EOL,
'<info>Targeted minimal PHP version is ' . $minimalPhpVersion . '</info>' . PHP_EOL,
OutputInterface::VERBOSITY_VERBOSE,
);
}
Expand Down
Loading

0 comments on commit e6898c6

Please sign in to comment.