From 7e7222ef0b0d7f0a0b9635543c0d7d09ef720cf1 Mon Sep 17 00:00:00 2001 From: Jess Archer Date: Wed, 17 Aug 2022 00:53:54 +1000 Subject: [PATCH] [1.x] Build and pull images on install (#467) --- src/Console/InstallCommand.php | 90 ++++++++++++++++++++++++++++------ 1 file changed, 75 insertions(+), 15 deletions(-) diff --git a/src/Console/InstallCommand.php b/src/Console/InstallCommand.php index a12fe9a4..ff027c66 100644 --- a/src/Console/InstallCommand.php +++ b/src/Console/InstallCommand.php @@ -3,6 +3,8 @@ namespace Laravel\Sail\Console; use Illuminate\Console\Command; +use RuntimeException; +use Symfony\Component\Process\Process; class InstallCommand extends Command { @@ -22,10 +24,27 @@ class InstallCommand extends Command */ protected $description = 'Install Laravel Sail\'s default Docker Compose file'; + /** + * The available services that may be installed. + * + * @var array + */ + protected $services = [ + 'mysql', + 'pgsql', + 'mariadb', + 'redis', + 'memcached', + 'meilisearch', + 'minio', + 'mailhog', + 'selenium', + ]; + /** * Execute the console command. * - * @return void + * @return int|null */ public function handle() { @@ -37,6 +56,12 @@ public function handle() $services = $this->gatherServicesWithSymfonyMenu(); } + if ($invalidServices = array_diff($services, $this->services)) { + $this->error('Invalid services ['.implode(',', $invalidServices).'].'); + + return 1; + } + $this->buildDockerCompose($services); $this->replaceEnvVariables($services); $this->configurePhpUnit(); @@ -46,6 +71,8 @@ public function handle() } $this->info('Sail scaffolding installed successfully.'); + + return $this->prepareInstallation($services); } /** @@ -55,17 +82,7 @@ public function handle() */ protected function gatherServicesWithSymfonyMenu() { - return $this->choice('Which services would you like to install?', [ - 'mysql', - 'pgsql', - 'mariadb', - 'redis', - 'memcached', - 'meilisearch', - 'minio', - 'mailhog', - 'selenium', - ], 0, null, true); + return $this->choice('Which services would you like to install?', $this->services, 0, null, true); } /** @@ -77,9 +94,7 @@ protected function gatherServicesWithSymfonyMenu() protected function buildDockerCompose(array $services) { $depends = collect($services) - ->filter(function ($service) { - return in_array($service, ['mysql', 'pgsql', 'mariadb', 'redis', 'meilisearch', 'minio', 'selenium']); - })->map(function ($service) { + ->map(function ($service) { return " - {$service}"; })->whenNotEmpty(function ($collection) { return $collection->prepend('depends_on:'); @@ -191,4 +206,49 @@ protected function installDevContainer() file_put_contents($this->laravel->basePath('.env'), $environment); } + + /** + * Prepare the installation by pulling and building any necessary images. + * + * @param array $services + * @return int|null + */ + protected function prepareInstallation($services) + { + $status = $this->runCommands([ + './vendor/bin/sail pull '.implode(' ', $services), + './vendor/bin/sail build', + ]); + + if ($status !== 0) { + $this->warn('Unable to download and build your Sail images. Is Docker installed and running?'); + + return 1; + } + + $this->info('Sail images installed successfully.'); + } + + /** + * Run the given commands. + * + * @param array $commands + * @return int + */ + protected function runCommands($commands) + { + $process = Process::fromShellCommandline(implode(' && ', $commands), null, null, null, null); + + if ('\\' !== DIRECTORY_SEPARATOR && file_exists('/dev/tty') && is_readable('/dev/tty')) { + try { + $process->setTty(true); + } catch (RuntimeException $e) { + $this->output->writeln(' WARN '.$e->getMessage().PHP_EOL); + } + } + + return $process->run(function ($type, $line) { + $this->output->write(' '.$line); + }); + } }