Skip to content

Commit 41f884d

Browse files
authored
Make use of Entropy (#14)
* migrate to entropy/console * wip
1 parent 4ec9bc0 commit 41f884d

34 files changed

+587
-559
lines changed

.github/workflows/code_analysis.yaml

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -34,19 +34,19 @@ jobs:
3434

3535
-
3636
name: 'Check Active Classes'
37-
run: vendor/bin/class-leak check bin src tests --ansi --skip-type="Rector\Monitor\Compare\Contract\ComparatorInterface"
37+
run: vendor/bin/class-leak check bin src tests --ansi --skip-type="Rector\Monitor\Compare\Contract\ComparatorInterface" --skip-type="Entropy\Console\Contract\CommandInterface" --skip-type="\Rector\Monitor\Analyze\Contract\RuleProcessorInterface"
3838

3939
-
40-
name: 'Run "Compare Projects" command'
41-
run: php bin/monitor compare-projects tests/project-fixture/first-project --merge-project tests/project-fixture/second-project --ansi
40+
name: 'Run "Analyze"'
41+
run: php bin/monitor analyze
4242

4343
-
44-
name: 'Run "Matrix"'
45-
run: php bin/monitor matrix --ansi
44+
name: 'Run "Compare"'
45+
run: php bin/monitor compare-projects tests/project-fixture/first-project --merge-project tests/project-fixture/second-project
4646

4747
-
48-
name: 'Run "Analyze"'
49-
run: php bin/monitor analyze --ansi
48+
name: 'Run "Matrix"'
49+
run: php bin/monitor matrix
5050

5151
-
5252
name: 'Composer dependency Analyser'

README.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
# [PRIVATE BETA] Monitor quality of many Packages and Projects in one place
22

3-
[![License](https://img.shields.io/packagist/l/rector/monitor.svg?style=flat-square)](https://packagist.org/packages/rector/monitor)
43
[![Downloads total](https://img.shields.io/packagist/dt/rector/monitor.svg?style=flat-square)](https://packagist.org/packages/rector/monitor/stats)
54

65
Monitor code quality for all your projects and packages in one place, ensuring consistency and eliminating conflicts across PHP versions.
@@ -42,7 +41,7 @@ return MonitorConfig::configure()
4241
// ->addRepositoryBranch('...', 'stage')
4342

4443
// composer rules
45-
// ->disallowPackages(['symfony/phpunit-bridge'])
44+
->disallowPackages(['symfony/phpunit-bridge'])
4645
->requirePackages([
4746
'rector/rector',
4847
'phpecs/phpecs',

bin/monitor.php

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
declare(strict_types=1);
44

5-
use Rector\Monitor\Console\MonitorConsoleApplication;
5+
use Entropy\Console\ConsoleApplication;
66
use Rector\Monitor\DependencyInjection\ContainerFactory;
77

88
$scoperAutoloadFilepath = __DIR__ . '/../vendor/scoper-autoload.php';
@@ -30,5 +30,7 @@
3030
$containerFactory = new ContainerFactory();
3131
$container = $containerFactory->create();
3232

33-
$application = $container->make(MonitorConsoleApplication::class);
34-
exit($application->run());
33+
$application = $container->make(ConsoleApplication::class);
34+
$exitCode = $application->run($argv);
35+
36+
exit($exitCode);

composer-dependency-analyser.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,6 @@
44

55
use ShipMonk\ComposerDependencyAnalyser\Config\Configuration;
66

7-
return new Configuration();
7+
return (new Configuration())
8+
// conditional use
9+
->ignoreErrorsOnExtension('ext-mbstring', [\ShipMonk\ComposerDependencyAnalyser\Config\ErrorType::SHADOW_DEPENDENCY]);

composer.json

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,21 +10,19 @@
1010
"composer/semver": "^3.4",
1111
"entropy/entropy": "dev-main",
1212
"nette/neon": "^3.4",
13-
"nette/utils": "^4.1",
14-
"symfony/filesystem": "^7.4",
15-
"symfony/console": "^6.4",
16-
"symfony/finder": "^7.4",
17-
"symfony/process": "^7.4",
18-
"webmozart/assert": "^1.12"
13+
"symfony/filesystem": "^7.4|8.0.*",
14+
"symfony/finder": "^7.4|8.0.*",
15+
"symfony/process": "^7.4|8.0.*",
16+
"webmozart/assert": "^1.12|^2.0"
1917
},
2018
"require-dev": {
21-
"phpecs/phpecs": "^2.2",
19+
"phpecs/phpecs": "^2.3",
2220
"phpstan/extension-installer": "^1.4",
2321
"phpstan/phpstan": "^2.1",
2422
"phpstan/phpstan-deprecation-rules": "^2.0",
25-
"phpunit/phpunit": "^11.5",
26-
"rector/jack": "^0.4.0",
27-
"rector/rector": "^2.2",
23+
"phpunit/phpunit": "^12.5",
24+
"rector/jack": "^0.5",
25+
"rector/rector": "^2.3",
2826
"shipmonk/composer-dependency-analyser": "^1.8",
2927
"symplify/phpstan-extensions": "^12.0",
3028
"symplify/phpstan-rules": "^14.9",

phpstan.neon

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,11 @@ parameters:
1616
treatPhpDocTypesAsCertain: false
1717

1818
errorFormat: symplify
19+
20+
ignoreErrors:
21+
# part of entropy magic contract
22+
- '#Public method "Rector\\(.*?)Command\:\:run\(\)" is never used#'
23+
24+
# too detailed
25+
- '#Parameter (.*?) expects list<int>, (.*?)<int<0, max>, int<0, max>> given#'
26+

src/Analyze/Command/AnalyzeCommand.php

Lines changed: 48 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -4,79 +4,60 @@
44

55
namespace Rector\Monitor\Analyze\Command;
66

7+
use Entropy\Console\Contract\CommandInterface;
8+
use Entropy\Console\Enum\ExitCode;
9+
use Entropy\Console\Output\OutputPrinter;
710
use Rector\Monitor\Analyze\Contract\RuleProcessorInterface;
811
use Rector\Monitor\Analyze\Reporting\ErrorCollector;
9-
use Rector\Monitor\Analyze\RuleProcessor\DisallowedPackagesRuleProcessor;
10-
use Rector\Monitor\Analyze\RuleProcessor\MetafileProcessor\NoPHPStanBaselineMetafileProcessor;
11-
use Rector\Monitor\Analyze\RuleProcessor\MissingPackagesRuleProcessor;
12-
use Rector\Monitor\Analyze\RuleProcessor\TooLowPackagesRulesProcessor;
1312
use Rector\Monitor\Config\ConfigInitializer;
1413
use Rector\Monitor\Config\MonitorConfigProvider;
1514
use Rector\Monitor\Git\RepositoryMetafilesResolver;
16-
use Rector\Monitor\ValueObject\RepositoryCollection;
17-
use Symfony\Component\Console\Command\Command;
18-
use Symfony\Component\Console\Input\InputInterface;
19-
use Symfony\Component\Console\Input\InputOption;
20-
use Symfony\Component\Console\Output\OutputInterface;
21-
use Symfony\Component\Console\Style\SymfonyStyle;
22-
23-
final class AnalyzeCommand extends Command
15+
use Webmozart\Assert\Assert;
16+
17+
final readonly class AnalyzeCommand implements CommandInterface
2418
{
2519
/**
26-
* @var RuleProcessorInterface[]
20+
* @param RuleProcessorInterface[] $ruleProcessors
2721
*/
28-
private array $ruleProcessors;
29-
3022
public function __construct(
31-
private readonly SymfonyStyle $symfonyStyle,
32-
private readonly MonitorConfigProvider $monitorConfigProvider,
33-
private readonly RepositoryMetafilesResolver $repositoryMetafilesResolver,
34-
private readonly ConfigInitializer $configInitializer,
35-
DisallowedPackagesRuleProcessor $disallowedPackagesRuleProcessor,
36-
MissingPackagesRuleProcessor $missingPackagesRuleProcessor,
37-
TooLowPackagesRulesProcessor $tooLowPackagesRulesProcessor,
38-
NoPHPStanBaselineMetafileProcessor $noPHPStanBaselineMetafileProcessor
23+
private OutputPrinter $outputPrinter,
24+
private MonitorConfigProvider $monitorConfigProvider,
25+
private RepositoryMetafilesResolver $repositoryMetafilesResolver,
26+
private ConfigInitializer $configInitializer,
27+
private array $ruleProcessors,
3928
) {
40-
parent::__construct();
41-
42-
$this->ruleProcessors[] = $disallowedPackagesRuleProcessor;
43-
$this->ruleProcessors[] = $missingPackagesRuleProcessor;
44-
$this->ruleProcessors[] = $tooLowPackagesRulesProcessor;
45-
$this->ruleProcessors[] = $noPHPStanBaselineMetafileProcessor;
29+
Assert::notEmpty($ruleProcessors);
4630
}
4731

48-
protected function configure(): void
32+
public function getName(): string
4933
{
50-
$this->setName('analyze');
51-
$this->setAliases(['analyse']);
52-
53-
$this->setDescription(
54-
'Check repositories composer.json files, assess "require" section, root files, tooling setup and min PHP version with defined quality control rules'
55-
);
34+
return 'analyze';
35+
}
5636

57-
$this->addOption(
58-
'clear-cache',
59-
null,
60-
InputOption::VALUE_NONE,
61-
'Remove cached repositoryCollection composer.json files'
62-
);
37+
public function getDescription(): string
38+
{
39+
return 'Analyze multiple repositories for required packages, root files, min PHP version etc. against defined standard';
6340
}
6441

65-
protected function execute(InputInterface $input, OutputInterface $output): int
42+
/**
43+
* @param bool $clearCache Remove cached repositoryCollection composer.json files
44+
* @return ExitCode::*
45+
*/
46+
public function run(bool $clearCache = false, bool $debug = false): int
6647
{
6748
if ($this->configInitializer->createConfigIfMissing(getcwd())) {
68-
return self::SUCCESS;
49+
return ExitCode::SUCCESS;
6950
}
7051

7152
$monitorConfig = $this->monitorConfigProvider->provide();
72-
$shouldClearCache = (bool) $input->getOption('clear-cache');
7353

7454
$this->repositoryMetafilesResolver->decorateRepositories(
7555
$monitorConfig->getRepositoryCollection(),
76-
$shouldClearCache
56+
$clearCache,
57+
$debug
7758
);
7859

79-
$this->symfonyStyle->title('Repository analysis report');
60+
$this->outputPrinter->title('Repository analysis report');
8061

8162
$erroredRepositoryCount = 0;
8263

@@ -85,42 +66,45 @@ protected function execute(InputInterface $input, OutputInterface $output): int
8566

8667
$composerJson = $repository->getComposerJson();
8768

88-
$this->symfonyStyle->writeln(
89-
sprintf('<fg=yellow;options=bold>%d) %s</>', $key + 1, $composerJson->getRepositoryName())
69+
$this->outputPrinter->writeln(
70+
sprintf('<fg=yellow>%d) %s</>', $key + 1, $composerJson->getRepositoryName())
9071
);
9172
foreach ($this->ruleProcessors as $ruleProcessor) {
9273
$ruleProcessor->process($monitorConfig, $composerJson, $errorCollector);
9374
}
9475

9576
foreach ($errorCollector->getErrorMessages() as $errorMessage) {
96-
$this->symfonyStyle->writeln($errorMessage);
77+
$this->outputPrinter->writeln($errorMessage);
9778
}
9879

9980
if ($errorCollector->hasErrors() === false) {
100-
$this->symfonyStyle->writeln(' * <fg=green>Package perfect ✔</>');
81+
$this->outputPrinter->greenBackground('Package perfect ✔');
10182
} else {
10283
++$erroredRepositoryCount;
10384
}
10485

105-
$this->symfonyStyle->newLine();
86+
$this->outputPrinter->newLine();
10687
}
10788

108-
$this->printAnalysisSummary($monitorConfig->getRepositoryCollection(), $erroredRepositoryCount);
89+
$this->printAnalysisSummary($erroredRepositoryCount);
10990

110-
return self::SUCCESS;
91+
return ExitCode::SUCCESS;
11192
}
11293

113-
private function printAnalysisSummary(RepositoryCollection $repositoryCollection, int $erroredRepositoryCount): void
94+
private function printAnalysisSummary(int $erroredRepositoryCount): void
11495
{
115-
$this->symfonyStyle->newLine();
116-
117-
$this->symfonyStyle->writeln(sprintf(
118-
' Summary: %d %s analyzed, %d with issues',
119-
$repositoryCollection->count(),
120-
$repositoryCollection->count() === 1 ? 'repository' : 'repositories',
121-
$erroredRepositoryCount
122-
));
96+
$this->outputPrinter->newLine();
97+
98+
if ($erroredRepositoryCount > 0) {
99+
$this->outputPrinter->redBackground(sprintf(
100+
'Found %d %s',
101+
$erroredRepositoryCount,
102+
$erroredRepositoryCount === 1 ? 'issue' : 'issues'
103+
));
104+
} else {
105+
$this->outputPrinter->greenBackground('All repositories are perfect ✔');
106+
}
123107

124-
$this->symfonyStyle->newLine();
108+
$this->outputPrinter->newLine();
125109
}
126110
}

src/Compare/Command/CompareProjectsCommand.php

Lines changed: 22 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -4,58 +4,54 @@
44

55
namespace Rector\Monitor\Compare\Command;
66

7+
use Entropy\Console\Contract\CommandInterface;
8+
use Entropy\Console\Output\OutputPrinter;
9+
use Rector\Console\ExitCode;
710
use Rector\Monitor\Compare\Contract\ComparatorInterface;
811
use Rector\Monitor\Compare\ValueObject\ProjectMetadata;
9-
use Symfony\Component\Console\Command\Command;
10-
use Symfony\Component\Console\Input\InputArgument;
11-
use Symfony\Component\Console\Input\InputInterface;
12-
use Symfony\Component\Console\Input\InputOption;
13-
use Symfony\Component\Console\Output\OutputInterface;
14-
use Symfony\Component\Console\Style\SymfonyStyle;
1512
use Webmozart\Assert\Assert;
1613

17-
final class CompareProjectsCommand extends Command
14+
final readonly class CompareProjectsCommand implements CommandInterface
1815
{
1916
/**
2017
* @param ComparatorInterface[] $comparators
2118
*/
2219
public function __construct(
23-
private readonly SymfonyStyle $symfonyStyle,
24-
private readonly array $comparators
20+
private OutputPrinter $outputPrinter,
21+
private array $comparators
2522
) {
26-
parent::__construct();
27-
2823
// make sure not empty to verify DI works
2924
Assert::notEmpty($comparators);
3025
Assert::allIsInstanceOf($comparators, ComparatorInterface::class);
3126
}
3227

33-
protected function configure(): void
28+
public function getName(): string
3429
{
35-
$this->setName('compare-projects');
36-
37-
$this->setDescription(
38-
'Compare two projects and show the differences. First is the macro, monorepo project we want to merge into. Other is the project to merge merge and dismantle later.'
39-
);
30+
return 'compare-projects';
31+
}
4032

41-
$this->addArgument('monorepo-directory', InputArgument::REQUIRED, 'Path to the monorepo directory');
42-
$this->addOption('merge-project', null, InputOption::VALUE_REQUIRED);
33+
public function getDescription(): string
34+
{
35+
return 'Compare 2 projects and show their differences - configs, required packages, PHPStan extensions, levels etc.';
4336
}
4437

45-
protected function execute(InputInterface $input, OutputInterface $output): int
38+
/**
39+
* @param string $monorepoDirectory Path to the monorepo directory
40+
* @param string $mergeProject Path to the project to merge directory
41+
*
42+
* @return ExitCode::*
43+
*/
44+
public function run(string $monorepoDirectory, string $mergeProject): int
4645
{
47-
$monorepoDirectory = $input->getArgument('monorepo-directory');
4846
$monorepoProjectMetadata = new ProjectMetadata($monorepoDirectory);
47+
$mergeProjectMetadata = new ProjectMetadata($mergeProject);
4948

50-
$mergeDirectory = $input->getOption('merge-project');
51-
$mergeProjectMetadata = new ProjectMetadata($mergeDirectory);
52-
53-
$this->symfonyStyle->writeln('<fg=green>Both directories found. Comparing 2 projects</>');
49+
$this->outputPrinter->green('Both directories found. Comparing 2 projects');
5450

5551
foreach ($this->comparators as $comparator) {
5652
$comparator->compare($monorepoProjectMetadata, $mergeProjectMetadata);
5753
}
5854

59-
return self::SUCCESS;
55+
return \Entropy\Console\Enum\ExitCode::SUCCESS;
6056
}
6157
}

0 commit comments

Comments
 (0)