mirror of
https://github.com/vitodeploy/vito.git
synced 2025-04-21 02:41:36 +00:00
deploy Wordpress sites via VitoDeploy (#83)
This commit is contained in:
parent
5e6d338bdc
commit
4cda14f4b8
@ -49,11 +49,6 @@ public function create(Server $server, array $input): Site
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// detect php version
|
|
||||||
if ($site->type()->language() === 'php') {
|
|
||||||
$site->php_version = $input['php_version'];
|
|
||||||
}
|
|
||||||
|
|
||||||
// validate type
|
// validate type
|
||||||
$this->validateType($site, $input);
|
$this->validateType($site, $input);
|
||||||
|
|
||||||
|
@ -6,6 +6,8 @@ interface SiteType
|
|||||||
{
|
{
|
||||||
public function language(): string;
|
public function language(): string;
|
||||||
|
|
||||||
|
public function supportedFeatures(): array;
|
||||||
|
|
||||||
public function createValidationRules(array $input): array;
|
public function createValidationRules(array $input): array;
|
||||||
|
|
||||||
public function createFields(array $input): array;
|
public function createFields(array $input): array;
|
||||||
|
16
app/Enums/SiteFeature.php
Normal file
16
app/Enums/SiteFeature.php
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Enums;
|
||||||
|
|
||||||
|
use BenSampo\Enum\Enum;
|
||||||
|
|
||||||
|
final class SiteFeature extends Enum
|
||||||
|
{
|
||||||
|
const DEPLOYMENT = 'deployment';
|
||||||
|
|
||||||
|
const ENV = 'env';
|
||||||
|
|
||||||
|
const SSL = 'ssl';
|
||||||
|
|
||||||
|
const QUEUES = 'queues';
|
||||||
|
}
|
@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
namespace App\Http\Livewire\Sites;
|
namespace App\Http\Livewire\Sites;
|
||||||
|
|
||||||
use App\Enums\SiteType;
|
|
||||||
use App\Exceptions\SourceControlIsNotConnected;
|
use App\Exceptions\SourceControlIsNotConnected;
|
||||||
use App\Models\Server;
|
use App\Models\Server;
|
||||||
use App\Models\SourceControl;
|
use App\Models\SourceControl;
|
||||||
@ -16,23 +15,12 @@ class CreateSite extends Component
|
|||||||
|
|
||||||
public Server $server;
|
public Server $server;
|
||||||
|
|
||||||
public string $type = SiteType::LARAVEL;
|
public array $inputs = [
|
||||||
|
'type' => '',
|
||||||
public string $domain;
|
'web_directory' => 'public',
|
||||||
|
'source_control' => '',
|
||||||
public string $alias;
|
'php_version' => '',
|
||||||
|
];
|
||||||
public string $php_version = '';
|
|
||||||
|
|
||||||
public string $web_directory = 'public';
|
|
||||||
|
|
||||||
public string $source_control = '';
|
|
||||||
|
|
||||||
public string $repository;
|
|
||||||
|
|
||||||
public string $branch;
|
|
||||||
|
|
||||||
public bool $composer;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @throws SourceControlIsNotConnected
|
* @throws SourceControlIsNotConnected
|
||||||
@ -41,7 +29,7 @@ public function create(): void
|
|||||||
{
|
{
|
||||||
$site = app(\App\Actions\Site\CreateSite::class)->create(
|
$site = app(\App\Actions\Site\CreateSite::class)->create(
|
||||||
$this->server,
|
$this->server,
|
||||||
$this->all()
|
$this->inputs
|
||||||
);
|
);
|
||||||
|
|
||||||
$this->redirect(route('servers.sites.show', [
|
$this->redirect(route('servers.sites.show', [
|
||||||
|
@ -52,7 +52,7 @@ public function handle(): void
|
|||||||
$this->site->id
|
$this->site->id
|
||||||
);
|
);
|
||||||
|
|
||||||
if (! Str::contains($result, 'Wordpress installed!')) {
|
if (! Str::contains($result, 'Success')) {
|
||||||
throw new FailedToInstallWordpress($result);
|
throw new FailedToInstallWordpress($result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -57,19 +57,19 @@ public function server(): BelongsTo
|
|||||||
/**
|
/**
|
||||||
* create database on server
|
* create database on server
|
||||||
*/
|
*/
|
||||||
public function createOnServer(): void
|
public function createOnServer(string $queue = 'ssh'): void
|
||||||
{
|
{
|
||||||
dispatch(new CreateOnServer($this))->onConnection('ssh');
|
dispatch(new CreateOnServer($this))->onConnection($queue);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* delete database from server
|
* delete database from server
|
||||||
*/
|
*/
|
||||||
public function deleteFromServer(): void
|
public function deleteFromServer(string $queue = 'ssh'): void
|
||||||
{
|
{
|
||||||
$this->status = DatabaseStatus::DELETING;
|
$this->status = DatabaseStatus::DELETING;
|
||||||
$this->save();
|
$this->save();
|
||||||
dispatch(new DeleteFromServer($this))->onConnection('ssh');
|
dispatch(new DeleteFromServer($this))->onConnection($queue);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function backups(): HasMany
|
public function backups(): HasMany
|
||||||
|
@ -54,17 +54,17 @@ public function scopeHasDatabase(Builder $query, string $databaseName): Builder
|
|||||||
return $query->where('databases', 'like', "%\"$databaseName\"%");
|
return $query->where('databases', 'like', "%\"$databaseName\"%");
|
||||||
}
|
}
|
||||||
|
|
||||||
public function createOnServer(): void
|
public function createOnServer(string $queue = 'ssh'): void
|
||||||
{
|
{
|
||||||
dispatch(new CreateOnServer($this))->onConnection('ssh');
|
dispatch(new CreateOnServer($this))->onConnection($queue);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function deleteFromServer(): void
|
public function deleteFromServer(string $queue = 'ssh'): void
|
||||||
{
|
{
|
||||||
$this->status = DatabaseStatus::DELETING;
|
$this->status = DatabaseStatus::DELETING;
|
||||||
$this->save();
|
$this->save();
|
||||||
|
|
||||||
dispatch(new DeleteFromServer($this))->onConnection('ssh');
|
dispatch(new DeleteFromServer($this))->onConnection($queue);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function linkNewDatabase(string $name): void
|
public function linkNewDatabase(string $name): void
|
||||||
@ -79,14 +79,14 @@ public function linkNewDatabase(string $name): void
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function linkUser(): void
|
public function linkUser(string $queue = 'ssh'): void
|
||||||
{
|
{
|
||||||
dispatch(new LinkUser($this))->onConnection('ssh');
|
dispatch(new LinkUser($this))->onConnection($queue);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function unlinkUser(): void
|
public function unlinkUser(string $queue = 'ssh'): void
|
||||||
{
|
{
|
||||||
dispatch(new UnlinkUser($this))->onConnection('ssh');
|
dispatch(new UnlinkUser($this))->onConnection($queue);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getFullUserAttribute(): string
|
public function getFullUserAttribute(): string
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
use App\Enums\DeploymentStatus;
|
use App\Enums\DeploymentStatus;
|
||||||
use App\Enums\SiteStatus;
|
use App\Enums\SiteStatus;
|
||||||
use App\Enums\SslStatus;
|
use App\Enums\SslStatus;
|
||||||
|
use App\Events\Broadcast;
|
||||||
use App\Exceptions\SourceControlIsNotConnected;
|
use App\Exceptions\SourceControlIsNotConnected;
|
||||||
use App\Jobs\Site\ChangePHPVersion;
|
use App\Jobs\Site\ChangePHPVersion;
|
||||||
use App\Jobs\Site\Deploy;
|
use App\Jobs\Site\Deploy;
|
||||||
@ -18,6 +19,7 @@
|
|||||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||||
use Illuminate\Database\Eloquent\Relations\HasOne;
|
use Illuminate\Database\Eloquent\Relations\HasOne;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
use Illuminate\Support\Str;
|
use Illuminate\Support\Str;
|
||||||
use Throwable;
|
use Throwable;
|
||||||
|
|
||||||
@ -392,4 +394,49 @@ public function getSshKeyNameAttribute(): string
|
|||||||
{
|
{
|
||||||
return str('site_'.$this->id)->toString();
|
return str('site_'.$this->id)->toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function installationFinished(): void
|
||||||
|
{
|
||||||
|
$this->update([
|
||||||
|
'status' => SiteStatus::READY,
|
||||||
|
'progress' => 100,
|
||||||
|
]);
|
||||||
|
event(
|
||||||
|
new Broadcast('install-site-finished', [
|
||||||
|
'site' => $this,
|
||||||
|
])
|
||||||
|
);
|
||||||
|
/** @todo notify */
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws Throwable
|
||||||
|
*/
|
||||||
|
public function installationFailed(Throwable $e): void
|
||||||
|
{
|
||||||
|
$this->update([
|
||||||
|
'status' => SiteStatus::INSTALLATION_FAILED,
|
||||||
|
]);
|
||||||
|
event(
|
||||||
|
new Broadcast('install-site-failed', [
|
||||||
|
'site' => $this,
|
||||||
|
])
|
||||||
|
);
|
||||||
|
/** @todo notify */
|
||||||
|
Log::error('install-site-error', [
|
||||||
|
'error' => (string) $e,
|
||||||
|
]);
|
||||||
|
|
||||||
|
throw $e;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function hasFeature(string $feature): bool
|
||||||
|
{
|
||||||
|
return in_array($feature, $this->type()->supportedFeatures());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isReady(): bool
|
||||||
|
{
|
||||||
|
return $this->status === SiteStatus::READY;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,14 +2,12 @@
|
|||||||
|
|
||||||
namespace App\SiteTypes;
|
namespace App\SiteTypes;
|
||||||
|
|
||||||
use App\Enums\SiteStatus;
|
use App\Enums\SiteFeature;
|
||||||
use App\Events\Broadcast;
|
|
||||||
use App\Jobs\Site\CloneRepository;
|
use App\Jobs\Site\CloneRepository;
|
||||||
use App\Jobs\Site\ComposerInstall;
|
use App\Jobs\Site\ComposerInstall;
|
||||||
use App\Jobs\Site\CreateVHost;
|
use App\Jobs\Site\CreateVHost;
|
||||||
use App\Jobs\Site\DeployKey;
|
use App\Jobs\Site\DeployKey;
|
||||||
use Illuminate\Support\Facades\Bus;
|
use Illuminate\Support\Facades\Bus;
|
||||||
use Illuminate\Support\Facades\Log;
|
|
||||||
use Illuminate\Validation\Rule;
|
use Illuminate\Validation\Rule;
|
||||||
use Throwable;
|
use Throwable;
|
||||||
|
|
||||||
@ -20,12 +18,22 @@ public function language(): string
|
|||||||
return 'php';
|
return 'php';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function supportedFeatures(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
SiteFeature::DEPLOYMENT,
|
||||||
|
SiteFeature::ENV,
|
||||||
|
SiteFeature::SSL,
|
||||||
|
SiteFeature::QUEUES,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
public function createValidationRules(array $input): array
|
public function createValidationRules(array $input): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'php_version' => [
|
'php_version' => [
|
||||||
'required',
|
'required',
|
||||||
'in:'.implode(',', $this->site->server->installedPHPVersions()),
|
Rule::in($this->site->server->installedPHPVersions()),
|
||||||
],
|
],
|
||||||
'source_control' => [
|
'source_control' => [
|
||||||
'required',
|
'required',
|
||||||
@ -44,9 +52,9 @@ public function createFields(array $input): array
|
|||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'web_directory' => $input['web_directory'] ?? '',
|
'web_directory' => $input['web_directory'] ?? '',
|
||||||
'source_control_id' => $input['source_control'] ?? '',
|
'source_control_id' => $input['source_control'],
|
||||||
'repository' => $input['repository'] ?? '',
|
'repository' => $input['repository'],
|
||||||
'branch' => $input['branch'] ?? '',
|
'branch' => $input['branch'],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,6 +62,7 @@ public function data(array $input): array
|
|||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'composer' => (bool) $input['composer'],
|
'composer' => (bool) $input['composer'],
|
||||||
|
'php_version' => $input['php_version'],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -76,33 +85,12 @@ function () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$chain[] = function () {
|
$chain[] = function () {
|
||||||
$this->site->update([
|
$this->site->installationFinished();
|
||||||
'status' => SiteStatus::READY,
|
|
||||||
'progress' => 100,
|
|
||||||
]);
|
|
||||||
event(
|
|
||||||
new Broadcast('install-site-finished', [
|
|
||||||
'site' => $this->site,
|
|
||||||
])
|
|
||||||
);
|
|
||||||
/** @todo notify */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Bus::chain($chain)
|
Bus::chain($chain)
|
||||||
->catch(function (Throwable $e) {
|
->catch(function (Throwable $e) {
|
||||||
$this->site->update([
|
$this->site->installationFailed($e);
|
||||||
'status' => SiteStatus::INSTALLATION_FAILED,
|
|
||||||
]);
|
|
||||||
event(
|
|
||||||
new Broadcast('install-site-failed', [
|
|
||||||
'site' => $this->site,
|
|
||||||
])
|
|
||||||
);
|
|
||||||
/** @todo notify */
|
|
||||||
Log::error('install-site-error', [
|
|
||||||
'error' => (string) $e,
|
|
||||||
]);
|
|
||||||
throw $e;
|
|
||||||
})
|
})
|
||||||
->onConnection('ssh-long')
|
->onConnection('ssh-long')
|
||||||
->dispatch();
|
->dispatch();
|
||||||
|
@ -2,13 +2,15 @@
|
|||||||
|
|
||||||
namespace App\SiteTypes;
|
namespace App\SiteTypes;
|
||||||
|
|
||||||
use App\Enums\SiteStatus;
|
use App\Enums\SiteFeature;
|
||||||
use App\Events\Broadcast;
|
|
||||||
use App\Jobs\Site\CreateVHost;
|
use App\Jobs\Site\CreateVHost;
|
||||||
use App\Jobs\Site\InstallWordpress;
|
use App\Jobs\Site\InstallWordpress;
|
||||||
|
use App\Models\Database;
|
||||||
|
use App\Models\DatabaseUser;
|
||||||
use App\SSHCommands\Wordpress\UpdateWordpressCommand;
|
use App\SSHCommands\Wordpress\UpdateWordpressCommand;
|
||||||
|
use Closure;
|
||||||
use Illuminate\Support\Facades\Bus;
|
use Illuminate\Support\Facades\Bus;
|
||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Validation\Rule;
|
||||||
use Throwable;
|
use Throwable;
|
||||||
|
|
||||||
class Wordpress extends AbstractSiteType
|
class Wordpress extends AbstractSiteType
|
||||||
@ -18,94 +20,100 @@ public function language(): string
|
|||||||
return 'php';
|
return 'php';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function supportedFeatures(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
SiteFeature::SSL,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
public function createValidationRules(array $input): array
|
public function createValidationRules(array $input): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
|
'php_version' => [
|
||||||
|
'required',
|
||||||
|
Rule::in($this->site->server->installedPHPVersions()),
|
||||||
|
],
|
||||||
'title' => 'required',
|
'title' => 'required',
|
||||||
'username' => 'required',
|
'username' => 'required',
|
||||||
'password' => 'required',
|
'password' => 'required',
|
||||||
'email' => 'required|email',
|
'email' => 'required|email',
|
||||||
'database' => 'required',
|
'database' => [
|
||||||
'database_user' => 'required',
|
'required',
|
||||||
|
Rule::unique('databases', 'name')->where(function ($query) {
|
||||||
|
return $query->where('server_id', $this->site->server_id);
|
||||||
|
}),
|
||||||
|
function (string $attribute, mixed $value, Closure $fail) {
|
||||||
|
if (! $this->site->server->database()) {
|
||||||
|
$fail(__('Database is not installed'));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'database_user' => [
|
||||||
|
'required',
|
||||||
|
Rule::unique('database_users', 'username')->where(function ($query) {
|
||||||
|
return $query->where('server_id', $this->site->server_id);
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
'database_password' => 'required',
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function createFields(array $input): array
|
public function createFields(array $input): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'web_directory' => $input['web_directory'] ?? '',
|
'web_directory' => '',
|
||||||
|
'php_version' => $input['php_version'],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function data(array $input): array
|
public function data(array $input): array
|
||||||
{
|
{
|
||||||
$data = $this->site->type_data;
|
return [
|
||||||
$data['url'] = $this->site->url;
|
'url' => $this->site->url,
|
||||||
if (isset($input['title']) && $input['title']) {
|
'title' => $input['title'],
|
||||||
$data['title'] = $input['title'];
|
'username' => $input['username'],
|
||||||
}
|
'email' => $input['email'],
|
||||||
if (isset($input['username']) && $input['username']) {
|
'password' => $input['password'],
|
||||||
$data['username'] = $input['username'];
|
'database' => $input['database'],
|
||||||
}
|
'database_user' => $input['database_user'],
|
||||||
if (isset($input['email']) && $input['email']) {
|
'database_password' => $input['database_password'],
|
||||||
$data['email'] = $input['email'];
|
];
|
||||||
}
|
|
||||||
if (isset($input['password']) && $input['password']) {
|
|
||||||
$data['password'] = $input['password'];
|
|
||||||
}
|
|
||||||
if (isset($input['database']) && $input['database']) {
|
|
||||||
$data['database'] = $input['database'];
|
|
||||||
}
|
|
||||||
if (isset($input['database_user']) && $input['database_user']) {
|
|
||||||
$data['database_user'] = $input['database_user'];
|
|
||||||
}
|
|
||||||
if (isset($input['url']) && $input['url']) {
|
|
||||||
$data['url'] = $input['url'];
|
|
||||||
}
|
|
||||||
|
|
||||||
return $data;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function install(): void
|
public function install(): void
|
||||||
{
|
{
|
||||||
$chain = [
|
$chain = [
|
||||||
new CreateVHost($this->site),
|
new CreateVHost($this->site),
|
||||||
$this->progress(30),
|
$this->progress(15),
|
||||||
|
function () {
|
||||||
|
/** @var Database $database */
|
||||||
|
$database = $this->site->server->databases()->create([
|
||||||
|
'name' => $this->site->type_data['database'],
|
||||||
|
]);
|
||||||
|
$database->createOnServer('sync');
|
||||||
|
/** @var DatabaseUser $databaseUser */
|
||||||
|
$databaseUser = $this->site->server->databaseUsers()->create([
|
||||||
|
'username' => $this->site->type_data['database_user'],
|
||||||
|
'password' => $this->site->type_data['database_password'],
|
||||||
|
'databases' => [$this->site->type_data['database']],
|
||||||
|
]);
|
||||||
|
$databaseUser->createOnServer('sync');
|
||||||
|
$databaseUser->unlinkUser('sync');
|
||||||
|
$databaseUser->linkUser('sync');
|
||||||
|
},
|
||||||
|
$this->progress(50),
|
||||||
new InstallWordpress($this->site),
|
new InstallWordpress($this->site),
|
||||||
$this->progress(65),
|
$this->progress(75),
|
||||||
function () {
|
function () {
|
||||||
$this->site->php()?->restart();
|
$this->site->php()?->restart();
|
||||||
|
$this->site->installationFinished();
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
$chain[] = function () {
|
|
||||||
$this->site->update([
|
|
||||||
'status' => SiteStatus::READY,
|
|
||||||
'progress' => 100,
|
|
||||||
]);
|
|
||||||
event(
|
|
||||||
new Broadcast('install-site-finished', [
|
|
||||||
'site' => $this->site,
|
|
||||||
])
|
|
||||||
);
|
|
||||||
/** @todo notify */
|
|
||||||
};
|
|
||||||
|
|
||||||
Bus::chain($chain)
|
Bus::chain($chain)
|
||||||
->catch(function (Throwable $e) {
|
->catch(function (Throwable $e) {
|
||||||
$this->site->update([
|
$this->site->installationFailed($e);
|
||||||
'status' => SiteStatus::INSTALLATION_FAILED,
|
|
||||||
]);
|
|
||||||
event(
|
|
||||||
new Broadcast('install-site-failed', [
|
|
||||||
'site' => $this->site,
|
|
||||||
])
|
|
||||||
);
|
|
||||||
/** @todo notify */
|
|
||||||
Log::error('install-site-error', [
|
|
||||||
'error' => (string) $e,
|
|
||||||
]);
|
|
||||||
throw $e;
|
|
||||||
})
|
})
|
||||||
->onConnection('ssh-long')
|
->onConnection('ssh-long')
|
||||||
->dispatch();
|
->dispatch();
|
||||||
@ -139,32 +147,13 @@ function () {
|
|||||||
'update-wordpress',
|
'update-wordpress',
|
||||||
$this->site->id
|
$this->site->id
|
||||||
);
|
);
|
||||||
$this->site->update([
|
$this->site->installationFinished();
|
||||||
'status' => SiteStatus::READY,
|
|
||||||
]);
|
|
||||||
event(
|
|
||||||
new Broadcast('install-site-finished', [
|
|
||||||
'site' => $this->site,
|
|
||||||
])
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
Bus::chain($chain)
|
Bus::chain($chain)
|
||||||
->catch(function (Throwable $e) {
|
->catch(function (Throwable $e) {
|
||||||
$this->site->update([
|
$this->site->installationFailed($e);
|
||||||
'status' => SiteStatus::INSTALLATION_FAILED,
|
|
||||||
]);
|
|
||||||
event(
|
|
||||||
new Broadcast('install-site-failed', [
|
|
||||||
'site' => $this->site,
|
|
||||||
])
|
|
||||||
);
|
|
||||||
/** @todo notify */
|
|
||||||
Log::error('install-site-error', [
|
|
||||||
'error' => (string) $e,
|
|
||||||
]);
|
|
||||||
throw $e;
|
|
||||||
})
|
})
|
||||||
->onConnection('ssh')
|
->onConnection('ssh')
|
||||||
->dispatch();
|
->dispatch();
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
use App\ServiceHandlers\Webserver\Nginx;
|
use App\ServiceHandlers\Webserver\Nginx;
|
||||||
use App\SiteTypes\Laravel;
|
use App\SiteTypes\Laravel;
|
||||||
use App\SiteTypes\PHPSite;
|
use App\SiteTypes\PHPSite;
|
||||||
|
use App\SiteTypes\Wordpress;
|
||||||
use App\SourceControlProviders\Bitbucket;
|
use App\SourceControlProviders\Bitbucket;
|
||||||
use App\SourceControlProviders\Github;
|
use App\SourceControlProviders\Github;
|
||||||
use App\SourceControlProviders\Gitlab;
|
use App\SourceControlProviders\Gitlab;
|
||||||
@ -262,12 +263,12 @@
|
|||||||
'site_types' => [
|
'site_types' => [
|
||||||
\App\Enums\SiteType::PHP,
|
\App\Enums\SiteType::PHP,
|
||||||
\App\Enums\SiteType::LARAVEL,
|
\App\Enums\SiteType::LARAVEL,
|
||||||
// \App\Enums\SiteType::WORDPRESS,
|
\App\Enums\SiteType::WORDPRESS,
|
||||||
],
|
],
|
||||||
'site_types_class' => [
|
'site_types_class' => [
|
||||||
\App\Enums\SiteType::PHP => PHPSite::class,
|
\App\Enums\SiteType::PHP => PHPSite::class,
|
||||||
\App\Enums\SiteType::LARAVEL => Laravel::class,
|
\App\Enums\SiteType::LARAVEL => Laravel::class,
|
||||||
// \App\Enums\SiteType::WORDPRESS => Wordpress::class,
|
\App\Enums\SiteType::WORDPRESS => Wordpress::class,
|
||||||
],
|
],
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
1
public/build/assets/app-328222da.css
Normal file
1
public/build/assets/app-328222da.css
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
24
public/build/assets/app-9aa488bb.js
Normal file
24
public/build/assets/app-9aa488bb.js
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1,11 +1,11 @@
|
|||||||
{
|
{
|
||||||
"resources/css/app.css": {
|
"resources/css/app.css": {
|
||||||
"file": "assets/app-99c9ce18.css",
|
"file": "assets/app-328222da.css",
|
||||||
"isEntry": true,
|
"isEntry": true,
|
||||||
"src": "resources/css/app.css"
|
"src": "resources/css/app.css"
|
||||||
},
|
},
|
||||||
"resources/js/app.js": {
|
"resources/js/app.js": {
|
||||||
"file": "assets/app-fa1f93fa.js",
|
"file": "assets/app-9aa488bb.js",
|
||||||
"isEntry": true,
|
"isEntry": true,
|
||||||
"src": "resources/js/app.js"
|
"src": "resources/js/app.js"
|
||||||
}
|
}
|
||||||
|
@ -161,45 +161,7 @@ class="min-h-screen w-64 flex-none border-r border-gray-200 bg-white dark:border
|
|||||||
<div class="flex items-center justify-center">
|
<div class="flex items-center justify-center">
|
||||||
{{-- Search --}}
|
{{-- Search --}}
|
||||||
</div>
|
</div>
|
||||||
{{-- Dark Mode Toggle Button section --}}
|
@include('layouts.partials.color-scheme')
|
||||||
<div class="flex items-center" x-data="{
|
|
||||||
isDarkMode: localStorage.theme,
|
|
||||||
toggleTheme() {
|
|
||||||
localStorage.theme = this.isDarkMode == 'dark' ? 'light' : 'dark';
|
|
||||||
|
|
||||||
if (localStorage.theme === 'dark') {
|
|
||||||
document.documentElement.classList.add('dark')
|
|
||||||
} else {
|
|
||||||
document.documentElement.classList.remove('dark')
|
|
||||||
}
|
|
||||||
|
|
||||||
this.isDarkMode = localStorage.theme
|
|
||||||
}
|
|
||||||
}" x-on:click="toggleTheme()">
|
|
||||||
<div class="flex items-center">
|
|
||||||
<div class="flex items-center justify-end">
|
|
||||||
<button id="theme-toggle" type="button" class="text-sm p-2"
|
|
||||||
:class="isDarkMode == 'dark' ? 'text-gray-300 border-gray-300' :
|
|
||||||
'text-gray-800 border-gray-800'">
|
|
||||||
<svg x-show="isDarkMode!='dark'" id="theme-toggle-dark-icon" class="w-5 h-5"
|
|
||||||
fill="currentColor" viewBox="0 0 20 20"
|
|
||||||
xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<path
|
|
||||||
d="M17.293 13.293A8 8 0 016.707 2.707a8.001 8.001 0 1010.586 10.586z">
|
|
||||||
</path>
|
|
||||||
</svg>
|
|
||||||
<svg x-show="isDarkMode=='dark'" id="theme-toggle-light-icon" class="w-5 h-5"
|
|
||||||
fill="currentColor" viewBox="0 0 20 20"
|
|
||||||
xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<path
|
|
||||||
d="M10 2a1 1 0 011 1v1a1 1 0 11-2 0V3a1 1 0 011-1zm4 8a4 4 0 11-8 0 4 4 0 018 0zm-.464 4.95l.707.707a1 1 0 001.414-1.414l-.707-.707a1 1 0 00-1.414 1.414zm2.12-10.607a1 1 0 010 1.414l-.706.707a1 1 0 11-1.414-1.414l.707-.707a1 1 0 011.414 0zM17 11a1 1 0 100-2h-1a1 1 0 100 2h1zm-7 4a1 1 0 011 1v1a1 1 0 11-2 0v-1a1 1 0 011-1zM5.05 6.464A1 1 0 106.465 5.05l-.708-.707a1 1 0 00-1.414 1.414l.707.707zm1.414 8.486l-.707.707a1 1 0 01-1.414-1.414l.707-.707a1 1 0 011.414 1.414zM4 11a1 1 0 100-2H3a1 1 0 000 2h1z"
|
|
||||||
fillRule="evenodd" clipRule="evenodd"></path>
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{{-- End of Dark Mode Toggle Button section --}}
|
|
||||||
<div class="ml-6 flex items-center">
|
<div class="ml-6 flex items-center">
|
||||||
<div class="relative ml-5">
|
<div class="relative ml-5">
|
||||||
<x-dropdown align="right" width="48">
|
<x-dropdown align="right" width="48">
|
||||||
|
37
resources/views/layouts/partials/color-scheme.blade.php
Normal file
37
resources/views/layouts/partials/color-scheme.blade.php
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
<div class="flex items-center" x-data="{
|
||||||
|
isDarkMode: localStorage.theme,
|
||||||
|
toggleTheme() {
|
||||||
|
localStorage.theme = this.isDarkMode === 'dark' ? 'light' : 'dark';
|
||||||
|
|
||||||
|
if (localStorage.theme === 'dark') {
|
||||||
|
document.documentElement.classList.add('dark')
|
||||||
|
} else {
|
||||||
|
document.documentElement.classList.remove('dark')
|
||||||
|
}
|
||||||
|
|
||||||
|
this.isDarkMode = localStorage.theme
|
||||||
|
}
|
||||||
|
}" x-on:click="toggleTheme()">
|
||||||
|
<div class="flex items-center">
|
||||||
|
<div class="flex items-center justify-end">
|
||||||
|
<button id="theme-toggle" type="button" class="text-sm p-2"
|
||||||
|
:class="isDarkMode === 'dark' ? 'text-gray-300 border-gray-300' :
|
||||||
|
'text-gray-800 border-gray-800'">
|
||||||
|
<svg x-show="isDarkMode !== 'dark'" id="theme-toggle-dark-icon" class="w-5 h-5"
|
||||||
|
fill="currentColor" viewBox="0 0 20 20"
|
||||||
|
xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path
|
||||||
|
d="M17.293 13.293A8 8 0 016.707 2.707a8.001 8.001 0 1010.586 10.586z">
|
||||||
|
</path>
|
||||||
|
</svg>
|
||||||
|
<svg x-show="isDarkMode === 'dark'" id="theme-toggle-light-icon" class="w-5 h-5"
|
||||||
|
fill="currentColor" viewBox="0 0 20 20"
|
||||||
|
xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path
|
||||||
|
d="M10 2a1 1 0 011 1v1a1 1 0 11-2 0V3a1 1 0 011-1zm4 8a4 4 0 11-8 0 4 4 0 018 0zm-.464 4.95l.707.707a1 1 0 001.414-1.414l-.707-.707a1 1 0 00-1.414 1.414zm2.12-10.607a1 1 0 010 1.414l-.706.707a1 1 0 11-1.414-1.414l.707-.707a1 1 0 011.414 0zM17 11a1 1 0 100-2h-1a1 1 0 100 2h1zm-7 4a1 1 0 011 1v1a1 1 0 11-2 0v-1a1 1 0 011-1zM5.05 6.464A1 1 0 106.465 5.05l-.708-.707a1 1 0 00-1.414 1.414l.707.707zm1.414 8.486l-.707.707a1 1 0 01-1.414-1.414l.707-.707a1 1 0 011.414 1.414zM4 11a1 1 0 100-2H3a1 1 0 000 2h1z"
|
||||||
|
fillRule="evenodd" clipRule="evenodd"></path>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
@ -1,3 +1,4 @@
|
|||||||
|
@php use App\Enums\SiteFeature; @endphp
|
||||||
<x-app-layout :server="$site->server">
|
<x-app-layout :server="$site->server">
|
||||||
@if(isset($pageTitle))
|
@if(isset($pageTitle))
|
||||||
<x-slot name="pageTitle">{{ $site->domain }} - {{ $pageTitle }}</x-slot>
|
<x-slot name="pageTitle">{{ $site->domain }} - {{ $pageTitle }}</x-slot>
|
||||||
@ -58,10 +59,12 @@
|
|||||||
<x-secondary-sidebar-link :href="route('servers.sites.show', ['server' => $site->server, 'site' => $site])" :active="request()->routeIs('servers.sites.show')">
|
<x-secondary-sidebar-link :href="route('servers.sites.show', ['server' => $site->server, 'site' => $site])" :active="request()->routeIs('servers.sites.show')">
|
||||||
{{ __('Application') }}
|
{{ __('Application') }}
|
||||||
</x-secondary-sidebar-link>
|
</x-secondary-sidebar-link>
|
||||||
@if($site->status == \App\Enums\SiteStatus::READY)
|
@if($site->isReady() && $site->hasFeature(SiteFeature::SSL))
|
||||||
<x-secondary-sidebar-link :href="route('servers.sites.ssl', ['server' => $site->server, 'site' => $site])" :active="request()->routeIs('servers.sites.ssl')">
|
<x-secondary-sidebar-link :href="route('servers.sites.ssl', ['server' => $site->server, 'site' => $site])" :active="request()->routeIs('servers.sites.ssl')">
|
||||||
{{ __('SSL') }}
|
{{ __('SSL') }}
|
||||||
</x-secondary-sidebar-link>
|
</x-secondary-sidebar-link>
|
||||||
|
@endif
|
||||||
|
@if($site->isReady() && $site->hasFeature(SiteFeature::QUEUES))
|
||||||
<x-secondary-sidebar-link :href="route('servers.sites.queues', ['server' => $site->server, 'site' => $site])" :active="request()->routeIs('servers.sites.queues')">
|
<x-secondary-sidebar-link :href="route('servers.sites.queues', ['server' => $site->server, 'site' => $site])" :active="request()->routeIs('servers.sites.queues')">
|
||||||
{{ __('Queues') }}
|
{{ __('Queues') }}
|
||||||
</x-secondary-sidebar-link>
|
</x-secondary-sidebar-link>
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
<div>
|
<div>
|
||||||
|
<x-simple-card class="flex items-center justify-between">
|
||||||
|
<span>{{ __("Your Wordpress site is installed and ready to use! ") }}</span>
|
||||||
|
<x-secondary-button :href="$site->url" target="_blank">{{ __("Open Website") }}</x-secondary-button>
|
||||||
|
</x-simple-card>
|
||||||
</div>
|
</div>
|
||||||
|
@ -5,10 +5,10 @@
|
|||||||
<form id="create-site" wire:submit.prevent="create" class="space-y-6">
|
<form id="create-site" wire:submit.prevent="create" class="space-y-6">
|
||||||
<div>
|
<div>
|
||||||
<x-input-label>{{ __("Select site type") }}</x-input-label>
|
<x-input-label>{{ __("Select site type") }}</x-input-label>
|
||||||
<x-select-input wire:model="type" id="type" name="type" class="mt-1 w-full">
|
<x-select-input wire:model="inputs.type" id="type" name="type" class="mt-1 w-full">
|
||||||
<option value="" selected disabled>{{ __("Select") }}</option>
|
<option value="" selected disabled>{{ __("Select") }}</option>
|
||||||
@foreach(config('core.site_types') as $t)
|
@foreach(config('core.site_types') as $t)
|
||||||
<option value="{{ $t }}" @if($t === $type) selected @endif>
|
<option value="{{ $t }}" @if($t === $inputs['type']) selected @endif>
|
||||||
{{ $t }}
|
{{ $t }}
|
||||||
</option>
|
</option>
|
||||||
@endforeach
|
@endforeach
|
||||||
@ -20,7 +20,7 @@
|
|||||||
|
|
||||||
<div>
|
<div>
|
||||||
<x-input-label for="domain" :value="__('Domain')" />
|
<x-input-label for="domain" :value="__('Domain')" />
|
||||||
<x-text-input wire:model.defer="domain" id="domain" name="domain" type="text" class="mt-1 block w-full" autocomplete="domain" placeholder="example.com" />
|
<x-text-input wire:model.defer="inputs.domain" id="domain" name="domain" type="text" class="mt-1 block w-full" autocomplete="domain" placeholder="example.com" />
|
||||||
@error('domain')
|
@error('domain')
|
||||||
<x-input-error class="mt-2" :messages="$message" />
|
<x-input-error class="mt-2" :messages="$message" />
|
||||||
@enderror
|
@enderror
|
||||||
@ -28,75 +28,15 @@
|
|||||||
|
|
||||||
<div>
|
<div>
|
||||||
<x-input-label for="alias" :value="__('Alias')" />
|
<x-input-label for="alias" :value="__('Alias')" />
|
||||||
<x-text-input wire:model.defer="alias" id="alias" name="alias" type="text" class="mt-1 block w-full" autocomplete="alias" placeholder="www.example.com" />
|
<x-text-input wire:model.defer="inputs.alias" id="alias" name="alias" type="text" class="mt-1 block w-full" autocomplete="alias" placeholder="www.example.com" />
|
||||||
@error('alias')
|
@error('alias')
|
||||||
<x-input-error class="mt-2" :messages="$message" />
|
<x-input-error class="mt-2" :messages="$message" />
|
||||||
@enderror
|
@enderror
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
@if (isset($inputs['type']) && $inputs['type'])
|
||||||
<x-input-label for="php_version" :value="__('PHP Version')" />
|
@include('livewire.sites.partials.create.' . $inputs['type'])
|
||||||
<x-select-input wire:model.defer="php_version" id="php_version" name="php_version" class="mt-1 w-full">
|
@endif
|
||||||
<option value="" selected disabled>{{ __("Select") }}</option>
|
|
||||||
@foreach($server->installedPHPVersions() as $version)
|
|
||||||
<option value="{{ $version }}" @if($version === $php_version) selected @endif>
|
|
||||||
PHP {{ $version }}
|
|
||||||
</option>
|
|
||||||
@endforeach
|
|
||||||
</x-select-input>
|
|
||||||
@error('php_version')
|
|
||||||
<x-input-error class="mt-2" :messages="$message" />
|
|
||||||
@enderror
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<x-input-label for="web_directory" :value="__('Web Directory')" />
|
|
||||||
<x-text-input wire:model.defer="web_directory" id="web_directory" name="web_directory" type="text" class="mt-1 block w-full" autocomplete="web_directory" />
|
|
||||||
@error('web_directory')
|
|
||||||
<x-input-error class="mt-2" :messages="$message" />
|
|
||||||
@enderror
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<x-input-label for="source_control" :value="__('Source Control')" />
|
|
||||||
<div class="flex items-center mt-1">
|
|
||||||
<x-select-input wire:model="source_control" id="source_control" name="source_control" class="mt-1 w-full">
|
|
||||||
<option value="" selected disabled>{{ __("Select") }}</option>
|
|
||||||
@foreach($sourceControls as $sourceControl)
|
|
||||||
<option value="{{ $sourceControl->id }}" @if($sourceControl->id === $source_control) selected @endif>
|
|
||||||
{{ $sourceControl->profile }} ({{ $sourceControl->provider }})
|
|
||||||
</option>
|
|
||||||
@endforeach
|
|
||||||
</x-select-input>
|
|
||||||
<x-secondary-button :href="route('source-controls', ['redirect' => request()->url()])" class="flex-none ml-2">{{ __('Connect') }}</x-secondary-button>
|
|
||||||
</div>
|
|
||||||
@error('source_control')
|
|
||||||
<x-input-error class="mt-2" :messages="$message" />
|
|
||||||
@enderror
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<x-input-label for="repository" :value="__('Repository')" />
|
|
||||||
<x-text-input wire:model.defer="repository" id="repository" name="repository" type="text" class="mt-1 block w-full" autocomplete="repository" placeholder="organization/repository" />
|
|
||||||
@error('repository')
|
|
||||||
<x-input-error class="mt-2" :messages="$message" />
|
|
||||||
@enderror
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<x-input-label for="branch" :value="__('Branch')" />
|
|
||||||
<x-text-input wire:model.defer="branch" id="branch" name="branch" type="text" class="mt-1 block w-full" autocomplete="branch" placeholder="main" />
|
|
||||||
@error('branch')
|
|
||||||
<x-input-error class="mt-2" :messages="$message" />
|
|
||||||
@enderror
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="mt-6">
|
|
||||||
<label for="composer" class="inline-flex items-center">
|
|
||||||
<input id="composer" wire:model.defer="composer" type="checkbox" class="rounded dark:bg-gray-900 border-gray-300 dark:border-gray-700 text-indigo-600 shadow-sm focus:ring-indigo-500 dark:focus:ring-indigo-600 dark:focus:ring-offset-gray-800" name="composer">
|
|
||||||
<span class="ml-2 text-sm text-gray-600 dark:text-gray-400">{{ __('Run `composer install --no-dev`') }}</span>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</form>
|
</form>
|
||||||
<x-slot name="actions">
|
<x-slot name="actions">
|
||||||
<x-primary-button form="create-site" wire:loading.attr="disabled">{{ __('Create') }}</x-primary-button>
|
<x-primary-button form="create-site" wire:loading.attr="disabled">{{ __('Create') }}</x-primary-button>
|
||||||
|
@ -0,0 +1,7 @@
|
|||||||
|
<div>
|
||||||
|
<x-input-label for="branch" :value="__('Branch')" />
|
||||||
|
<x-text-input wire:model.defer="inputs.branch" id="branch" name="branch" type="text" class="mt-1 block w-full" autocomplete="branch" placeholder="main" />
|
||||||
|
@error('branch')
|
||||||
|
<x-input-error class="mt-2" :messages="$message" />
|
||||||
|
@enderror
|
||||||
|
</div>
|
@ -0,0 +1,6 @@
|
|||||||
|
<div class="mt-6">
|
||||||
|
<label for="composer" class="inline-flex items-center">
|
||||||
|
<input id="composer" wire:model.defer="inputs.composer" type="checkbox" class="rounded dark:bg-gray-900 border-gray-300 dark:border-gray-700 text-indigo-600 shadow-sm focus:ring-indigo-500 dark:focus:ring-indigo-600 dark:focus:ring-offset-gray-800" name="composer">
|
||||||
|
<span class="ml-2 text-sm text-gray-600 dark:text-gray-400">{{ __('Run `composer install --no-dev`') }}</span>
|
||||||
|
</label>
|
||||||
|
</div>
|
@ -0,0 +1,17 @@
|
|||||||
|
@php
|
||||||
|
/* @var \App\Models\Server $server */
|
||||||
|
@endphp
|
||||||
|
<div>
|
||||||
|
<x-input-label for="php_version" :value="__('PHP Version')" />
|
||||||
|
<x-select-input wire:model.defer="inputs.php_version" id="php_version" name="php_version" class="mt-1 w-full">
|
||||||
|
<option value="" selected>{{ __("Select") }}</option>
|
||||||
|
@foreach($server->installedPHPVersions() as $version)
|
||||||
|
<option value="{{ $version }}" @if($version === $inputs['php_version']) selected @endif>
|
||||||
|
PHP {{ $version }}
|
||||||
|
</option>
|
||||||
|
@endforeach
|
||||||
|
</x-select-input>
|
||||||
|
@error('php_version')
|
||||||
|
<x-input-error class="mt-2" :messages="$message" />
|
||||||
|
@enderror
|
||||||
|
</div>
|
@ -0,0 +1,7 @@
|
|||||||
|
<div>
|
||||||
|
<x-input-label for="repository" :value="__('Repository')" />
|
||||||
|
<x-text-input wire:model.defer="inputs.repository" id="repository" name="repository" type="text" class="mt-1 block w-full" autocomplete="repository" placeholder="organization/repository" />
|
||||||
|
@error('repository')
|
||||||
|
<x-input-error class="mt-2" :messages="$message" />
|
||||||
|
@enderror
|
||||||
|
</div>
|
@ -0,0 +1,17 @@
|
|||||||
|
<div>
|
||||||
|
<x-input-label for="source_control" :value="__('Source Control')" />
|
||||||
|
<div class="flex items-center mt-1">
|
||||||
|
<x-select-input wire:model="inputs.source_control" id="source_control" name="source_control" class="mt-1 w-full">
|
||||||
|
<option value="" selected>{{ __("Select") }}</option>
|
||||||
|
@foreach($sourceControls as $sourceControl)
|
||||||
|
<option value="{{ $sourceControl->id }}" @if($sourceControl->id === $inputs['source_control']) selected @endif>
|
||||||
|
{{ $sourceControl->profile }} ({{ $sourceControl->provider }})
|
||||||
|
</option>
|
||||||
|
@endforeach
|
||||||
|
</x-select-input>
|
||||||
|
<x-secondary-button :href="route('source-controls', ['redirect' => request()->url()])" class="flex-none ml-2">{{ __('Connect') }}</x-secondary-button>
|
||||||
|
</div>
|
||||||
|
@error('source_control')
|
||||||
|
<x-input-error class="mt-2" :messages="$message" />
|
||||||
|
@enderror
|
||||||
|
</div>
|
@ -0,0 +1,10 @@
|
|||||||
|
<div>
|
||||||
|
<x-input-label for="web_directory" :value="__('Web Directory')" />
|
||||||
|
<x-text-input wire:model.defer="inputs.web_directory" id="web_directory" name="web_directory" type="text" class="mt-1 block w-full" autocomplete="web_directory" />
|
||||||
|
<x-input-help>
|
||||||
|
{{ __("For root, leave this blank") }}
|
||||||
|
</x-input-help>
|
||||||
|
@error('web_directory')
|
||||||
|
<x-input-error class="mt-2" :messages="$message" />
|
||||||
|
@enderror
|
||||||
|
</div>
|
@ -0,0 +1,11 @@
|
|||||||
|
@include('livewire.sites.partials.create.fields.php-version')
|
||||||
|
|
||||||
|
@include('livewire.sites.partials.create.fields.web-directory')
|
||||||
|
|
||||||
|
@include('livewire.sites.partials.create.fields.source-control')
|
||||||
|
|
||||||
|
@include('livewire.sites.partials.create.fields.repository')
|
||||||
|
|
||||||
|
@include('livewire.sites.partials.create.fields.branch')
|
||||||
|
|
||||||
|
@include('livewire.sites.partials.create.fields.composer')
|
11
resources/views/livewire/sites/partials/create/php.blade.php
Normal file
11
resources/views/livewire/sites/partials/create/php.blade.php
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
@include('livewire.sites.partials.create.fields.php-version')
|
||||||
|
|
||||||
|
@include('livewire.sites.partials.create.fields.web-directory')
|
||||||
|
|
||||||
|
@include('livewire.sites.partials.create.fields.source-control')
|
||||||
|
|
||||||
|
@include('livewire.sites.partials.create.fields.repository')
|
||||||
|
|
||||||
|
@include('livewire.sites.partials.create.fields.branch')
|
||||||
|
|
||||||
|
@include('livewire.sites.partials.create.fields.composer')
|
@ -0,0 +1,63 @@
|
|||||||
|
@include('livewire.sites.partials.create.fields.php-version')
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<x-input-label for="title" :value="__('Title')" />
|
||||||
|
<x-text-input wire:model.defer="inputs.title" id="title" name="title" type="text" class="mt-1 block w-full" autocomplete="branch" />
|
||||||
|
@error('title')
|
||||||
|
<x-input-error class="mt-2" :messages="$message" />
|
||||||
|
@enderror
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="grid grid-cols-1 lg:grid-cols-3 gap-5">
|
||||||
|
<div>
|
||||||
|
<x-input-label for="email" :value="__('WP Admin Email')" />
|
||||||
|
<x-text-input wire:model.defer="inputs.email" id="email" name="email" type="email" class="mt-1 block w-full" autocomplete="email" />
|
||||||
|
@error('email')
|
||||||
|
<x-input-error class="mt-2" :messages="$message" />
|
||||||
|
@enderror
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<x-input-label for="username" :value="__('WP Admin Username')" />
|
||||||
|
<x-text-input wire:model.defer="inputs.username" id="username" name="username" type="text" class="mt-1 block w-full" autocomplete="username" />
|
||||||
|
@error('username')
|
||||||
|
<x-input-error class="mt-2" :messages="$message" />
|
||||||
|
@enderror
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<x-input-label for="password" :value="__('WP Admin Password')" />
|
||||||
|
<x-text-input wire:model.defer="inputs.password" id="password" name="password" type="text" class="mt-1 block w-full" />
|
||||||
|
@error('title')
|
||||||
|
<x-input-error class="mt-2" :messages="$message" />
|
||||||
|
@enderror
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="grid grid-cols-1 lg:grid-cols-3 gap-5">
|
||||||
|
<div>
|
||||||
|
<x-input-label for="database" :value="__('Database Name')" />
|
||||||
|
<x-text-input wire:model.defer="inputs.database" id="database" name="database" type="text" class="mt-1 block w-full" autocomplete="database" />
|
||||||
|
<x-input-help>{{ __("It will create a database with this name") }}</x-input-help>
|
||||||
|
@error('database')
|
||||||
|
<x-input-error class="mt-2" :messages="$message" />
|
||||||
|
@enderror
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<x-input-label for="database" :value="__('Database User')" />
|
||||||
|
<x-text-input wire:model.defer="inputs.database_user" id="database_user" name="database_user" type="text" class="mt-1 block w-full" autocomplete="database_user" />
|
||||||
|
<x-input-help>{{ __("It will create a database user with this username") }}</x-input-help>
|
||||||
|
@error('database_user')
|
||||||
|
<x-input-error class="mt-2" :messages="$message" />
|
||||||
|
@enderror
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<x-input-label for="password" :value="__('Database Password')" />
|
||||||
|
<x-text-input wire:model.defer="inputs.database_password" id="database_password" name="database_password" type="text" class="mt-1 block w-full" />
|
||||||
|
@error('database_password')
|
||||||
|
<x-input-error class="mt-2" :messages="$message" />
|
||||||
|
@enderror
|
||||||
|
</div>
|
||||||
|
</div>
|
@ -22,7 +22,10 @@ class SitesTest extends TestCase
|
|||||||
{
|
{
|
||||||
use RefreshDatabase;
|
use RefreshDatabase;
|
||||||
|
|
||||||
public function test_create_site(): void
|
/**
|
||||||
|
* @dataProvider create_data
|
||||||
|
*/
|
||||||
|
public function test_create_site(array $inputs): void
|
||||||
{
|
{
|
||||||
Bus::fake();
|
Bus::fake();
|
||||||
|
|
||||||
@ -36,15 +39,8 @@ public function test_create_site(): void
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
Livewire::test(CreateSite::class, ['server' => $this->server])
|
Livewire::test(CreateSite::class, ['server' => $this->server])
|
||||||
->set('type', SiteType::LARAVEL)
|
->fill($inputs)
|
||||||
->set('domain', 'example.com')
|
->set('inputs.source_control', $sourceControl->id)
|
||||||
->set('alias', 'www.example.com')
|
|
||||||
->set('php_version', '8.2')
|
|
||||||
->set('web_directory', 'public')
|
|
||||||
->set('source_control', $sourceControl->id)
|
|
||||||
->set('repository', 'test/test')
|
|
||||||
->set('branch', 'main')
|
|
||||||
->set('composer', true)
|
|
||||||
->call('create')
|
->call('create')
|
||||||
->assertSuccessful()
|
->assertSuccessful()
|
||||||
->assertHasNoErrors();
|
->assertHasNoErrors();
|
||||||
@ -127,4 +123,37 @@ public function test_update_source_control(): void
|
|||||||
|
|
||||||
$this->assertEquals($gitlab->id, $this->site->source_control_id);
|
$this->assertEquals($gitlab->id, $this->site->source_control_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function create_data(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
[
|
||||||
|
[
|
||||||
|
'inputs.type' => SiteType::LARAVEL,
|
||||||
|
'inputs.domain' => 'example.com',
|
||||||
|
'inputs.alias' => 'www.example.com',
|
||||||
|
'inputs.php_version' => '8.2',
|
||||||
|
'inputs.web_directory' => 'public',
|
||||||
|
'inputs.repository' => 'test/test',
|
||||||
|
'inputs.branch' => 'main',
|
||||||
|
'inputs.composer' => true,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
[
|
||||||
|
'inputs.type' => SiteType::WORDPRESS,
|
||||||
|
'inputs.domain' => 'example.com',
|
||||||
|
'inputs.alias' => 'www.example.com',
|
||||||
|
'inputs.php_version' => '8.2',
|
||||||
|
'inputs.title' => 'Example',
|
||||||
|
'inputs.username' => 'example',
|
||||||
|
'inputs.email' => 'email@example.com',
|
||||||
|
'inputs.password' => 'password',
|
||||||
|
'inputs.database' => 'example',
|
||||||
|
'inputs.database_user' => 'example',
|
||||||
|
'inputs.database_password' => 'password',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user