Accurate deployment statuses (#168)

This commit is contained in:
Saeed Vaziry 2024-04-21 16:26:26 +02:00 committed by GitHub
parent e2dd9177f7
commit f0da1c6d8c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 88 additions and 35 deletions

View File

@ -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();

View File

@ -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)

View File

@ -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;

View File

@ -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;
}

View File

@ -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;
}
}

View File

@ -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 '';
}
}
}

View File

@ -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;

View File

@ -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',

View File

@ -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;

View File

@ -19,6 +19,10 @@ class="p-6"
{{ __("Install Vito Agent") }}
</h2>
@error("type")
<x-input-error class="mt-2" :messages="$message" />
@enderror
<div class="mt-6">
<x-alert-warning>
Vito Agent is only works if you are running your Vito instance on a cloud not local! Consider

View File

@ -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',