'integer', 'type_data' => 'json', 'port' => 'integer', 'progress' => 'integer', 'auto_deployment' => 'boolean', 'aliases' => 'array', 'source_control_id' => 'integer', ]; protected $appends = [ 'url', 'auto_deployment', ]; public static function boot(): void { parent::boot(); static::deleting(function (Site $site) { $site->redirects()->delete(); $site->queues()->delete(); $site->ssls()->delete(); $site->deployments()->delete(); $site->deploymentScript()->delete(); }); static::created(function (Site $site) { $site->deploymentScript()->create([ 'name' => 'default', 'content' => '', ]); }); } public function server(): BelongsTo { return $this->belongsTo(Server::class); } public function logs(): HasMany { return $this->hasMany(ServerLog::class); } public function deployments(): HasMany { return $this->hasMany(Deployment::class); } public function gitHook(): HasOne { return $this->hasOne(GitHook::class); } public function deploymentScript(): HasOne { return $this->hasOne(DeploymentScript::class); } public function redirects(): HasMany { return $this->hasMany(Redirect::class); } public function queues(): HasMany { return $this->hasMany(Queue::class); } public function ssls(): HasMany { return $this->hasMany(Ssl::class); } /** * @throws SourceControlIsNotConnected */ public function sourceControl(): SourceControl|HasOne|null|Model { $sourceControl = null; if (! $this->source_control && ! $this->source_control_id) { return null; } if ($this->source_control) { $sourceControl = SourceControl::query()->where('provider', $this->source_control)->first(); } if ($this->source_control_id) { $sourceControl = SourceControl::query()->find($this->source_control_id); } if (! $sourceControl) { throw new SourceControlIsNotConnected($this->source_control); } return $sourceControl; } /** * @throws SourceControlIsNotConnected */ public function getFullRepositoryUrlAttribute() { return $this->sourceControl()->provider()->fullRepoUrl($this->repository, $this->ssh_key_name); } public function getAliasesStringAttribute(): string { if (count($this->aliases) > 0) { return implode(' ', $this->aliases); } return ''; } public function type(): SiteType { $typeClass = config('core.site_types_class.'.$this->type); return new $typeClass($this); } public function install(): void { $this->type()->install(); } public function remove(): void { $this->update([ 'status' => SiteStatus::DELETING, ]); $this->type()->delete(); } public function php(): ?Service { if ($this->php_version) { return $this->server->php($this->php_version); } return null; } public function changePHPVersion($version): void { dispatch(new ChangePHPVersion($this, $version))->onConnection('ssh'); } public function getDeploymentScriptTextAttribute(): string { /* @var DeploymentScript $script */ $script = $this->deploymentScript()->firstOrCreate([ 'site_id' => $this->id, ], [ 'site_id' => $this->id, 'name' => 'default', ]); return $script->content; } /** * @throws SourceControlIsNotConnected */ public function deploy(): Deployment { if ($this->sourceControl()) { $this->sourceControl()->getRepo($this->repository); } $deployment = new Deployment([ 'site_id' => $this->id, 'deployment_script_id' => $this->deploymentScript->id, 'status' => DeploymentStatus::DEPLOYING, ]); $lastCommit = $this->sourceControl()->provider()->getLastCommit($this->repository, $this->branch); if ($lastCommit) { $deployment->commit_id = $lastCommit['commit_id']; $deployment->commit_data = $lastCommit['commit_data']; } $deployment->save(); dispatch(new Deploy($deployment, $this->path))->onConnection('ssh'); return $deployment; } public function getEnvAttribute(): string { $typeData = $this->type_data; if (! isset($typeData['env'])) { $typeData['env'] = ''; $this->type_data = $typeData; $this->save(); } return $typeData['env']; } public function deployEnv(): void { dispatch(new DeployEnv($this))->onConnection('ssh'); } public function activeSsl(): HasOne { return $this->hasOne(Ssl::class) ->where('expires_at', '>=', now()) ->orderByDesc('id'); } public function createFreeSsl(): void { $ssl = new Ssl([ 'site_id' => $this->id, 'type' => 'letsencrypt', 'expires_at' => now()->addMonths(3), 'status' => SslStatus::CREATING, ]); $ssl->save(); $ssl->deploy(); } public function createCustomSsl(string $certificate, string $pk): void { $ssl = new Ssl([ 'site_id' => $this->id, 'type' => 'custom', 'certificate' => $certificate, 'pk' => $pk, 'expires_at' => '', 'status' => SslStatus::CREATING, ]); $ssl->save(); $ssl->deploy(); } public function getUrlAttribute(): string { if ($this->activeSsl) { return 'https://'.$this->domain; } return 'http://'.$this->domain; } public function getWebDirectoryPathAttribute(): string { if ($this->web_directory) { return $this->path.'/'.$this->web_directory; } return $this->path; } /** * @throws SourceControlIsNotConnected * @throws Throwable */ public function enableAutoDeployment(): void { if ($this->gitHook) { return; } if (! $this->sourceControl()) { throw new SourceControlIsNotConnected($this->source_control); } try { DB::beginTransaction(); $gitHook = new GitHook([ 'site_id' => $this->id, 'source_control_id' => $this->sourceControl()->id, 'secret' => Str::uuid()->toString(), 'actions' => ['deploy'], 'events' => ['push'], ]); $gitHook->save(); $gitHook->deployHook(); DB::commit(); } catch (Exception $e) { DB::rollBack(); throw $e; } } /** * @throws Throwable */ public function disableAutoDeployment(): void { $this->gitHook?->destroyHook(); } public function getAutoDeploymentAttribute(): bool { return (bool) $this->gitHook; } public function updateBranch(string $branch): void { dispatch(new UpdateBranch($this, $branch))->onConnection('ssh'); } public function getSshKeyNameAttribute(): string { return str('site_'.$this->id)->toString(); } }