diff --git a/README.md b/README.md index 44f438f..0ac9b06 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ composer require bringyourownideas/silverstripe-maintenance Build schema and queue an initial job to populate the database: ```sh -sake dev/build +sake db:build --flush ``` If you haven't already, you need to [configure the job queue](https://github.com/symbiote/silverstripe-queuedjobs) @@ -58,8 +58,9 @@ BringYourOwnIdeas\Maintenance\Jobs\CheckForUpdatesJob: By default, tasks are run through a job queue. You can also choose to manually refresh via the command line. Run the update task (includes the [update-checker](https://github.com/bringyourownideas/silverstripe-composer-update-checker)) -``` -sake dev/tasks/UpdatePackageInfoTask + +```sh +sake tasks:UpdatePackageInfoTask ``` ## How your composer.json influences the report diff --git a/src/Jobs/CheckForUpdatesJob.php b/src/Jobs/CheckForUpdatesJob.php index f19d9fd..2b6bb23 100644 --- a/src/Jobs/CheckForUpdatesJob.php +++ b/src/Jobs/CheckForUpdatesJob.php @@ -8,8 +8,10 @@ use SilverStripe\ORM\FieldType\DBDatetime; use Symbiote\QueuedJobs\Services\QueuedJob; use SilverStripe\Core\Injector\Injector; +use SilverStripe\PolyExecution\PolyOutput; use Symbiote\QueuedJobs\Services\AbstractQueuedJob; use Symbiote\QueuedJobs\Services\QueuedJobService; +use Symfony\Component\Console\Input\ArrayInput; /** * Refresh report job. Runs as a queued job. @@ -59,7 +61,10 @@ public function process() { // Run the UpdatePackageInfo task $updateTask = Injector::inst()->create(UpdatePackageInfoTask::class); - $updateTask->run(null); + $output = PolyOutput::create(PolyOutput::FORMAT_ANSI); + $input = new ArrayInput([]); + $input->setInteractive(false); + $updateTask->run($input, $output); // mark job as completed $this->isComplete = true; diff --git a/src/Tasks/UpdatePackageInfoTask.php b/src/Tasks/UpdatePackageInfoTask.php index a98a6cc..6c9096f 100644 --- a/src/Tasks/UpdatePackageInfoTask.php +++ b/src/Tasks/UpdatePackageInfoTask.php @@ -3,10 +3,7 @@ namespace BringYourOwnIdeas\Maintenance\Tasks; use BringYourOwnIdeas\Maintenance\Util\ComposerLoader; -use BringYourOwnIdeas\Maintenance\Util\ModuleHealthLoader; -use BringYourOwnIdeas\Maintenance\Util\SupportedAddonsLoader; use RuntimeException; -use SilverStripe\Control\HTTPRequest; use SilverStripe\Core\Convert; use SilverStripe\Core\Environment; use SilverStripe\ORM\Queries\SQLDelete; @@ -14,20 +11,18 @@ use BringYourOwnIdeas\Maintenance\Model\Package; use SilverStripe\Core\Manifest\VersionProvider; use SilverStripe\Dev\BuildTask; -use SilverStripe\Dev\Deprecation; +use SilverStripe\PolyExecution\PolyOutput; use SilverStripe\SupportedModules\BranchLogic; use SilverStripe\SupportedModules\MetaData; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; /** * Parses a composer lock file in order to cache information about the installation. */ class UpdatePackageInfoTask extends BuildTask { - /** - * {@inheritDoc} - * @var string - */ - private static $segment = 'UpdatePackageInfoTask'; + protected static string $commandName = 'UpdatePackageInfoTask'; /** * A custom memory limit to set for this to increase to (or do nothing if the memory is already set high enough) @@ -43,8 +38,6 @@ class UpdatePackageInfoTask extends BuildTask */ private static $dependencies = [ 'ComposerLoader' => '%$BringYourOwnIdeas\\Maintenance\\Util\\ComposerLoader', - 'SupportedAddonsLoader' => '%$BringYourOwnIdeas\\Maintenance\\Util\\SupportedAddonsLoader', - 'ModuleHealthLoader' => '%$BringYourOwnIdeas\\Maintenance\\Util\\ModuleHealthLoader', ]; /** @@ -63,17 +56,6 @@ class UpdatePackageInfoTask extends BuildTask */ protected $composerLoader; - /** - * @var SupportedAddonsLoader - */ - protected $supportedAddonsLoader; - - /** - * @var ModuleHealthLoader - * @deprecated 3.2.0 Will be removed without equivalent functionality - */ - protected $moduleHealthLoader; - /** * Fetch the composer loader * @@ -97,54 +79,12 @@ public function setComposerLoader($composerLoader) return $this; } - /** - * @return SupportedAddonsLoader - */ - public function getSupportedAddonsLoader() - { - return $this->supportedAddonsLoader; - } - - /** - * @param SupportedAddonsLoader $supportedAddonsLoader - * @return $this - */ - public function setSupportedAddonsLoader(SupportedAddonsLoader $supportedAddonsLoader) - { - $this->supportedAddonsLoader = $supportedAddonsLoader; - return $this; - } - - /** - * @return ModuleHealthLoader - * @deprecated 3.2.0 Will be removed without equivalent functionality - */ - public function getModuleHealthLoader() - { - Deprecation::notice('3.2.0', 'Will be removed without equivalent functionality'); - return $this->moduleHealthLoader; - } - - /** - * @param ModuleHealthLoader $moduleHealthLoader - * @return $this - * @deprecated 3.2.0 Will be removed without equivalent functionality - */ - public function setModuleHealthLoader(ModuleHealthLoader $moduleHealthLoader) - { - Deprecation::withNoReplacement( - fn() => Deprecation::notice('3.2.0', 'Will be removed without equivalent functionality') - ); - $this->moduleHealthLoader = $moduleHealthLoader; - return $this; - } - - public function getTitle() + public function getTitle(): string { return _t(__CLASS__ . '.TITLE', 'Refresh installed package info'); } - public function getDescription() + public static function getDescription(): string { return _t( __CLASS__ . '.DESCRIPTION', @@ -155,10 +95,8 @@ public function getDescription() /** * Update database cached information about this site. - * - * @param HTTPRequest $request unused, can be null (must match signature of parent function). */ - public function run($request) + protected function execute(InputInterface $input, PolyOutput $output): int { // Loading packages and all their updates can be quite memory intensive. $memoryLimit = $this->config()->get('memory_limit'); @@ -172,7 +110,7 @@ public function run($request) $composerLock = $this->getComposerLoader()->getLock(); $rawPackages = array_merge($composerLock->packages, (array) $composerLock->{'packages-dev'}); $packages = $this->getPackageInfo($rawPackages); - $supportedPackages = $this->getSupportedPackages(); + $supportedPackages = $this->getSupportedPackages($output); // Extensions to the process that add data may rely on external services. // There may be a communication issue between the site and the external service, @@ -190,6 +128,8 @@ public function run($request) Package::create()->update($package)->write(); } } + + return Command::SUCCESS; } /** @@ -218,10 +158,8 @@ public function getPackageInfo($packageList) /** * Return an array of supported modules as fetched from silverstripe/supported-modules. * Outputs a message and returns null if an error occurs - * - * @return null|array */ - public function getSupportedPackages() + public function getSupportedPackages(PolyOutput $output): ?array { try { $repos = MetaData::getAllRepositoryMetaData()[MetaData::CATEGORY_SUPPORTED]; @@ -236,27 +174,7 @@ public function getSupportedPackages() $repos )); } catch (RuntimeException $exception) { - echo $exception->getMessage() . PHP_EOL; - } - - return null; - } - - /** - * Return an array of module health information as fetched from addons.silverstripe.org. - * Outputs a message and returns null if an error occurs - * - * @param string[] $moduleNames - * @return null|array - * @deprecated 3.2.0 Will be removed without equivalent functionality - */ - public function getHealthIndicator(array $moduleNames) - { - Deprecation::notice('3.2.0', 'Will be removed without equivalent functionality'); - try { - return $this->getModuleHealthLoader()->setModuleNames($moduleNames)->getModuleHealthInfo() ?: []; - } catch (RuntimeException $exception) { - echo $exception->getMessage() . PHP_EOL; + $output->writeln(''.$exception->getMessage().''); } return null; diff --git a/src/Util/SupportedAddonsLoader.php b/src/Util/SupportedAddonsLoader.php deleted file mode 100644 index 72ed7ae..0000000 --- a/src/Util/SupportedAddonsLoader.php +++ /dev/null @@ -1,46 +0,0 @@ - Deprecation::notice( - '3.2.0', - 'Use ' . UpdatePackageInfoTask::class . '::getSupportedPackages() instead.', - Deprecation::SCOPE_CLASS - ) - ); - } - - /** - * Return the list of supported modules - * - * @return array - */ - public function getAddonNames() - { - // Check for a cached value and return if one is available - $endpoint = 'https://raw.githubusercontent.com/silverstripe/supported-modules/main/repositories.json'; - return $this->doRequest($endpoint, function ($responseJson) { - return array_filter(array_map( - fn(array $item) => isset($item['majorVersionMapping'][5]) ? $item['packagist'] : null, - $responseJson['supportedModules'] - )); - }); - } - - protected function getCacheKey() - { - return 'addons'; - } -} diff --git a/tests/Tasks/UpdatePackageInfoTest.php b/tests/Tasks/UpdatePackageInfoTest.php index cdb11a1..562a302 100644 --- a/tests/Tasks/UpdatePackageInfoTest.php +++ b/tests/Tasks/UpdatePackageInfoTest.php @@ -11,6 +11,9 @@ use SilverStripe\Dev\SapphireTest; use SilverStripe\SupportedModules\MetaData; use SilverStripe\Core\Injector\Injector; +use SilverStripe\PolyExecution\PolyOutput; +use Symfony\Component\Console\Input\ArrayInput; +use Symfony\Component\Console\Output\BufferedOutput; /** * @mixin PHPUnit_Framework_TestCase @@ -82,7 +85,11 @@ public function getModuleVersion(string $module): string $task = UpdatePackageInfoTask::create(); $task->setComposerLoader($composerLoader); - $task->run(null); + $output = PolyOutput::create(PolyOutput::FORMAT_ANSI); + $output->setWrappedOutput(new BufferedOutput()); + $input = new ArrayInput([]); + $input->setInteractive(false); + $task->run($input, $output); $packages = Package::get(); $this->assertCount(2, $packages); diff --git a/tests/Util/ModuleHealthLoaderTest.php b/tests/Util/ModuleHealthLoaderTest.php deleted file mode 100644 index c6ed3df..0000000 --- a/tests/Util/ModuleHealthLoaderTest.php +++ /dev/null @@ -1,32 +0,0 @@ -loader = $this->getMockBuilder(ModuleHealthLoader::class) - ->setMethods(['doRequest']) - ->getMock(); - } - - public function testModuleNamesAreInTheRequestUrl() - { - $this->loader->setModuleNames(['foo/bar', 'bar/baz']); - - $this->loader->expects($this->once()) - ->method('doRequest') - ->with('addons.silverstripe.org/api/ratings?addons=foo/bar,bar/baz'); - - $this->loader->getModuleHealthInfo(); - } -} diff --git a/tests/Util/SupportedAddonsLoaderTest.php b/tests/Util/SupportedAddonsLoaderTest.php deleted file mode 100644 index 413544f..0000000 --- a/tests/Util/SupportedAddonsLoaderTest.php +++ /dev/null @@ -1,110 +0,0 @@ -loader = $this->getMockBuilder(SupportedAddonsLoader::class) - ->setMethods(['doRequest']) - ->getMock(); - } - - public function testCallsSupportedAddonsEndpoint() - { - $endpoint = 'https://raw.githubusercontent.com/silverstripe/supported-modules/main/repositories.json'; - $this->loader->expects($this->once()) - ->method('doRequest') - ->with($endpoint, function () { - // no-op - }); - - $this->loader->getAddonNames(); - } - - public function testCallbackReturnsAddonsFromBody() - { - $this->loader->expects($this->once()) - ->method('doRequest') - ->with($this->isType('string'), $this->isType('callable')) - ->will($this->returnArgument(1)); - - $result = $this->loader->getAddonNames(); - $mockResponse = [ - 'supportedModules' => [ - [ - 'github' => 'some/repo1', - 'packagist' => 'foo/bar', - 'majorVersionMapping' => [ - 4 => [4], - 5 => [5], - ], - ], - [ - 'github' => 'some/repo2', - 'packagist' => 'bin/baz', - 'majorVersionMapping' => [ - 5 => [5, 6], - ], - ], - [ - 'github' => 'some/repo3', - 'packagist' => 'bin/baz2', - 'majorVersionMapping' => [ - 4 => [4], - ], - ], - ], - 'workflow' => [ - [ - 'github' => 'some/repo4', - 'packagist' => 'bin/baz1', - 'majorVersionMapping' => [ - 4 => [4], - 5 => [5], - ], - ], - ], - 'tooling' => [ - [ - 'github' => 'some/repo5', - 'packagist' => 'bin/baz2', - 'majorVersionMapping' => [ - 5 => [5, 6], - ], - ], - ], - 'misc' => [ - [ - 'github' => 'some/repo6', - 'packagist' => 'bin/baz3', - 'majorVersionMapping' => [ - 4 => [4], - ], - ], - ], - ]; - - $this->assertSame(['foo/bar', 'bin/baz'], $result($mockResponse)); - } - - public function testValueOfDoRequestIsReturned() - { - $this->loader->expects($this->once()) - ->method('doRequest') - ->willReturn('hello world'); - - $this->assertSame('hello world', $this->loader->getAddonNames()); - } -}