logs ot fixes in executeNow.
errors handled properly, etc.
This commit is contained in:
parent
14919980c2
commit
46a543441f
3
.gitignore
vendored
3
.gitignore
vendored
@ -20,3 +20,6 @@ yarn-error.log
|
||||
/.npm
|
||||
/.bash_history
|
||||
/_volumes
|
||||
|
||||
.lesshst
|
||||
psysh_history
|
||||
|
@ -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()) {
|
||||
|
29
app/Http/Livewire/ApplicationForm.php
Normal file
29
app/Http/Livewire/ApplicationForm.php
Normal 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,
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
@ -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();
|
||||
|
@ -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()
|
||||
{
|
||||
|
@ -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/*
|
||||
|
@ -1,3 +1,3 @@
|
||||
/* @tailwind base;
|
||||
/* @tailwind base; */
|
||||
@tailwind components;
|
||||
@tailwind utilities; */
|
||||
@tailwind utilities;
|
||||
|
15
resources/views/livewire/application-form.blade.php
Normal file
15
resources/views/livewire/application-form.blade.php
Normal 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>
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user