diff --git a/.github/workflows/code_analysis.yaml b/.github/workflows/code_analysis.yaml
index 25024c1..bdaefc8 100644
--- a/.github/workflows/code_analysis.yaml
+++ b/.github/workflows/code_analysis.yaml
@@ -40,6 +40,14 @@ jobs:
name: 'Run "Compare Projects" command'
run: php bin/monitor compare-projects tests/project-fixture/first-project --merge-project tests/project-fixture/second-project --ansi
+ -
+ name: 'Run "Matrix"'
+ run: php bin/monitor matrix --ansi
+
+ -
+ name: 'Run "Analyze"'
+ run: php bin/monitor analyze --ansi
+
-
name: 'Composer dependency Analyser'
run: vendor/bin/composer-dependency-analyser
diff --git a/README.md b/README.md
index d040268..0e51996 100644
--- a/README.md
+++ b/README.md
@@ -20,16 +20,48 @@ composer require rector/monitor --dev
-## Usage
-
-
-
-### 1. Quality control for `composer.json` in multiple repositories
+## 1. Single place to Quality control Multiple repositories
```bash
vendor/bin/monitor analyze
```
+This command will load `monitor.php` configuration file from project root. There you define repositories and requirements to meet.
+
+```php
+use Rector\Monitor\Config\MonitorConfig;
+
+return MonitorConfig::configure()
+ ->addRepositories([
+ 'https://github.com/rectorphp/rector-symfony',
+ 'https://github.com/rectorphp/rector-doctrine',
+ 'https://github.com/rectorphp/rector-phpunit',
+ 'https://github.com/rectorphp/rector-downgrade-php',
+ ])
+ ->addRepositoryBranch('https://github.com/rectorphp/rector-src', 'main')
+ // ->addRepositoryBranch('...', 'stage')
+
+ // composer rules
+ // ->disallowPackages(['symfony/phpunit-bridge'])
+ ->requirePackages([
+ 'rector/rector',
+ 'phpecs/phpecs',
+ 'phpstan/phpstan',
+ 'phpstan/extension-installer',
+ 'symplify/phpstan-rules',
+ ])
+
+ // version requirements
+ ->minPackageVersion('phpstan/phpstan', '2.1')
+ ->minPackageVersion('rector/rector', '2.2')
+
+ // other rules
+ ->noPhpstanBaseline();
+```
+
+
+
+The repositories are cached to get fast performance. To refresh them:
```bash
vendor/bin/monitor analyze --clear-cache
@@ -37,24 +69,22 @@ vendor/bin/monitor analyze --clear-cache
-### 2. See full Matrix of repositories's dependencies
+## 2. See full Matrix of Repositories' Dependencies
```bash
vendor/bin/monitor matrix
```
----
-## Merge many projects to one Monorepo
+
-Automate micro-services merge to one macro project, to make coding saint again.
+## 3. See Difference between Two Projects
+Automate micro-services merge to one macro project, to make coding saint again.
-### Use
-
See how the monorepo project and the merge one are different. Use this knowledge to fill gaps in monorepo project. Only then create a final merge pull-request.
```bash
diff --git a/monitor.php b/monitor.php
index 11370d2..c034bac 100644
--- a/monitor.php
+++ b/monitor.php
@@ -7,20 +7,19 @@
return MonitorConfig::configure()
->addRepositories([
// rector repositories
- 'https://github.com/rectorphp/rector-src',
'https://github.com/rectorphp/rector-symfony',
'https://github.com/rectorphp/rector-doctrine',
'https://github.com/rectorphp/rector-phpunit',
'https://github.com/rectorphp/rector-downgrade-php',
])
- // ->addRepositoryBranch('...', 'stage')
+ ->addRepositoryBranch('https://github.com/rectorphp/rector-src', 'main')
// composer rules
// ->disallowPackages(['symfony/phpunit-bridge'])
->requirePackages([
'phpstan/phpstan',
'phpecs/phpecs',
- 'rector/rector',
+ 'rector/rector-src',
'phpstan/phpstan-deprecation-rules',
'phpstan/extension-installer',
'symplify/phpstan-rules',
diff --git a/rector.php b/rector.php
index 6b47995..deb230e 100644
--- a/rector.php
+++ b/rector.php
@@ -3,6 +3,7 @@
declare(strict_types=1);
use Rector\Config\RectorConfig;
+use Rector\TypeDeclaration\Rector\StmtsAwareInterface\DeclareStrictTypesRector;
return RectorConfig::configure()
->withPaths([__DIR__ . '/bin', __DIR__ . '/src', __DIR__ . '/tests'])
@@ -23,5 +24,6 @@
\Rector\Naming\Rector\ClassMethod\RenameParamToMatchTypeRector::class => [
__DIR__ . '/src/Composer/ComposerJsonResolver.php',
],
+ DeclareStrictTypesRector::class,
])
->withImportNames(removeUnusedImports: true);
diff --git a/src/Config/MonitorConfig.php b/src/Config/MonitorConfig.php
index 9ca5260..c564aea 100644
--- a/src/Config/MonitorConfig.php
+++ b/src/Config/MonitorConfig.php
@@ -129,6 +129,10 @@ public function getMinPackagesVersions(): array
public function addRepositoryBranch(string $repository, string $branch): self
{
+ if (! str_ends_with($repository, '.git')) {
+ $repository .= '.git';
+ }
+
MonitorAssert::assertRepositoryUrl($repository);
$this->repositoriesWithBranches[$repository] = $branch;
diff --git a/src/Git/RepositoryMetafilesResolver.php b/src/Git/RepositoryMetafilesResolver.php
index b5d8d85..aa203e7 100644
--- a/src/Git/RepositoryMetafilesResolver.php
+++ b/src/Git/RepositoryMetafilesResolver.php
@@ -22,42 +22,36 @@ public function __construct(
) {
}
- public function decorateRepositories(RepositoryCollection $repositoryCollection, bool $clearCache = false): void
- {
+ public function decorateRepositories(
+ RepositoryCollection $repositoryCollection,
+ bool $clearCache = false,
+ bool $isDebug = false
+ ): void {
foreach ($repositoryCollection->all() as $repository) {
$repositoryCacheDirectory = sys_get_temp_dir() . '/rector-monitor-cache/repository-' . md5(
$repository->getRepositoryUrl()
);
- if (file_exists($repositoryCacheDirectory) && $this->hasDirectorySomeFiles($repositoryCacheDirectory)) {
- if ($clearCache) {
- // clear old files
- FileSystem::delete($repositoryCacheDirectory);
- } else {
- $rootFiles = $this->findRootFilesInDirectory($repositoryCacheDirectory);
- $repository->decorateRootFiles($rootFiles);
-
- $composerJsonFile = $this->matchComposerJsonFile($rootFiles, $repository);
-
- $composerJson = $this->composerJsonFactory->create($composerJsonFile, $repository);
- $repository->decorateComposerJson($composerJson);
-
- $this->symfonyStyle->writeln(sprintf(
- ' * loading "%s>" repository from cache',
- $repository->getComposerJson()
- ->getRepositoryName()
- ));
-
- continue;
- }
+ if ($clearCache) {
+ // clear old files
+ FileSystem::delete($repositoryCacheDirectory);
}
- $this->symfonyStyle->writeln(sprintf(
- ' * loading files from "%s>" remote repository',
- $repository->getRepositoryUrl()
- ));
+ if ($this->hasDirectorySomeFiles($repositoryCacheDirectory)) {
+ $this->symfonyStyle->writeln(sprintf(
+ ' * loading "%s>" repository from cache',
+ $repository->getRepositoryUrl()
+ ));
+ } else {
+ $this->symfonyStyle->writeln(sprintf(
+ ' * loading files from "%s>" remote repository',
+ $repository->getRepositoryUrl()
+ ));
+
+ $this->downloadRepository($repository, $repositoryCacheDirectory, $isDebug);
+ }
- $rootFiles = $this->loadRootFilesFromRepository($repository, $repositoryCacheDirectory);
+ $rootFiles = $this->findRootFilesInDirectory($repositoryCacheDirectory);
$repository->decorateRootFiles($rootFiles);
$composerJsonFile = $this->matchComposerJsonFile($rootFiles, $repository);
@@ -77,20 +71,33 @@ private function findRootFilesInDirectory(string $repositoryCacheDirectory): arr
return iterator_to_array($repositoryRootFilesFinder->getIterator());
}
- /**
- * @return SplFileInfo[]
- */
- private function loadRootFilesFromRepository(Repository $repository, string $repositoryCacheDirectory): array
+ private function downloadRepository(Repository $repository, string $repositoryCacheDirectory, bool $isDebug): void
{
FileSystem::createDir($repositoryCacheDirectory);
- Process::fromShellCommandline('git init', $repositoryCacheDirectory)
- ->mustRun();
+ $process = Process::fromShellCommandline('git init', $repositoryCacheDirectory);
+ if ($isDebug) {
+ $this->symfonyStyle->writeln('Running command: ' . $process->getCommandLine());
+ }
- Process::fromShellCommandline(
+ $process->mustRun();
+ if ($isDebug) {
+ $this->symfonyStyle->writeln('Cloning repository:' . PHP_EOL . $process->getOutput());
+ }
+
+ $process = Process::fromShellCommandline(
'git remote add origin ' . $repository->getClonableRepositoryUrl(),
$repositoryCacheDirectory
- )->mustRun();
+ );
+
+ if ($isDebug) {
+ $this->symfonyStyle->writeln('Running command: ' . $process->getCommandLine());
+ }
+
+ $process->mustRun();
+ if ($isDebug) {
+ $this->symfonyStyle->writeln('Cloning repository:' . PHP_EOL . $process->getOutput());
+ }
// might be a bit longer for large repositories
Process::fromShellCommandline('git fetch origin --depth 1', $repositoryCacheDirectory, timeout: 120)
@@ -98,11 +105,9 @@ private function loadRootFilesFromRepository(Repository $repository, string $rep
// Fetch the latest changes from the remote repository
Process::fromShellCommandline(
- sprintf('git checkout %s', $repository->getBranch() ?: 'FETCH_HEAD'),
+ sprintf('git checkout %s', $repository->getBranch() ?: 'main'),
$repositoryCacheDirectory
)->mustRun();
-
- return $this->findRootFilesInDirectory($repositoryCacheDirectory);
}
/**
@@ -126,8 +131,11 @@ private function matchComposerJsonFile(array $rootFiles, Repository $repository)
private function hasDirectorySomeFiles(string $repositoryCacheDirectory): bool
{
- $fileCountInDirectory = Finder::create()->in($repositoryCacheDirectory)->files()->count();
+ if (! is_dir($repositoryCacheDirectory)) {
+ return false;
+ }
+ $fileCountInDirectory = Finder::create()->in($repositoryCacheDirectory)->files()->count();
return $fileCountInDirectory > 0;
}
}
diff --git a/src/Matrix/Command/MatrixCommand.php b/src/Matrix/Command/MatrixCommand.php
index c26ed2d..53b6e1e 100644
--- a/src/Matrix/Command/MatrixCommand.php
+++ b/src/Matrix/Command/MatrixCommand.php
@@ -44,6 +44,9 @@ protected function configure(): void
InputOption::VALUE_NONE,
'Remove cached repositories composer.json files'
);
+
+ // add --debug option
+ $this->addOption('debug', null, InputOption::VALUE_NONE, 'Enable debug mode for more verbose output');
}
protected function execute(InputInterface $input, OutputInterface $output): int
@@ -54,24 +57,26 @@ protected function execute(InputInterface $input, OutputInterface $output): int
$monitorConfig = $this->monitorConfigProvider->provide();
$shouldClearCache = (bool) $input->getOption('clear-cache');
+ $isDebug = (bool) $input->getOption('debug');
- $this->symfonyStyle->title('Showing Dependency Matrix');
+ $this->symfonyStyle->title('Composer Dependency Matrix');
$this->repositoryMetafilesResolver->decorateRepositories(
$monitorConfig->getRepositoryCollection(),
- $shouldClearCache
+ $shouldClearCache,
+ $isDebug
);
+ $this->symfonyStyle->newLine(2);
+
$repositoryCollection = $monitorConfig->getRepositoryCollection();
$requiredPackageNames = $monitorConfig->getComposerRequiredPackageNames();
- $tableHeadlines = array_merge(['dependency'], $repositoryCollection->getRepositoryNames());
+ $tableHeadlines = array_merge(['dependency'], $repositoryCollection->getRepositoryNamesByPackageCount());
$tableRows = $this->createTableRows($requiredPackageNames, $repositoryCollection);
$this->renderTable($tableHeadlines, $tableRows);
- $this->symfonyStyle->newLine();
-
return self::SUCCESS;
}
@@ -93,7 +98,6 @@ private function createTableRows(array $requiredPackageNames, RepositoryCollecti
$dataRow = [];
foreach ($repositoryCollection->allSorterByPackageCount() as $composerJson) {
-
$packageVersion = $composerJson->getPackageVersion($requiredPackageName);
if ($packageVersion !== null) {
++$knownValuesCount;
@@ -112,7 +116,7 @@ private function createTableRows(array $requiredPackageNames, RepositoryCollecti
}
$dataRow = SymfonyColumnStyler::styleHighsAndLows($dataRow);
- $shortRequiredPackageName = Strings::truncate($requiredPackageName, 25);
+ $shortRequiredPackageName = Strings::truncate($requiredPackageName, 35);
$tableRow = array_merge([$shortRequiredPackageName], $dataRow);
$tableRows[] = $tableRow;
diff --git a/src/ValueObject/RepositoryCollection.php b/src/ValueObject/RepositoryCollection.php
index bd9c04c..4e87991 100644
--- a/src/ValueObject/RepositoryCollection.php
+++ b/src/ValueObject/RepositoryCollection.php
@@ -26,7 +26,6 @@ public function getComposerRequiredPackageNames(): array
$requiredPackageNames = [];
foreach ($this->repositories as $repository) {
$composerJson = $repository->getComposerJson();
-
$requiredPackageNames = array_merge($requiredPackageNames, $composerJson->getRequiredPackageNames());
}
@@ -49,6 +48,19 @@ public function getRepositoryNames(): array
return $repositoryNames;
}
+ /**
+ * @return string[]
+ */
+ public function getRepositoryNamesByPackageCount(): array
+ {
+ $repositoryNames = [];
+ foreach ($this->allSorterByPackageCount() as $composerJson) {
+ $repositoryNames[] = $composerJson->getRepositoryName();
+ }
+
+ return $repositoryNames;
+ }
+
public function count(): int
{
return count($this->repositories);