logs ot fixes in executeNow.

errors handled properly, etc.
This commit is contained in:
Andras Bacsai 2023-04-14 21:09:38 +02:00
parent 14919980c2
commit 46a543441f
9 changed files with 157 additions and 68 deletions

3
.gitignore vendored
View File

@ -20,3 +20,6 @@ yarn-error.log
/.npm
/.bash_history
/_volumes
.lesshst
psysh_history

View File

@ -16,7 +16,9 @@ class RunRemoteProcess
public bool $hideFromOutput;
public bool $setStatus;
public bool $isFinished;
public bool $ignoreErrors;
protected $timeStart;
@ -31,7 +33,7 @@ class RunRemoteProcess
/**
* Create a new job instance.
*/
public function __construct(Activity $activity, bool $hideFromOutput = false, bool $setStatus = false)
public function __construct(Activity $activity, bool $hideFromOutput = false, bool $isFinished = false, bool $ignoreErrors = false)
{
if ($activity->getExtraProperty('type') !== ActivityTypes::REMOTE_PROCESS->value && $activity->getExtraProperty('type') !== ActivityTypes::DEPLOYMENT->value) {
@ -40,36 +42,41 @@ public function __construct(Activity $activity, bool $hideFromOutput = false, bo
$this->activity = $activity;
$this->hideFromOutput = $hideFromOutput;
$this->setStatus = $setStatus;
$this->isFinished = $isFinished;
$this->ignoreErrors = $ignoreErrors;
}
public function __invoke(): ProcessResult
{
$this->activity->properties = $this->activity->properties->merge([
'status' => ProcessStatus::IN_PROGRESS,
]);
$this->timeStart = hrtime(true);
$status = ProcessStatus::IN_PROGRESS;
$processResult = Process::run($this->getCommand(), $this->handleOutput(...));
$status = $processResult->exitCode() != 0 ? ProcessStatus::ERROR : ($this->setStatus ? ProcessStatus::FINISHED : null);
if ($this->activity->properties->get('status') === ProcessStatus::ERROR->value) {
$status = ProcessStatus::ERROR;
} else {
if (($processResult->exitCode() == 0 && $this->isFinished) || $this->activity->properties->get('status') === ProcessStatus::FINISHED->value) {
$status = ProcessStatus::FINISHED;
}
if ($processResult->exitCode() != 0 && !$this->ignoreErrors) {
$status = ProcessStatus::ERROR;
}
}
$this->activity->properties = $this->activity->properties->merge([
'exitCode' => $processResult->exitCode(),
'stdout' => $this->hideFromOutput || $processResult->output(),
'stdout' => $processResult->output(),
'stderr' => $processResult->errorOutput(),
'status' => $status->value,
]);
if (isset($status)) {
$this->activity->properties = $this->activity->properties->merge([
'status' => $status->value,
]);
}
$this->activity->save();
if ($processResult->exitCode() != 0 && $processResult->errorOutput()) {
throw new \RuntimeException('Remote command failed');
if ($processResult->exitCode() != 0 && !$this->ignoreErrors) {
throw new \RuntimeException($processResult->errorOutput());
}
return $processResult;
}
@ -98,9 +105,7 @@ protected function handleOutput(string $type, string $output)
if ($this->hideFromOutput) {
return;
}
$this->currentTime = $this->elapsedTime();
$this->activity->description = $this->encodeOutput($type, $output);
if ($this->isAfterLastThrottle()) {

View File

@ -0,0 +1,29 @@
<?php
namespace App\Http\Livewire;
use App\Models\Application;
use Livewire\Component;
class ApplicationForm extends Component
{
protected Application $application;
public string $applicationId;
public string $name;
public string|null $fqdn;
public string $git_repository;
public string $git_branch;
public string|null $git_commit_sha;
public function mount() {
$this->application = Application::find($this->applicationId);
$this->fill([
'name' => $this->application->name,
'fqdn' => $this->application->fqdn,
'git_repository' => $this->application->git_repository,
'git_branch' => $this->application->git_branch,
'git_commit_sha' => $this->application->git_commit_sha,
]);
}
}

View File

@ -9,7 +9,7 @@
class DeployApplication extends Component
{
public string $application_uuid;
public string $applicationId;
public $activity;
public $status;
public Application $application;
@ -19,10 +19,9 @@ class DeployApplication extends Component
protected array $command = [];
protected $source;
public function mount($application_uuid)
public function mount($applicationId)
{
$this->application_uuid = $application_uuid;
$this->application = Application::where('uuid', $this->application_uuid)->first();
$this->application = Application::find($applicationId)->first();
$this->destination = $this->application->destination->getMorphClass()::where('id', $this->application->destination->id)->first();
}
@ -39,7 +38,7 @@ public function start()
dispatch(new DeployApplicationJob(
deployment_uuid: $this->deployment_uuid,
application_uuid: $this->application_uuid,
application_uuid: $this->application->uuid,
));
$currentUrl = url()->previous();
@ -49,13 +48,13 @@ public function start()
public function stop()
{
runRemoteCommandSync($this->destination->server, ["docker stop -t 0 {$this->application_uuid} >/dev/null 2>&1"]);
runRemoteCommandSync($this->destination->server, ["docker stop -t 0 {$this->application->uuid} >/dev/null 2>&1"]);
$this->application->status = 'stopped';
$this->application->save();
}
public function kill()
{
runRemoteCommandSync($this->destination->server, ["docker rm -f {$this->application_uuid}"]);
runRemoteCommandSync($this->destination->server, ["docker rm -f {$this->application->uuid}"]);
if ($this->application->status != 'exited') {
$this->application->status = 'exited';
$this->application->save();

View File

@ -75,38 +75,39 @@ public function __construct(
*/
public function handle(): void
{
$coolify_instance_settings = CoolifyInstanceSettings::find(1);
$this->source = $this->application->source->getMorphClass()::where('id', $this->application->source->id)->first();
try {
$coolify_instance_settings = CoolifyInstanceSettings::find(1);
$this->source = $this->application->source->getMorphClass()::where('id', $this->application->source->id)->first();
// Get Wildcard Domain
$project_wildcard_domain = data_get($this->application, 'environment.project.settings.wildcard_domain');
$global_wildcard_domain = data_get($coolify_instance_settings, 'wildcard_domain');
$wildcard_domain = $project_wildcard_domain ?? $global_wildcard_domain ?? null;
// Get Wildcard Domain
$project_wildcard_domain = data_get($this->application, 'environment.project.settings.wildcard_domain');
$global_wildcard_domain = data_get($coolify_instance_settings, 'wildcard_domain');
$wildcard_domain = $project_wildcard_domain ?? $global_wildcard_domain ?? null;
// Set wildcard domain
if (!$this->application->settings->is_bot && !$this->application->fqdn && $wildcard_domain) {
$this->application->fqdn = $this->application->uuid . '.' . $wildcard_domain;
$this->application->save();
}
$this->workdir = "/artifacts/{$this->deployment_uuid}";
// Set wildcard domain
if (!$this->application->settings->is_bot && !$this->application->fqdn && $wildcard_domain) {
$this->application->fqdn = $this->application->uuid . '.' . $wildcard_domain;
$this->application->save();
}
$this->workdir = "/artifacts/{$this->deployment_uuid}";
$this->executeNow([
"docker inspect {$this->application->uuid} >/dev/null 2>&1",
"echo $?"
], 'stopped_container_check', hideFromOutput: true);
// $this->executeNow([
// "docker inspect {$this->application->uuid} >/dev/null 2>&1",
// "echo $?"
// ], 'stopped_container_check', hideFromOutput: true, ignoreErrors: true);
if ($this->activity->properties->get('stopped_container_check') == 0) {
$this->executeNow([
"echo -n 'Container {$this->application->uuid} was stopped, starting it...'"
]);
$this->executeNow([
"docker start {$this->application->uuid}"
], hideFromOutput: true);
// if ($this->activity->properties->get('stopped_container_check') == 0) {
// $this->executeNow([
// "echo 'Application is already available. Starting it...'"
// ]);
// $this->executeNow([
// "docker start {$this->application->uuid}"
// ], hideFromOutput: true);
$this->executeNow([
"echo 'Started! 🎉'"
], setStatus: true);
} else {
// $this->executeNow([
// "echo 'Done. 🎉'",
// ], isFinished: true);
// } else {
// Pull builder image
$this->executeNow([
"echo 'Starting deployment of {$this->application->git_repository}:{$this->application->git_branch}...'",
@ -132,6 +133,26 @@ public function handle(): void
$this->executeNow([$this->execute_in_builder("cd {$this->workdir} && git rev-parse HEAD")], 'commit_sha', hideFromOutput: true);
$this->git_commit = $this->activity->properties->get('commit_sha');
$this->executeNow([
"docker inspect {$this->application->uuid} --format '{{json .Config.Image}}' 2>&1",
], 'stopped_container_image', hideFromOutput: true, ignoreErrors: true);
$image = $this->activity->properties->get('stopped_container_image');
if (isset($image)) {
$image = explode(':', str_replace('"', '', $image))[1];
if ($image == $this->git_commit) {
$this->executeNow([
"echo 'Application found locally with the same Git Commit SHA. Starting it...'"
]);
$this->executeNow([
"docker start {$this->application->uuid}"
], hideFromOutput: true);
$this->executeNow([
"echo 'Done. 🎉'",
], isFinished: true);
return;
}
}
$this->executeNow([
$this->execute_in_builder("rm -fr {$this->workdir}/.git")
], hideFromOutput: true);
@ -173,14 +194,21 @@ public function handle(): void
$this->executeNow([
"echo 'Done. 🎉'",
"docker stop -t 0 {$this->deployment_uuid} >/dev/null"
], setStatus: true);
], isFinished: true);
// Saving docker-compose.yml
Storage::disk('deployments')->put(Str::kebab($this->application->name) . '/docker-compose.yml', $docker_compose);
// }
} catch (\Exception $e) {
$this->executeNow([
"echo 'Oops something is not okay, are you okay? 😢'",
"echo '\n\n{$e->getMessage()}'",
]);
throw new \Exception('Deployment finished');
} finally {
$this->executeNow(["docker rm -f {$this->deployment_uuid} >/dev/null 2>&1"], hideFromOutput: true);
dispatch(new ContainerStatusJob($this->application_uuid));
}
dispatch(new ContainerStatusJob($this->application_uuid));
// Saving docker-compose.yml
Storage::disk('deployments')->put(Str::kebab($this->application->name) . '/docker-compose.yml', $docker_compose);
}
private function execute_in_builder(string $command)
@ -314,8 +342,14 @@ private function set_labels_for_applications()
return $labels;
}
private function executeNow(array|Collection $command, string $propertyName = null, bool $hideFromOutput = false, $setStatus = false, bool $isDebuggable = false)
{
private function executeNow(
array|Collection $command,
string $propertyName = null,
bool $isFinished = false,
bool $hideFromOutput = false,
bool $isDebuggable = false,
bool $ignoreErrors = false
) {
static::$batch_counter++;
if ($command instanceof Collection) {
@ -334,16 +368,20 @@ private function executeNow(array|Collection $command, string $propertyName = nu
$remoteProcess = resolve(RunRemoteProcess::class, [
'activity' => $this->activity,
'hideFromOutput' => $hideFromOutput,
'setStatus' => $setStatus,
'isFinished' => $isFinished,
'ignoreErrors' => $ignoreErrors,
]);
$result = $remoteProcess();
if ($propertyName) {
$this->activity->properties = $this->activity->properties->merge([
$propertyName => trim($result->output()),
]);
$this->activity->save();
}
if ($result->exitCode() != 0 && $result->errorOutput() && !$ignoreErrors) {
throw new \RuntimeException($result->errorOutput());
}
}
private function gitImport()
{

View File

@ -1,6 +1,6 @@
FROM serversideup/php:8.2-fpm-nginx
ARG POSTGRES_VERSION=15
RUN apt-get update && apt-get install -y php-pgsql openssh-client git git-lfs
RUN apt-get update && apt-get install -y php-pgsql openssh-client git git-lfs postgresql-client
RUN apt-get -y autoremove \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* /usr/share/doc/*

View File

@ -1,3 +1,3 @@
/* @tailwind base;
/* @tailwind base; */
@tailwind components;
@tailwind utilities; */
@tailwind utilities;

View File

@ -0,0 +1,15 @@
<div>
<form class="flex flex-col">
<label>Name</label>
<input wire:model="name" type="text" name="name" />
<label>Fqdn</label>
<input wire:model="fqdn" type="text" name="fqdn" />
<label>Repository</label>
<input wire:model="git_repository" type="text" name="git_repository" />
<label>Branch</label>
<input wire:model="git_branch" type="text" name="git_branch" />
<label>Commit SHA</label>
<input wire:model="git_commit_sha" type="text" name="git_commit_sha" />
</form>
</div>

View File

@ -1,7 +1,7 @@
<x-layout>
<h1>Application</h1>
<p>Name: {{ $application->name }}</p>
<livewire:deploy-application :application_uuid="$application->uuid" />
<livewire:deploy-application :applicationId="$application->id" />
<livewire:application-form :applicationId="$application->id" />
<div>
<h2>Deployments</h2>
@foreach ($deployments as $deployment)