diff --git a/.docker/main/drupal/composer.json b/.docker/main/drupal/composer.json index eacd408..81d357b 100644 --- a/.docker/main/drupal/composer.json +++ b/.docker/main/drupal/composer.json @@ -31,10 +31,11 @@ "sort-packages": true, "allow-plugins": { "composer/installers": true, + "dealerdirect/phpcodesniffer-composer-installer": true, "drupal/core-composer-scaffold": true, "drupal/core-project-message": true, "drupal/core-vendor-hardening": true, - "dealerdirect/phpcodesniffer-composer-installer": true + "phpro/grumphp": true } }, "extra": { @@ -72,5 +73,8 @@ "type:drupal-custom-theme" ] } + }, + "require-dev": { + "phpro/grumphp": "^2" } } diff --git a/composer.json b/composer.json index 26c15d8..e680d9a 100644 --- a/composer.json +++ b/composer.json @@ -18,8 +18,8 @@ "homepage": "https://github.com/jigarius/drall", "require": { "php": ">= 8.3", - "amphp/process": "^1.1", - "amphp/sync": "^1.4", + "amphp/pipeline": "^1.2", + "amphp/process": "^2", "consolidation/filter-via-dot-access-data": "^2.0", "consolidation/site-alias": "^3 || ^4", "drush/drush": "^12 || ^13", @@ -29,7 +29,6 @@ "dealerdirect/phpcodesniffer-composer-installer": "^0.7.1", "drupal/coder": "^8.3", "ergebnis/composer-normalize": "^2.28", - "phpro/grumphp": "^1.13", "phpunit/phpunit": "^9.5", "squizlabs/php_codesniffer": "^3.6" }, @@ -47,8 +46,7 @@ "config": { "allow-plugins": { "dealerdirect/phpcodesniffer-composer-installer": true, - "ergebnis/composer-normalize": true, - "phpro/grumphp": true + "ergebnis/composer-normalize": true }, "sort-packages": true }, diff --git a/src/Command/ExecCommand.php b/src/Command/ExecCommand.php index b31487e..2f32db3 100644 --- a/src/Command/ExecCommand.php +++ b/src/Command/ExecCommand.php @@ -3,11 +3,8 @@ namespace Drall\Command; use Amp\ByteStream; -use Amp\Iterator; -use Amp\Loop; +use Amp\Pipeline\Pipeline; use Amp\Process\Process; -use Amp\Sync\ConcurrentIterator; -use Amp\Sync\LocalSemaphore; use Drall\Model\EnvironmentId; use Drall\Model\Placeholder; use Drall\Trait\SignalAwareTrait; @@ -162,11 +159,12 @@ private function checkIntervalOption(InputInterface $input, OutputInterface $out private function checkWorkersOption(InputInterface $input, OutputInterface $output): void { $workers = $input->getOption('workers'); + $limit = self::WORKER_LIMIT; - if ($workers > self::WORKER_LIMIT) { - $limit = self::WORKER_LIMIT; + if ($workers < 1 || $workers > $limit) { + ; $output->writeln(<<--workers must be less than or equal to $limit. +The value for --workers must be between 1 and $limit. EOT); throw new \RuntimeException('Invalid options detected'); } @@ -225,8 +223,6 @@ protected function execute(InputInterface $input, OutputInterface $output): int return 0; } - $workers = $workers = $input->getOption('workers'); - // Display commands without executing them. if ($input->getOption('dry-run')) { foreach ($values as $value) { @@ -260,66 +256,112 @@ protected function execute(InputInterface $input, OutputInterface $output): int $isStopping = TRUE; }); - Loop::run(function () use ( - $values, - $command, - $placeholder, - $input, - $output, - $progressBar, - $workers, - &$exitCode, - &$isStopping - ) { - yield ConcurrentIterator\each( - Iterator\fromIterable($values), - new LocalSemaphore($workers), - function ($value) use ( - $command, - $placeholder, - $input, - $output, - $progressBar, - &$exitCode, - &$isStopping, - ) { - if ($isStopping) { - return; - } - - $pCommand = Placeholder::replace([$placeholder->value => $value], $command); - $process = new Process("($pCommand) 2>&1", getcwd()); - - yield $process->start(); - $this->logger->debug('Running: {command}', ['command' => $pCommand]); - - // @todo Improve formatting of headings. - $pOutput = yield ByteStream\buffer($process->getStdout()); - $pStatus = 'Done'; - $pIcon = '✔'; - if (Command::SUCCESS !== yield $process->join()) { - $pStatus = 'Failed'; - $pIcon = '✖'; - $exitCode = Command::FAILURE; - } - - $pMessage = "$pIcon $value: $pStatus"; - - $progressBar->clear(); - // Always display command output, even in --quiet mode. - $output->writeln($pMessage, OutputInterface::VERBOSITY_QUIET); - $output->write($pOutput); - - $progressBar->advance(); - $progressBar->display(); - - // Wait between commands if --interval is specified. - if ($interval = $input->getOption('interval')) { - sleep($interval); - } + Pipeline::fromIterable($values) + ->concurrent($input->getOption('workers')) + ->unordered() + ->forEach((function ($value) use ( + $input, + $output, + $command, + $placeholder, + $progressBar, + &$exitCode, + &$isStopping, + ) { + if ($isStopping) { + return; } - ); - }); + + $pCommand = Placeholder::replace([$placeholder->value => $value], $command); + $process = Process::start("($pCommand) 2>&1"); + $this->logger->debug('Running: {command}', ['command' => $pCommand]); + + // @todo Improve formatting of headings. + $pOutput = ByteStream\buffer($process->getStdout()); + $pStatus = 'Done'; + $pIcon = '✔'; + if (Command::SUCCESS !== $process->join()) { + $pStatus = 'Failed'; + $pIcon = '✖'; + $exitCode = Command::FAILURE; + } + + $pMessage = "$pIcon $value: $pStatus"; + + $progressBar->clear(); + // Always display command output, even in --quiet mode. + $output->writeln($pMessage, OutputInterface::VERBOSITY_QUIET); + $output->write($pOutput); + + $progressBar->advance(); + $progressBar->display(); + + // Wait between commands if --interval is specified. + if ($interval = $input->getOption('interval')) { + sleep($interval); + } + })); + +// Loop::run(function () use ( +// $values, +// $command, +// $placeholder, +// $input, +// $output, +// $progressBar, +// $workers, +// &$exitCode, +// &$isStopping +// ) { +// yield ConcurrentIterator\each( +// Iterator\fromIterable($values), +// new LocalSemaphore($workers), +// function ($value) use ( +// $command, +// $placeholder, +// $input, +// $output, +// $progressBar, +// &$exitCode, +// &$isStopping, +// ) { +// if ($isStopping) { +// return; +// } +// +// $pCommand = Placeholder::replace([$placeholder->value => $value], $command); +// $process = new Process("($pCommand) 2>&1", getcwd()); +// +// yield $process->start(); +// $this->logger->debug('Running: {command}', ['command' => $pCommand]); +// +// // @todo Improve formatting of headings. +// $pOutput = yield ByteStream\buffer($process->getStdout()); +// $pStatus = 'Done'; +// $pIcon = '✔'; +// if (Command::SUCCESS !== yield $process->join()) { +// $pStatus = 'Failed'; +// $pIcon = '✖'; +// $exitCode = Command::FAILURE; +// } +// +// $pMessage = "$pIcon $value: $pStatus"; +// +// $progressBar->clear(); +// // Always display command output, even in --quiet mode. +// $output->writeln($pMessage, OutputInterface::VERBOSITY_QUIET); +// $output->write($pOutput); +// +// $progressBar->advance(); +// $progressBar->display(); +// +// // Wait between commands if --interval is specified. +// if ($interval = $input->getOption('interval')) { +// sleep($interval); +// } +// } +// ); +// }); if (!$isStopping) { $progressBar->finish(); diff --git a/src/Drall.php b/src/Drall.php index ef796f0..a726d1d 100644 --- a/src/Drall.php +++ b/src/Drall.php @@ -66,6 +66,7 @@ protected function getDefaultInputDefinition(): InputDefinition { $options = $definition->getOptions(); unset( $options['no-interaction'], + $options['silent'], ); $definition->setOptions($options); diff --git a/test/Integration/Command/ExecCommandTest.php b/test/Integration/Command/ExecCommandTest.php index f84f5d9..9f40071 100644 --- a/test/Integration/Command/ExecCommandTest.php +++ b/test/Integration/Command/ExecCommandTest.php @@ -744,7 +744,7 @@ public function testWorkerLimit(): void { ); $process->run(); $this->assertOutputEquals(<<getOutput()); $this->assertOutputContainsString('Invalid options detected', $process->getErrorOutput());