first commit
This commit is contained in:
60
vendor/laravel/sail/src/Console/AddCommand.php
vendored
Normal file
60
vendor/laravel/sail/src/Console/AddCommand.php
vendored
Normal file
@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Sail\Console;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use Laravel\Sail\Console\Concerns\InteractsWithDockerComposeServices;
|
||||
use Symfony\Component\Console\Attribute\AsCommand;
|
||||
|
||||
#[AsCommand(name: 'sail:add')]
|
||||
class AddCommand extends Command
|
||||
{
|
||||
use InteractsWithDockerComposeServices;
|
||||
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'sail:add
|
||||
{services? : The services that should be added}
|
||||
';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Add a service to an existing Sail installation';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return int|null
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
if ($this->argument('services')) {
|
||||
$services = $this->argument('services') == 'none' ? [] : explode(',', $this->argument('services'));
|
||||
} elseif ($this->option('no-interaction')) {
|
||||
$services = $this->defaultServices;
|
||||
} else {
|
||||
$services = $this->gatherServicesInteractively();
|
||||
}
|
||||
|
||||
if ($invalidServices = array_diff($services, $this->services)) {
|
||||
$this->components->error('Invalid services ['.implode(',', $invalidServices).'].');
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
$this->buildDockerCompose($services);
|
||||
$this->replaceEnvVariables($services);
|
||||
$this->configurePhpUnit();
|
||||
|
||||
$this->prepareInstallation($services);
|
||||
|
||||
$this->output->writeln('');
|
||||
$this->components->info('Additional Sail services installed successfully.');
|
||||
}
|
||||
}
|
289
vendor/laravel/sail/src/Console/Concerns/InteractsWithDockerComposeServices.php
vendored
Normal file
289
vendor/laravel/sail/src/Console/Concerns/InteractsWithDockerComposeServices.php
vendored
Normal file
@ -0,0 +1,289 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Sail\Console\Concerns;
|
||||
|
||||
use Symfony\Component\Process\Process;
|
||||
use Symfony\Component\Yaml\Yaml;
|
||||
|
||||
trait InteractsWithDockerComposeServices
|
||||
{
|
||||
/**
|
||||
* The available services that may be installed.
|
||||
*
|
||||
* @var array<string>
|
||||
*/
|
||||
protected $services = [
|
||||
'mysql',
|
||||
'pgsql',
|
||||
'mariadb',
|
||||
'redis',
|
||||
'memcached',
|
||||
'meilisearch',
|
||||
'typesense',
|
||||
'minio',
|
||||
'mailpit',
|
||||
'selenium',
|
||||
'soketi',
|
||||
];
|
||||
|
||||
/**
|
||||
* The default services used when the user chooses non-interactive mode.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
protected $defaultServices = ['mysql', 'redis', 'selenium', 'mailpit'];
|
||||
|
||||
/**
|
||||
* Gather the desired Sail services using an interactive prompt.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function gatherServicesInteractively()
|
||||
{
|
||||
if (function_exists('\Laravel\Prompts\multiselect')) {
|
||||
return \Laravel\Prompts\multiselect(
|
||||
label: 'Which services would you like to install?',
|
||||
options: $this->services,
|
||||
default: ['mysql'],
|
||||
);
|
||||
}
|
||||
|
||||
return $this->choice('Which services would you like to install?', $this->services, 0, null, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the Docker Compose file.
|
||||
*
|
||||
* @param array $services
|
||||
* @return void
|
||||
*/
|
||||
protected function buildDockerCompose(array $services)
|
||||
{
|
||||
$composePath = base_path('docker-compose.yml');
|
||||
|
||||
$compose = file_exists($composePath)
|
||||
? Yaml::parseFile($composePath)
|
||||
: Yaml::parse(file_get_contents(__DIR__ . '/../../../stubs/docker-compose.stub'));
|
||||
|
||||
// Adds the new services as dependencies of the laravel.test service...
|
||||
if (! array_key_exists('laravel.test', $compose['services'])) {
|
||||
$this->warn('Couldn\'t find the laravel.test service. Make sure you add ['.implode(',', $services).'] to the depends_on config.');
|
||||
} else {
|
||||
$compose['services']['laravel.test']['depends_on'] = collect($compose['services']['laravel.test']['depends_on'] ?? [])
|
||||
->merge($services)
|
||||
->unique()
|
||||
->values()
|
||||
->all();
|
||||
}
|
||||
|
||||
// Add the services to the docker-compose.yml...
|
||||
collect($services)
|
||||
->filter(function ($service) use ($compose) {
|
||||
return ! array_key_exists($service, $compose['services'] ?? []);
|
||||
})->each(function ($service) use (&$compose) {
|
||||
$compose['services'][$service] = Yaml::parseFile(__DIR__ . "/../../../stubs/{$service}.stub")[$service];
|
||||
});
|
||||
|
||||
// Merge volumes...
|
||||
collect($services)
|
||||
->filter(function ($service) {
|
||||
return in_array($service, ['mysql', 'pgsql', 'mariadb', 'redis', 'meilisearch', 'typesense', 'minio']);
|
||||
})->filter(function ($service) use ($compose) {
|
||||
return ! array_key_exists($service, $compose['volumes'] ?? []);
|
||||
})->each(function ($service) use (&$compose) {
|
||||
$compose['volumes']["sail-{$service}"] = ['driver' => 'local'];
|
||||
});
|
||||
|
||||
// If the list of volumes is empty, we can remove it...
|
||||
if (empty($compose['volumes'])) {
|
||||
unset($compose['volumes']);
|
||||
}
|
||||
|
||||
// Replace Selenium with ARM base container on Apple Silicon...
|
||||
if (in_array('selenium', $services) && in_array(php_uname('m'), ['arm64', 'aarch64'])) {
|
||||
$compose['services']['selenium']['image'] = 'seleniarm/standalone-chromium';
|
||||
}
|
||||
|
||||
file_put_contents($this->laravel->basePath('docker-compose.yml'), Yaml::dump($compose, Yaml::DUMP_OBJECT_AS_MAP));
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the Host environment variables in the app's .env file.
|
||||
*
|
||||
* @param array $services
|
||||
* @return void
|
||||
*/
|
||||
protected function replaceEnvVariables(array $services)
|
||||
{
|
||||
$environment = file_get_contents($this->laravel->basePath('.env'));
|
||||
|
||||
if (in_array('mysql', $services) ||
|
||||
in_array('mariadb', $services) ||
|
||||
in_array('pgsql', $services)) {
|
||||
$defaults = [
|
||||
'# DB_HOST=127.0.0.1',
|
||||
'# DB_PORT=3306',
|
||||
'# DB_DATABASE=laravel',
|
||||
'# DB_USERNAME=root',
|
||||
'# DB_PASSWORD=',
|
||||
];
|
||||
|
||||
foreach ($defaults as $default) {
|
||||
$environment = str_replace($default, substr($default, 2), $environment);
|
||||
}
|
||||
}
|
||||
|
||||
if (in_array('mysql', $services)) {
|
||||
$environment = preg_replace('/DB_CONNECTION=.*/', 'DB_CONNECTION=mysql', $environment);
|
||||
$environment = str_replace('DB_HOST=127.0.0.1', "DB_HOST=mysql", $environment);
|
||||
}elseif (in_array('pgsql', $services)) {
|
||||
$environment = preg_replace('/DB_CONNECTION=.*/', 'DB_CONNECTION=pgsql', $environment);
|
||||
$environment = str_replace('DB_HOST=127.0.0.1', "DB_HOST=pgsql", $environment);
|
||||
$environment = str_replace('DB_PORT=3306', "DB_PORT=5432", $environment);
|
||||
} elseif (in_array('mariadb', $services)) {
|
||||
if ($this->laravel->config->has('database.connections.mariadb')) {
|
||||
$environment = preg_replace('/DB_CONNECTION=.*/', 'DB_CONNECTION=mariadb', $environment);
|
||||
}
|
||||
|
||||
$environment = str_replace('DB_HOST=127.0.0.1', "DB_HOST=mariadb", $environment);
|
||||
}
|
||||
|
||||
$environment = str_replace('DB_USERNAME=root', "DB_USERNAME=sail", $environment);
|
||||
$environment = preg_replace("/DB_PASSWORD=(.*)/", "DB_PASSWORD=password", $environment);
|
||||
|
||||
if (in_array('memcached', $services)) {
|
||||
$environment = str_replace('MEMCACHED_HOST=127.0.0.1', 'MEMCACHED_HOST=memcached', $environment);
|
||||
}
|
||||
|
||||
if (in_array('redis', $services)) {
|
||||
$environment = str_replace('REDIS_HOST=127.0.0.1', 'REDIS_HOST=redis', $environment);
|
||||
}
|
||||
|
||||
if (in_array('meilisearch', $services)) {
|
||||
$environment .= "\nSCOUT_DRIVER=meilisearch";
|
||||
$environment .= "\nMEILISEARCH_HOST=http://meilisearch:7700\n";
|
||||
$environment .= "\nMEILISEARCH_NO_ANALYTICS=false\n";
|
||||
}
|
||||
|
||||
if (in_array('typesense', $services)) {
|
||||
$environment .= "\nSCOUT_DRIVER=typesense";
|
||||
$environment .= "\nTYPESENSE_HOST=typesense";
|
||||
$environment .= "\nTYPESENSE_PORT=8108";
|
||||
$environment .= "\nTYPESENSE_PROTOCOL=http";
|
||||
$environment .= "\nTYPESENSE_API_KEY=xyz\n";
|
||||
}
|
||||
|
||||
if (in_array('soketi', $services)) {
|
||||
$environment = preg_replace("/^BROADCAST_DRIVER=(.*)/m", "BROADCAST_DRIVER=pusher", $environment);
|
||||
$environment = preg_replace("/^PUSHER_APP_ID=(.*)/m", "PUSHER_APP_ID=app-id", $environment);
|
||||
$environment = preg_replace("/^PUSHER_APP_KEY=(.*)/m", "PUSHER_APP_KEY=app-key", $environment);
|
||||
$environment = preg_replace("/^PUSHER_APP_SECRET=(.*)/m", "PUSHER_APP_SECRET=app-secret", $environment);
|
||||
$environment = preg_replace("/^PUSHER_HOST=(.*)/m", "PUSHER_HOST=soketi", $environment);
|
||||
$environment = preg_replace("/^PUSHER_PORT=(.*)/m", "PUSHER_PORT=6001", $environment);
|
||||
$environment = preg_replace("/^PUSHER_SCHEME=(.*)/m", "PUSHER_SCHEME=http", $environment);
|
||||
$environment = preg_replace("/^VITE_PUSHER_HOST=(.*)/m", "VITE_PUSHER_HOST=localhost", $environment);
|
||||
}
|
||||
|
||||
if (in_array('mailpit', $services)) {
|
||||
$environment = preg_replace("/^MAIL_MAILER=(.*)/m", "MAIL_MAILER=smtp", $environment);
|
||||
$environment = preg_replace("/^MAIL_HOST=(.*)/m", "MAIL_HOST=mailpit", $environment);
|
||||
$environment = preg_replace("/^MAIL_PORT=(.*)/m", "MAIL_PORT=1025", $environment);
|
||||
}
|
||||
|
||||
file_put_contents($this->laravel->basePath('.env'), $environment);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure PHPUnit to use the dedicated testing database.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function configurePhpUnit()
|
||||
{
|
||||
if (! file_exists($path = $this->laravel->basePath('phpunit.xml'))) {
|
||||
$path = $this->laravel->basePath('phpunit.xml.dist');
|
||||
|
||||
if (! file_exists($path)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
$phpunit = file_get_contents($path);
|
||||
|
||||
$phpunit = preg_replace('/^.*DB_CONNECTION.*\n/m', '', $phpunit);
|
||||
$phpunit = str_replace('<!-- <env name="DB_DATABASE" value=":memory:"/> -->', '<env name="DB_DATABASE" value="testing"/>', $phpunit);
|
||||
|
||||
file_put_contents($this->laravel->basePath('phpunit.xml'), $phpunit);
|
||||
}
|
||||
|
||||
/**
|
||||
* Install the devcontainer.json configuration file.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function installDevContainer()
|
||||
{
|
||||
if (! is_dir($this->laravel->basePath('.devcontainer'))) {
|
||||
mkdir($this->laravel->basePath('.devcontainer'), 0755, true);
|
||||
}
|
||||
|
||||
file_put_contents(
|
||||
$this->laravel->basePath('.devcontainer/devcontainer.json'),
|
||||
file_get_contents(__DIR__.'/../../../stubs/devcontainer.stub')
|
||||
);
|
||||
|
||||
$environment = file_get_contents($this->laravel->basePath('.env'));
|
||||
|
||||
$environment .= "\nWWWGROUP=1000";
|
||||
$environment .= "\nWWWUSER=1000\n";
|
||||
|
||||
file_put_contents($this->laravel->basePath('.env'), $environment);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the installation by pulling and building any necessary images.
|
||||
*
|
||||
* @param array $services
|
||||
* @return void
|
||||
*/
|
||||
protected function prepareInstallation($services)
|
||||
{
|
||||
// Ensure docker is installed...
|
||||
if ($this->runCommands(['docker info > /dev/null 2>&1']) !== 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (count($services) > 0) {
|
||||
$this->runCommands([
|
||||
'./vendor/bin/sail pull '.implode(' ', $services),
|
||||
]);
|
||||
}
|
||||
|
||||
$this->runCommands([
|
||||
'./vendor/bin/sail build',
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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(' <bg=yellow;fg=black> WARN </> '.$e->getMessage().PHP_EOL);
|
||||
}
|
||||
}
|
||||
|
||||
return $process->run(function ($type, $line) {
|
||||
$this->output->write(' '.$line);
|
||||
});
|
||||
}
|
||||
}
|
77
vendor/laravel/sail/src/Console/InstallCommand.php
vendored
Normal file
77
vendor/laravel/sail/src/Console/InstallCommand.php
vendored
Normal file
@ -0,0 +1,77 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Sail\Console;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use RuntimeException;
|
||||
use Symfony\Component\Console\Attribute\AsCommand;
|
||||
use Symfony\Component\Process\Process;
|
||||
|
||||
#[AsCommand(name: 'sail:install')]
|
||||
class InstallCommand extends Command
|
||||
{
|
||||
use Concerns\InteractsWithDockerComposeServices;
|
||||
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'sail:install
|
||||
{--with= : The services that should be included in the installation}
|
||||
{--devcontainer : Create a .devcontainer configuration directory}';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Install Laravel Sail\'s default Docker Compose file';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return int|null
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
if ($this->option('with')) {
|
||||
$services = $this->option('with') == 'none' ? [] : explode(',', $this->option('with'));
|
||||
} elseif ($this->option('no-interaction')) {
|
||||
$services = $this->defaultServices;
|
||||
} else {
|
||||
$services = $this->gatherServicesInteractively();
|
||||
}
|
||||
|
||||
if ($invalidServices = array_diff($services, $this->services)) {
|
||||
$this->components->error('Invalid services ['.implode(',', $invalidServices).'].');
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
$this->buildDockerCompose($services);
|
||||
$this->replaceEnvVariables($services);
|
||||
$this->configurePhpUnit();
|
||||
|
||||
if ($this->option('devcontainer')) {
|
||||
$this->installDevContainer();
|
||||
}
|
||||
|
||||
$this->prepareInstallation($services);
|
||||
|
||||
$this->output->writeln('');
|
||||
$this->components->info('Sail scaffolding installed successfully. You may run your Docker containers using Sail\'s "up" command.');
|
||||
|
||||
$this->output->writeln('<fg=gray>➜</> <options=bold>./vendor/bin/sail up</>');
|
||||
|
||||
if (in_array('mysql', $services) ||
|
||||
in_array('mariadb', $services) ||
|
||||
in_array('pgsql', $services)) {
|
||||
$this->components->warn('A database service was installed. Run "artisan migrate" to prepare your database:');
|
||||
|
||||
$this->output->writeln('<fg=gray>➜</> <options=bold>./vendor/bin/sail artisan migrate</>');
|
||||
}
|
||||
|
||||
$this->output->writeln('');
|
||||
}
|
||||
}
|
58
vendor/laravel/sail/src/Console/PublishCommand.php
vendored
Normal file
58
vendor/laravel/sail/src/Console/PublishCommand.php
vendored
Normal file
@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Sail\Console;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use Symfony\Component\Console\Attribute\AsCommand;
|
||||
|
||||
#[AsCommand(name: 'sail:publish')]
|
||||
class PublishCommand extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'sail:publish';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Publish the Laravel Sail Docker files';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$this->call('vendor:publish', ['--tag' => 'sail-docker']);
|
||||
$this->call('vendor:publish', ['--tag' => 'sail-database']);
|
||||
|
||||
file_put_contents(
|
||||
$this->laravel->basePath('docker-compose.yml'),
|
||||
str_replace(
|
||||
[
|
||||
'./vendor/laravel/sail/runtimes/8.3',
|
||||
'./vendor/laravel/sail/runtimes/8.2',
|
||||
'./vendor/laravel/sail/runtimes/8.1',
|
||||
'./vendor/laravel/sail/runtimes/8.0',
|
||||
'./vendor/laravel/sail/database/mysql',
|
||||
'./vendor/laravel/sail/database/pgsql'
|
||||
],
|
||||
[
|
||||
'./docker/8.3',
|
||||
'./docker/8.2',
|
||||
'./docker/8.1',
|
||||
'./docker/8.0',
|
||||
'./docker/mysql',
|
||||
'./docker/pgsql'
|
||||
],
|
||||
file_get_contents($this->laravel->basePath('docker-compose.yml'))
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
74
vendor/laravel/sail/src/SailServiceProvider.php
vendored
Normal file
74
vendor/laravel/sail/src/SailServiceProvider.php
vendored
Normal file
@ -0,0 +1,74 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Sail;
|
||||
|
||||
use Illuminate\Contracts\Support\DeferrableProvider;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use Laravel\Sail\Console\AddCommand;
|
||||
use Laravel\Sail\Console\InstallCommand;
|
||||
use Laravel\Sail\Console\PublishCommand;
|
||||
|
||||
class SailServiceProvider extends ServiceProvider implements DeferrableProvider
|
||||
{
|
||||
/**
|
||||
* Bootstrap any application services.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function boot()
|
||||
{
|
||||
$this->registerCommands();
|
||||
$this->configurePublishing();
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the console commands for the package.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function registerCommands()
|
||||
{
|
||||
if ($this->app->runningInConsole()) {
|
||||
$this->commands([
|
||||
InstallCommand::class,
|
||||
AddCommand::class,
|
||||
PublishCommand::class,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure publishing for the package.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function configurePublishing()
|
||||
{
|
||||
if ($this->app->runningInConsole()) {
|
||||
$this->publishes([
|
||||
__DIR__ . '/../runtimes' => $this->app->basePath('docker'),
|
||||
], ['sail', 'sail-docker']);
|
||||
|
||||
$this->publishes([
|
||||
__DIR__ . '/../bin/sail' => $this->app->basePath('sail'),
|
||||
], ['sail', 'sail-bin']);
|
||||
|
||||
$this->publishes([
|
||||
__DIR__ . '/../database' => $this->app->basePath('docker'),
|
||||
], ['sail', 'sail-database']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the services provided by the provider.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function provides()
|
||||
{
|
||||
return [
|
||||
InstallCommand::class,
|
||||
PublishCommand::class,
|
||||
];
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user