diff --git a/app/Actions/Site/Deploy.php b/app/Actions/Site/Deploy.php index fccf265..ab1487b 100644 --- a/app/Actions/Site/Deploy.php +++ b/app/Actions/Site/Deploy.php @@ -6,6 +6,7 @@ use App\Exceptions\DeploymentScriptIsEmptyException; use App\Exceptions\SourceControlIsNotConnected; use App\Models\Deployment; +use App\Models\ServerLog; use App\Models\Site; class Deploy @@ -37,10 +38,15 @@ public function run(Site $site): Deployment $deployment->save(); dispatch(function () use ($site, $deployment) { - $log = $site->server->os()->runScript($site->path, $site->deploymentScript->content, $site->id); - $deployment->status = DeploymentStatus::FINISHED; + /** @var ServerLog $log */ + $log = ServerLog::make($site->server, 'deploy-'.strtotime('now')) + ->forSite($site); + $log->save(); $deployment->log_id = $log->id; $deployment->save(); + $site->server->os()->runScript($site->path, $site->deploymentScript->content, $log); + $deployment->status = DeploymentStatus::FINISHED; + $deployment->save(); })->catch(function () use ($deployment) { $deployment->status = DeploymentStatus::FAILED; $deployment->save(); diff --git a/app/Facades/SSH.php b/app/Facades/SSH.php index 66eecd3..b98e770 100644 --- a/app/Facades/SSH.php +++ b/app/Facades/SSH.php @@ -3,6 +3,7 @@ namespace App\Facades; use App\Models\Server; +use App\Models\ServerLog; use App\Support\Testing\SSHFake; use Illuminate\Support\Facades\Facade as FacadeAlias; @@ -10,7 +11,7 @@ * Class SSH * * @method static init(Server $server, string $asUser = null) - * @method static setLog(string $logType, int $siteId = null) + * @method static setLog(?ServerLog $log) * @method static connect() * @method static string exec(string $command, string $log = '', int $siteId = null, ?bool $stream = false) * @method static string assertExecuted(array|string $commands) diff --git a/app/Helpers/SSH.php b/app/Helpers/SSH.php index e6a5dc8..145418e 100755 --- a/app/Helpers/SSH.php +++ b/app/Helpers/SSH.php @@ -50,14 +50,9 @@ public function init(Server $server, ?string $asUser = null): self return $this; } - public function setLog(string $logType, $siteId = null): self + public function setLog(ServerLog $log): self { - $this->log = $this->server->logs()->create([ - 'site_id' => $siteId, - 'name' => $this->server->id.'-'.strtotime('now').'-'.$logType.'.log', - 'type' => $logType, - 'disk' => config('core.logs_disk'), - ]); + $this->log = $log; return $this; } @@ -98,10 +93,18 @@ public function connect(bool $sftp = false): void */ public function exec(string $command, string $log = '', ?int $siteId = null, ?bool $stream = false): string { - if ($log) { - $this->setLog($log, $siteId); - } else { - $this->log = null; + if (! $this->log && $log) { + $this->log = $this->server->logs()->create([ + 'site_id' => $siteId, + 'name' => $this->server->id.'-'.strtotime('now').'-'.$log.'.log', + 'type' => $log, + 'disk' => config('core.logs_disk'), + ]); + $this->log = ServerLog::make($this->server, $log); + if ($siteId) { + $this->log->forSite($siteId); + } + $this->log->save(); } try { @@ -132,8 +135,8 @@ public function exec(string $command, string $log = '', ?int $siteId = null, ?bo $this->log?->write($output); - if (Str::contains($output, 'VITO_SSH_ERROR')) { - throw new SSHCommandError('SSH command failed with an error'); + if ($this->connection->getExitStatus() !== 0 || Str::contains($output, 'VITO_SSH_ERROR')) { + throw new SSHCommandError('SSH command failed with an error', $this->connection->getExitStatus()); } return $output; diff --git a/app/Http/Middleware/HandleSSHErrors.php b/app/Http/Middleware/HandleSSHErrors.php index 03df15a..7d2b99d 100644 --- a/app/Http/Middleware/HandleSSHErrors.php +++ b/app/Http/Middleware/HandleSSHErrors.php @@ -14,17 +14,17 @@ class HandleSSHErrors public function handle(Request $request, Closure $next) { $res = $next($request); - if ($res instanceof Response && $res->exception) { - if ($res->exception instanceof SSHConnectionError || $res->exception instanceof SSHCommandError) { - Toast::error($res->exception->getMessage()); + // if ($res instanceof Response && $res->exception) { + // if ($res->exception instanceof SSHConnectionError || $res->exception instanceof SSHCommandError) { + // Toast::error($res->exception->getMessage()); - if ($request->hasHeader('HX-Request')) { - return htmx()->back(); - } + // if ($request->hasHeader('HX-Request')) { + // return htmx()->back(); + // } - return back(); - } - } + // return back(); + // } + // } return $res; } diff --git a/app/Models/ServerLog.php b/app/Models/ServerLog.php index b6119ab..36c66f5 100755 --- a/app/Models/ServerLog.php +++ b/app/Models/ServerLog.php @@ -115,4 +115,27 @@ public static function log(Server $server, string $type, string $content, ?Site $log->save(); $log->write($content); } + + public static function make(Server $server, string $type): ServerLog + { + return new static([ + 'server_id' => $server->id, + 'name' => $server->id.'-'.strtotime('now').'-'.$type.'.log', + 'type' => $type, + 'disk' => config('core.logs_disk'), + ]); + } + + public function forSite(Site|int $site): ServerLog + { + if ($site instanceof Site) { + $site = $site->id; + } + + if (is_int($site)) { + $this->site_id = $site; + } + + return $this; + } } diff --git a/app/Models/Site.php b/app/Models/Site.php index c0f8ecb..f18a778 100755 --- a/app/Models/Site.php +++ b/app/Models/Site.php @@ -3,6 +3,7 @@ namespace App\Models; use App\Exceptions\SourceControlIsNotConnected; +use App\Exceptions\SSHError; use App\SiteTypes\SiteType; use App\SSH\Services\Webserver\Webserver; use Illuminate\Database\Eloquent\Factories\HasFactory; @@ -271,6 +272,10 @@ public function hasFeature(string $feature): bool public function getEnv(): string { - return $this->server->os()->readFile($this->path.'/.env'); + try { + return $this->server->os()->readFile($this->path.'/.env'); + } catch (SSHError) { + return ''; + } } } diff --git a/app/SSH/OS/OS.php b/app/SSH/OS/OS.php index c9aa1ee..e8f4a86 100644 --- a/app/SSH/OS/OS.php +++ b/app/SSH/OS/OS.php @@ -127,16 +127,18 @@ public function tail(string $path, int $lines): string ); } - public function runScript(string $path, string $script, ?int $siteId = null): ServerLog + public function runScript(string $path, string $script, ?ServerLog $serverLog): ServerLog { $ssh = $this->server->ssh(); + if ($serverLog) { + $ssh->setLog($serverLog); + } $ssh->exec( $this->getScript('run-script.sh', [ 'path' => $path, 'script' => $script, ]), - 'run-script', - $siteId + 'run-script' ); return $ssh->log; diff --git a/app/SSH/Services/Monitoring/VitoAgent/VitoAgent.php b/app/SSH/Services/Monitoring/VitoAgent/VitoAgent.php index c0bfbc6..d834d8a 100644 --- a/app/SSH/Services/Monitoring/VitoAgent/VitoAgent.php +++ b/app/SSH/Services/Monitoring/VitoAgent/VitoAgent.php @@ -5,6 +5,7 @@ use App\Models\Metric; use App\SSH\HasScripts; use App\SSH\Services\AbstractService; +use Closure; use Illuminate\Support\Facades\Http; use Illuminate\Validation\Rule; use Ramsey\Uuid\Uuid; @@ -21,7 +22,12 @@ public function creationRules(array $input): array { return [ 'type' => [ - Rule::unique('services', 'type')->where('server_id', $this->service->server_id), + function (string $attribute, mixed $value, Closure $fail) { + $monitoringExists = $this->service->server->monitoring(); + if ($monitoringExists) { + $fail('You already have a monitoring service on the server.'); + } + }, ], 'version' => [ 'required', diff --git a/app/Support/Testing/SSHFake.php b/app/Support/Testing/SSHFake.php index 593b7e1..2cecde9 100644 --- a/app/Support/Testing/SSHFake.php +++ b/app/Support/Testing/SSHFake.php @@ -36,10 +36,13 @@ public function connect(bool $sftp = false): void public function exec(string $command, string $log = '', ?int $siteId = null, ?bool $stream = false): string { - if ($log) { - $this->setLog($log, $siteId); - } else { - $this->log = null; + if (! $this->log && $log) { + $this->log = $this->server->logs()->create([ + 'site_id' => $siteId, + 'name' => $this->server->id.'-'.strtotime('now').'-'.$log.'.log', + 'type' => $log, + 'disk' => config('core.logs_disk'), + ]); } $this->commands[] = $command; diff --git a/resources/views/services/partials/installers/vito-agent.blade.php b/resources/views/services/partials/installers/vito-agent.blade.php index 45df258..2a2347b 100644 --- a/resources/views/services/partials/installers/vito-agent.blade.php +++ b/resources/views/services/partials/installers/vito-agent.blade.php @@ -19,6 +19,10 @@ class="p-6" {{ __("Install Vito Agent") }} + @error("type") + + @enderror +
Vito Agent is only works if you are running your Vito instance on a cloud not local! Consider diff --git a/tests/Feature/ApplicationTest.php b/tests/Feature/ApplicationTest.php index 341451f..b1e120a 100644 --- a/tests/Feature/ApplicationTest.php +++ b/tests/Feature/ApplicationTest.php @@ -49,7 +49,7 @@ public function test_update_deployment_script() public function test_deploy(): void { - SSH::fake(); + SSH::fake('fake output'); Http::fake([ 'github.com/*' => Http::response([ 'sha' => '123',