mirror of
https://github.com/vitodeploy/vito.git
synced 2025-07-05 16:02:34 +00:00
Plugins base (#613)
* wip * wip * cleanup * notification channels * phpstan * services * remove server types * refactoring * refactoring
This commit is contained in:
@ -4,8 +4,9 @@
|
||||
|
||||
use App\Exceptions\FailedToDeployGitKey;
|
||||
use App\Exceptions\SSHError;
|
||||
use App\Models\Service;
|
||||
use App\Models\Site;
|
||||
use App\SSH\Services\PHP\PHP;
|
||||
use App\Services\PHP\PHP;
|
||||
use Illuminate\Support\Str;
|
||||
use RuntimeException;
|
||||
|
||||
@ -76,7 +77,7 @@ protected function isolate(): void
|
||||
// Generate the FPM pool
|
||||
if ($this->site->php_version) {
|
||||
$service = $this->site->php();
|
||||
if (! $service instanceof \App\Models\Service) {
|
||||
if (! $service instanceof Service) {
|
||||
throw new RuntimeException('PHP service not found');
|
||||
}
|
||||
/** @var PHP $php */
|
||||
|
@ -6,57 +6,29 @@
|
||||
|
||||
class Laravel extends PHPSite
|
||||
{
|
||||
public static function id(): string
|
||||
{
|
||||
return 'laravel';
|
||||
}
|
||||
|
||||
public static function make(): self
|
||||
{
|
||||
return new self(new Site(['type' => \App\Enums\SiteType::LARAVEL]));
|
||||
return new self(new Site(['type' => self::id()]));
|
||||
}
|
||||
|
||||
public function baseCommands(): array
|
||||
{
|
||||
return array_merge(parent::baseCommands(), [
|
||||
// Initial Setup Commands
|
||||
[
|
||||
'name' => 'Generate Application Key',
|
||||
'command' => 'php artisan key:generate',
|
||||
],
|
||||
[
|
||||
'name' => 'Create Storage Symbolic Link',
|
||||
'command' => 'php artisan storage:link',
|
||||
],
|
||||
// Database Commands
|
||||
[
|
||||
'name' => 'Run Database Migrations',
|
||||
'command' => 'php artisan migrate --force',
|
||||
],
|
||||
// Cache & Optimization Commands
|
||||
[
|
||||
'name' => 'Optimize Application',
|
||||
'command' => 'php artisan optimize',
|
||||
],
|
||||
[
|
||||
'name' => 'Clear All Application Optimizations',
|
||||
'command' => 'php artisan optimize:clear',
|
||||
],
|
||||
[
|
||||
'name' => 'Clear Application Cache Only',
|
||||
'name' => 'cache:clear',
|
||||
'command' => 'php artisan cache:clear',
|
||||
],
|
||||
// Worker Commands
|
||||
[
|
||||
'name' => 'Restart Workers',
|
||||
'command' => 'php artisan queue:restart',
|
||||
],
|
||||
[
|
||||
'name' => 'Clear All Failed Queue Jobs',
|
||||
'command' => 'php artisan queue:flush',
|
||||
],
|
||||
// Application State Commands
|
||||
[
|
||||
'name' => 'Put Application in Maintenance Mode',
|
||||
'name' => 'down',
|
||||
'command' => 'php artisan down --retry=5 --refresh=6 --quiet',
|
||||
],
|
||||
[
|
||||
'name' => 'Bring Application Online',
|
||||
'name' => 'up',
|
||||
'command' => 'php artisan up',
|
||||
],
|
||||
]);
|
||||
|
@ -2,19 +2,21 @@
|
||||
|
||||
namespace App\SiteTypes;
|
||||
|
||||
use App\DTOs\DynamicFieldDTO;
|
||||
use App\DTOs\DynamicFieldsCollectionDTO;
|
||||
use App\Enums\LoadBalancerMethod;
|
||||
use App\Enums\SiteFeature;
|
||||
use App\Exceptions\SSHError;
|
||||
use App\Models\Site;
|
||||
use Illuminate\Validation\Rule;
|
||||
|
||||
class LoadBalancer extends AbstractSiteType
|
||||
{
|
||||
public static function id(): string
|
||||
{
|
||||
return 'load-balancer';
|
||||
}
|
||||
|
||||
public static function make(): self
|
||||
{
|
||||
return new self(new Site(['type' => \App\Enums\SiteType::LOAD_BALANCER]));
|
||||
return new self(new Site(['type' => self::id()]));
|
||||
}
|
||||
|
||||
public function language(): string
|
||||
@ -22,27 +24,6 @@ public function language(): string
|
||||
return 'yaml';
|
||||
}
|
||||
|
||||
public function supportedFeatures(): array
|
||||
{
|
||||
return [
|
||||
SiteFeature::SSL,
|
||||
];
|
||||
}
|
||||
|
||||
public function fields(): DynamicFieldsCollectionDTO
|
||||
{
|
||||
return new DynamicFieldsCollectionDTO([
|
||||
DynamicFieldDTO::make('method')
|
||||
->select()
|
||||
->label('Load Balancing Method')
|
||||
->options([
|
||||
LoadBalancerMethod::IP_HASH,
|
||||
LoadBalancerMethod::ROUND_ROBIN,
|
||||
LoadBalancerMethod::LEAST_CONNECTIONS,
|
||||
]),
|
||||
]);
|
||||
}
|
||||
|
||||
public function createRules(array $input): array
|
||||
{
|
||||
return [
|
||||
@ -73,4 +54,36 @@ public function install(): void
|
||||
|
||||
$this->site->webserver()->createVHost($this->site);
|
||||
}
|
||||
|
||||
public function vhost(string $webserver): string
|
||||
{
|
||||
if ($webserver === 'nginx') {
|
||||
return view('ssh.services.webserver.nginx.vhost', [
|
||||
'header' => [
|
||||
view('ssh.services.webserver.nginx.vhost-blocks.force-ssl', ['site' => $this->site]),
|
||||
view('ssh.services.webserver.nginx.vhost-blocks.load-balancer-upstream', ['site' => $this->site]),
|
||||
],
|
||||
'main' => [
|
||||
view('ssh.services.webserver.nginx.vhost-blocks.port', ['site' => $this->site]),
|
||||
view('ssh.services.webserver.nginx.vhost-blocks.core', ['site' => $this->site]),
|
||||
view('ssh.services.webserver.nginx.vhost-blocks.load-balancer', ['site' => $this->site]),
|
||||
view('ssh.services.webserver.nginx.vhost-blocks.redirects', ['site' => $this->site]),
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
if ($webserver === 'caddy') {
|
||||
return view('ssh.services.webserver.caddy.vhost', [
|
||||
'main' => implode("\n", [
|
||||
view('ssh.services.webserver.caddy.vhost-blocks.force-ssl', ['site' => $this->site]),
|
||||
view('ssh.services.webserver.caddy.vhost-blocks.port', ['site' => $this->site]),
|
||||
view('ssh.services.webserver.caddy.vhost-blocks.core', ['site' => $this->site]),
|
||||
view('ssh.services.webserver.caddy.vhost-blocks.load-balancer', ['site' => $this->site]),
|
||||
view('ssh.services.webserver.caddy.vhost-blocks.redirects', ['site' => $this->site]),
|
||||
]),
|
||||
]);
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
@ -2,43 +2,20 @@
|
||||
|
||||
namespace App\SiteTypes;
|
||||
|
||||
use App\DTOs\DynamicFieldDTO;
|
||||
use App\DTOs\DynamicFieldsCollectionDTO;
|
||||
use App\Enums\SiteFeature;
|
||||
use App\Exceptions\SSHError;
|
||||
use App\Models\Site;
|
||||
use Illuminate\Validation\Rule;
|
||||
|
||||
class PHPBlank extends PHPSite
|
||||
{
|
||||
public static function id(): string
|
||||
{
|
||||
return 'php-blank';
|
||||
}
|
||||
|
||||
public static function make(): self
|
||||
{
|
||||
return new self(new Site(['type' => \App\Enums\SiteType::PHP]));
|
||||
}
|
||||
|
||||
public function supportedFeatures(): array
|
||||
{
|
||||
return [
|
||||
SiteFeature::DEPLOYMENT,
|
||||
SiteFeature::COMMANDS,
|
||||
SiteFeature::ENV,
|
||||
SiteFeature::SSL,
|
||||
SiteFeature::WORKERS,
|
||||
];
|
||||
}
|
||||
|
||||
public function fields(): DynamicFieldsCollectionDTO
|
||||
{
|
||||
return new DynamicFieldsCollectionDTO([
|
||||
DynamicFieldDTO::make('php_version')
|
||||
->component()
|
||||
->label('PHP Version'),
|
||||
DynamicFieldDTO::make('web_directory')
|
||||
->text()
|
||||
->label('Web Directory')
|
||||
->placeholder('For / leave empty')
|
||||
->description('The relative path of your website from /home/vito/your-domain/'),
|
||||
]);
|
||||
return new self(new Site(['type' => self::id()]));
|
||||
}
|
||||
|
||||
public function createRules(array $input): array
|
||||
|
@ -2,34 +2,20 @@
|
||||
|
||||
namespace App\SiteTypes;
|
||||
|
||||
use App\DTOs\DynamicFieldDTO;
|
||||
use App\DTOs\DynamicFieldsCollectionDTO;
|
||||
use App\Enums\SiteFeature;
|
||||
use App\Exceptions\SSHError;
|
||||
use App\Models\Site;
|
||||
use Illuminate\Validation\Rule;
|
||||
|
||||
class PHPMyAdmin extends PHPSite
|
||||
{
|
||||
public static function id(): string
|
||||
{
|
||||
return 'phpmyadmin';
|
||||
}
|
||||
|
||||
public static function make(): self
|
||||
{
|
||||
return new self(new Site(['type' => \App\Enums\SiteType::PHPMYADMIN]));
|
||||
}
|
||||
|
||||
public function supportedFeatures(): array
|
||||
{
|
||||
return [
|
||||
SiteFeature::SSL,
|
||||
];
|
||||
}
|
||||
|
||||
public function fields(): DynamicFieldsCollectionDTO
|
||||
{
|
||||
return new DynamicFieldsCollectionDTO([
|
||||
DynamicFieldDTO::make('php_version')
|
||||
->component()
|
||||
->label('PHP Version'),
|
||||
]);
|
||||
return new self(new Site(['type' => self::id()]));
|
||||
}
|
||||
|
||||
public function createRules(array $input): array
|
||||
@ -65,7 +51,14 @@ public function install(): void
|
||||
$this->isolate();
|
||||
$this->site->webserver()->createVHost($this->site);
|
||||
$this->progress(30);
|
||||
app(\App\SSH\PHPMyAdmin\PHPMyAdmin::class)->install($this->site);
|
||||
$this->site->server->ssh($this->site->user)->exec(
|
||||
view('ssh.phpmyadmin.install', [
|
||||
'version' => $this->site->type_data['version'],
|
||||
'path' => $this->site->path,
|
||||
]),
|
||||
'install-phpmyadmin',
|
||||
$this->site->id
|
||||
);
|
||||
$this->progress(65);
|
||||
$this->site->php()?->restart();
|
||||
}
|
||||
|
@ -2,21 +2,18 @@
|
||||
|
||||
namespace App\SiteTypes;
|
||||
|
||||
use App\DTOs\DynamicFieldDTO;
|
||||
use App\DTOs\DynamicFieldsCollectionDTO;
|
||||
use App\Enums\SiteFeature;
|
||||
use App\Exceptions\FailedToDeployGitKey;
|
||||
use App\Exceptions\SSHError;
|
||||
use App\Models\Site;
|
||||
use App\SSH\Composer\Composer;
|
||||
use App\SSH\Git\Git;
|
||||
use App\SSH\OS\Composer;
|
||||
use App\SSH\OS\Git;
|
||||
use Illuminate\Validation\Rule;
|
||||
|
||||
class PHPSite extends AbstractSiteType
|
||||
{
|
||||
public static function make(): self
|
||||
public static function id(): string
|
||||
{
|
||||
return new self(new Site(['type' => \App\Enums\SiteType::PHP]));
|
||||
return 'php';
|
||||
}
|
||||
|
||||
public function language(): string
|
||||
@ -24,44 +21,9 @@ public function language(): string
|
||||
return 'php';
|
||||
}
|
||||
|
||||
public function supportedFeatures(): array
|
||||
public static function make(): self
|
||||
{
|
||||
return [
|
||||
SiteFeature::DEPLOYMENT,
|
||||
SiteFeature::COMMANDS,
|
||||
SiteFeature::ENV,
|
||||
SiteFeature::SSL,
|
||||
SiteFeature::WORKERS,
|
||||
];
|
||||
}
|
||||
|
||||
public function fields(): DynamicFieldsCollectionDTO
|
||||
{
|
||||
return new DynamicFieldsCollectionDTO([
|
||||
DynamicFieldDTO::make('php_version')
|
||||
->component()
|
||||
->label('PHP Version'),
|
||||
DynamicFieldDTO::make('source_control')
|
||||
->component()
|
||||
->label('Source Control'),
|
||||
DynamicFieldDTO::make('web_directory')
|
||||
->text()
|
||||
->label('Web Directory')
|
||||
->placeholder('For / leave empty')
|
||||
->description('The relative path of your website from /home/vito/your-domain/'),
|
||||
DynamicFieldDTO::make('repository')
|
||||
->text()
|
||||
->label('Repository')
|
||||
->placeholder('organization/repository'),
|
||||
DynamicFieldDTO::make('branch')
|
||||
->text()
|
||||
->label('Branch')
|
||||
->default('main'),
|
||||
DynamicFieldDTO::make('composer')
|
||||
->checkbox()
|
||||
->label('Run `composer install --no-dev`')
|
||||
->default(false),
|
||||
]);
|
||||
return new self(new Site(['type' => self::id()]));
|
||||
}
|
||||
|
||||
public function createRules(array $input): array
|
||||
@ -132,9 +94,40 @@ public function baseCommands(): array
|
||||
{
|
||||
return [
|
||||
[
|
||||
'name' => 'Install Composer Dependencies',
|
||||
'name' => 'composer:install',
|
||||
'command' => 'composer install --no-dev --no-interaction --no-progress',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
public function vhost(string $webserver): string
|
||||
{
|
||||
if ($webserver === 'nginx') {
|
||||
return view('ssh.services.webserver.nginx.vhost', [
|
||||
'header' => [
|
||||
view('ssh.services.webserver.nginx.vhost-blocks.force-ssl', ['site' => $this->site]),
|
||||
],
|
||||
'main' => [
|
||||
view('ssh.services.webserver.nginx.vhost-blocks.port', ['site' => $this->site]),
|
||||
view('ssh.services.webserver.nginx.vhost-blocks.core', ['site' => $this->site]),
|
||||
view('ssh.services.webserver.nginx.vhost-blocks.php', ['site' => $this->site]),
|
||||
view('ssh.services.webserver.nginx.vhost-blocks.redirects', ['site' => $this->site]),
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
if ($webserver === 'caddy') {
|
||||
return view('ssh.services.webserver.caddy.vhost', [
|
||||
'main' => [
|
||||
view('ssh.services.webserver.caddy.vhost-blocks.force-ssl', ['site' => $this->site]),
|
||||
view('ssh.services.webserver.caddy.vhost-blocks.port', ['site' => $this->site]),
|
||||
view('ssh.services.webserver.caddy.vhost-blocks.core', ['site' => $this->site]),
|
||||
view('ssh.services.webserver.caddy.vhost-blocks.php', ['site' => $this->site]),
|
||||
view('ssh.services.webserver.caddy.vhost-blocks.redirects', ['site' => $this->site]),
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
@ -2,19 +2,12 @@
|
||||
|
||||
namespace App\SiteTypes;
|
||||
|
||||
use App\DTOs\DynamicFieldsCollectionDTO;
|
||||
|
||||
interface SiteType
|
||||
{
|
||||
public static function id(): string;
|
||||
|
||||
public function language(): string;
|
||||
|
||||
/**
|
||||
* @return array<string>
|
||||
*/
|
||||
public function supportedFeatures(): array;
|
||||
|
||||
public function fields(): DynamicFieldsCollectionDTO;
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $input
|
||||
* @return array<string, mixed>
|
||||
@ -22,12 +15,16 @@ public function fields(): DynamicFieldsCollectionDTO;
|
||||
public function createRules(array $input): array;
|
||||
|
||||
/**
|
||||
* The fields here will be replaced in the Site model
|
||||
*
|
||||
* @param array<string, mixed> $input
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function createFields(array $input): array;
|
||||
|
||||
/**
|
||||
* The fields here will be replaced in the type_data column as json
|
||||
*
|
||||
* @param array<string, mixed> $input
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
@ -39,4 +36,6 @@ public function install(): void;
|
||||
* @return array<array<string, string>>
|
||||
*/
|
||||
public function baseCommands(): array;
|
||||
|
||||
public function vhost(string $webserver): string;
|
||||
}
|
||||
|
@ -5,9 +5,6 @@
|
||||
use App\Actions\Database\CreateDatabase;
|
||||
use App\Actions\Database\CreateDatabaseUser;
|
||||
use App\Actions\Database\LinkUser;
|
||||
use App\DTOs\DynamicFieldDTO;
|
||||
use App\DTOs\DynamicFieldsCollectionDTO;
|
||||
use App\Enums\SiteFeature;
|
||||
use App\Exceptions\SSHError;
|
||||
use App\Models\Database;
|
||||
use App\Models\DatabaseUser;
|
||||
@ -15,11 +12,16 @@
|
||||
use Closure;
|
||||
use Illuminate\Validation\Rule;
|
||||
|
||||
class Wordpress extends AbstractSiteType
|
||||
class Wordpress extends PHPSite
|
||||
{
|
||||
public static function id(): string
|
||||
{
|
||||
return 'wordpress';
|
||||
}
|
||||
|
||||
public static function make(): self
|
||||
{
|
||||
return new self(new Site(['type' => \App\Enums\SiteType::WORDPRESS]));
|
||||
return new self(new Site(['type' => self::id()]));
|
||||
}
|
||||
|
||||
public function language(): string
|
||||
@ -27,48 +29,6 @@ public function language(): string
|
||||
return 'php';
|
||||
}
|
||||
|
||||
public function supportedFeatures(): array
|
||||
{
|
||||
return [
|
||||
SiteFeature::SSL,
|
||||
SiteFeature::COMMANDS,
|
||||
];
|
||||
}
|
||||
|
||||
public function fields(): DynamicFieldsCollectionDTO
|
||||
{
|
||||
return new DynamicFieldsCollectionDTO([
|
||||
DynamicFieldDTO::make('php_version')
|
||||
->component()
|
||||
->label('PHP Version'),
|
||||
DynamicFieldDTO::make('title')
|
||||
->text()
|
||||
->label('Site Title')
|
||||
->placeholder('My WordPress Site'),
|
||||
DynamicFieldDTO::make('username')
|
||||
->text()
|
||||
->label('Admin Username')
|
||||
->placeholder('admin'),
|
||||
DynamicFieldDTO::make('password')
|
||||
->text()
|
||||
->label('Admin Password'),
|
||||
DynamicFieldDTO::make('email')
|
||||
->text()
|
||||
->label('Admin Email'),
|
||||
DynamicFieldDTO::make('database')
|
||||
->text()
|
||||
->label('Database Name')
|
||||
->placeholder('wordpress'),
|
||||
DynamicFieldDTO::make('database_user')
|
||||
->text()
|
||||
->label('Database User')
|
||||
->placeholder('wp_user'),
|
||||
DynamicFieldDTO::make('database_password')
|
||||
->text()
|
||||
->label('Database Password'),
|
||||
]);
|
||||
}
|
||||
|
||||
public function createRules(array $input): array
|
||||
{
|
||||
return [
|
||||
@ -157,6 +117,25 @@ public function install(): void
|
||||
|
||||
$this->site->php()?->restart();
|
||||
$this->progress(60);
|
||||
app(\App\SSH\Wordpress\Wordpress::class)->install($this->site);
|
||||
|
||||
$this->site->server->ssh($this->site->user)->exec(
|
||||
view('ssh.wordpress.install', [
|
||||
'path' => $this->site->path,
|
||||
'domain' => $this->site->domain,
|
||||
'isIsolated' => $this->site->isIsolated() ? 'true' : 'false',
|
||||
'isolatedUsername' => $this->site->user,
|
||||
'dbName' => $this->site->type_data['database'],
|
||||
'dbUser' => $this->site->type_data['database_user'],
|
||||
'dbPass' => $this->site->type_data['database_password'],
|
||||
'dbHost' => 'localhost',
|
||||
'dbPrefix' => 'wp_',
|
||||
'username' => $this->site->type_data['username'],
|
||||
'password' => $this->site->type_data['password'],
|
||||
'email' => $this->site->type_data['email'],
|
||||
'title' => $this->site->type_data['title'],
|
||||
]),
|
||||
'install-wordpress',
|
||||
$this->site->id
|
||||
);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user