diff --git a/app/Actions/CoolifyTask/PrepareCoolifyTask.php b/app/Actions/CoolifyTask/PrepareCoolifyTask.php index 3b2f70014..b5b5a8853 100644 --- a/app/Actions/CoolifyTask/PrepareCoolifyTask.php +++ b/app/Actions/CoolifyTask/PrepareCoolifyTask.php @@ -39,7 +39,7 @@ class PrepareCoolifyTask public function __invoke(): Activity { - $job = new CoolifyTask($this->activity, ignore_errors: $this->remoteProcessArgs->ignore_errors); + $job = new CoolifyTask($this->activity, ignore_errors: $this->remoteProcessArgs->ignore_errors, call_event_on_finish: $this->remoteProcessArgs->call_event_on_finish); dispatch($job); $this->activity->refresh(); return $this->activity; diff --git a/app/Actions/CoolifyTask/RunRemoteProcess.php b/app/Actions/CoolifyTask/RunRemoteProcess.php index cdbf6813c..baf5406bd 100644 --- a/app/Actions/CoolifyTask/RunRemoteProcess.php +++ b/app/Actions/CoolifyTask/RunRemoteProcess.php @@ -21,6 +21,8 @@ class RunRemoteProcess public bool $ignore_errors; + public $call_event_on_finish = null; + protected $time_start; protected $current_time; @@ -34,7 +36,7 @@ class RunRemoteProcess /** * Create a new job instance. */ - public function __construct(Activity $activity, bool $hide_from_output = false, bool $is_finished = false, bool $ignore_errors = false) + public function __construct(Activity $activity, bool $hide_from_output = false, bool $is_finished = false, bool $ignore_errors = false, $call_event_on_finish = null) { if ($activity->getExtraProperty('type') !== ActivityTypes::INLINE->value) { @@ -45,6 +47,7 @@ class RunRemoteProcess $this->hide_from_output = $hide_from_output; $this->is_finished = $is_finished; $this->ignore_errors = $ignore_errors; + $this->call_event_on_finish = $call_event_on_finish; } public static function decodeOutput(?Activity $activity = null): string @@ -79,12 +82,18 @@ class RunRemoteProcess if ($this->activity->properties->get('status') === ProcessStatus::ERROR->value) { $status = ProcessStatus::ERROR; } else { - if (($processResult->exitCode() == 0 && $this->is_finished) || $this->activity->properties->get('status') === ProcessStatus::FINISHED->value) { + if ($processResult->exitCode() == 0 && $this->is_finished) { $status = ProcessStatus::FINISHED; } if ($processResult->exitCode() != 0 && !$this->ignore_errors) { $status = ProcessStatus::ERROR; } + // if (($processResult->exitCode() == 0 && $this->is_finished) || $this->activity->properties->get('status') === ProcessStatus::FINISHED->value) { + // $status = ProcessStatus::FINISHED; + // } + // if ($processResult->exitCode() != 0 && !$this->ignore_errors) { + // $status = ProcessStatus::ERROR; + // } } $this->activity->properties = $this->activity->properties->merge([ @@ -97,7 +106,16 @@ class RunRemoteProcess if ($processResult->exitCode() != 0 && !$this->ignore_errors) { throw new \RuntimeException($processResult->errorOutput(), $processResult->exitCode()); } - + if ($this->call_event_on_finish) { + try { + event(resolve("App\\Events\\$this->call_event_on_finish", [ + 'userId' => $this->activity->causer_id, + 'typeUuid' => $this->activity->getExtraProperty('type_uuid'), + ])); + } catch (\Throwable $e) { + ray($e); + } + } return $processResult; } diff --git a/app/Actions/Service/StartService.php b/app/Actions/Service/StartService.php index 3cd23ef85..e4b334dff 100644 --- a/app/Actions/Service/StartService.php +++ b/app/Actions/Service/StartService.php @@ -23,12 +23,12 @@ class StartService $commands[] = "echo 'Starting containers.'"; $commands[] = "docker compose up -d --remove-orphans --force-recreate --build"; $commands[] = "docker network connect $service->uuid coolify-proxy >/dev/null 2>&1 || true"; - $compose = data_get($service,'docker_compose',[]); - $serviceNames = data_get(Yaml::parse($compose),'services',[]); - foreach($serviceNames as $serviceName => $serviceConfig){ + $compose = data_get($service, 'docker_compose', []); + $serviceNames = data_get(Yaml::parse($compose), 'services', []); + foreach ($serviceNames as $serviceName => $serviceConfig) { $commands[] = "docker network connect --alias {$serviceName}-{$service->uuid} $network {$serviceName}-{$service->uuid} || true"; } - $activity = remote_process($commands, $service->server); + $activity = remote_process($commands, $service->server, type_uuid: $service->uuid, callEventOnFinish: 'ServiceStatusChanged'); return $activity; } } diff --git a/app/Data/CoolifyTaskArgs.php b/app/Data/CoolifyTaskArgs.php index f73fd6318..584fadb98 100644 --- a/app/Data/CoolifyTaskArgs.php +++ b/app/Data/CoolifyTaskArgs.php @@ -19,6 +19,7 @@ class CoolifyTaskArgs extends Data public ?Model $model = null, public ?string $status = null , public bool $ignore_errors = false, + public $call_event_on_finish = null, ) { if(is_null($status)){ $this->status = ProcessStatus::QUEUED->value; diff --git a/app/Events/ServiceStatusChanged.php b/app/Events/ServiceStatusChanged.php new file mode 100644 index 000000000..34df1b711 --- /dev/null +++ b/app/Events/ServiceStatusChanged.php @@ -0,0 +1,28 @@ +userId = $userId; + } + + public function broadcastOn(): array + { + return [ + new PrivateChannel("custom.{$this->userId}"), + ]; + } +} diff --git a/app/Jobs/CoolifyTask.php b/app/Jobs/CoolifyTask.php index 3ea32c27a..77d453ae2 100755 --- a/app/Jobs/CoolifyTask.php +++ b/app/Jobs/CoolifyTask.php @@ -21,6 +21,7 @@ class CoolifyTask implements ShouldQueue, ShouldBeEncrypted public function __construct( public Activity $activity, public bool $ignore_errors = false, + public $call_event_on_finish = null ) { } @@ -32,6 +33,7 @@ class CoolifyTask implements ShouldQueue, ShouldBeEncrypted $remote_process = resolve(RunRemoteProcess::class, [ 'activity' => $this->activity, 'ignore_errors' => $this->ignore_errors, + 'call_event_on_finish' => $this->call_event_on_finish ]); $remote_process(); diff --git a/app/Livewire/Modal/EditCompose.php b/app/Livewire/Modal/EditCompose.php index e5222404f..f2804e5ac 100644 --- a/app/Livewire/Modal/EditCompose.php +++ b/app/Livewire/Modal/EditCompose.php @@ -3,7 +3,6 @@ namespace App\Livewire\Modal; use App\Models\Service; -use Livewire\Component; use LivewireUI\Modal\ModalComponent; class EditCompose extends ModalComponent diff --git a/app/Livewire/Project/New/Select.php b/app/Livewire/Project/New/Select.php index e083642b0..ed55553df 100644 --- a/app/Livewire/Project/New/Select.php +++ b/app/Livewire/Project/New/Select.php @@ -133,13 +133,13 @@ class Select extends Component public function setDestination(string $destination_uuid) { $this->destination_uuid = $destination_uuid; - return $this->redirectRoute('project.resources.new', [ + return redirect()->route('project.resources.new', [ 'project_uuid' => $this->parameters['project_uuid'], 'environment_name' => $this->parameters['environment_name'], 'type' => $this->type, 'destination' => $this->destination_uuid, 'server_id' => $this->server_id, - ], navigate: true); + ]); } public function loadServers() diff --git a/app/Livewire/Project/Service/Index.php b/app/Livewire/Project/Service/Index.php index a798ca734..4f3f9ce11 100644 --- a/app/Livewire/Project/Service/Index.php +++ b/app/Livewire/Project/Service/Index.php @@ -13,7 +13,15 @@ class Index extends Component public $databases; public array $parameters; public array $query; - protected $listeners = ["refreshStacks", "checkStatus"]; + public function getListeners() + { + $userId = auth()->user()->id; + return [ + "echo-private:custom.{$userId},ServiceStatusChanged" => 'checkStatus', + "refreshStacks", + "checkStatus", + ]; + } public function render() { return view('livewire.project.service.index'); @@ -28,7 +36,7 @@ class Index extends Component } public function checkStatus() { - dispatch(new ContainerStatusJob($this->service->server)); + dispatch_sync(new ContainerStatusJob($this->service->server)); $this->refreshStacks(); } public function refreshStacks() diff --git a/app/Livewire/Project/Service/Modal.php b/app/Livewire/Project/Service/Modal.php index eeeeba7e9..653425835 100644 --- a/app/Livewire/Project/Service/Modal.php +++ b/app/Livewire/Project/Service/Modal.php @@ -6,9 +6,6 @@ use Livewire\Component; class Modal extends Component { - public function checkStatus() { - $this->dispatch('checkStatus'); - } public function render() { return view('livewire.project.service.modal'); diff --git a/app/Livewire/Project/Service/Navbar.php b/app/Livewire/Project/Service/Navbar.php index 2457ecaa8..0fe5e6bd9 100644 --- a/app/Livewire/Project/Service/Navbar.php +++ b/app/Livewire/Project/Service/Navbar.php @@ -4,25 +4,53 @@ namespace App\Livewire\Project\Service; use App\Actions\Service\StartService; use App\Actions\Service\StopService; +use App\Jobs\ContainerStatusJob; use App\Models\Service; use Livewire\Component; +use Spatie\Activitylog\Models\Activity; class Navbar extends Component { public Service $service; public array $parameters; public array $query; - protected $listeners = ["checkStatus"]; + public $isDeploymentProgress = false; + public function checkDeployments() { + $activity = Activity::where('properties->type_uuid', $this->service->uuid)->latest()->first(); + $status = data_get($activity, 'properties.status'); + if ($status === 'queued' || $status === 'in_progress') { + $this->isDeploymentProgress = true; + } else { + $this->isDeploymentProgress = false; + } + } + public function getListeners() + { + $userId = auth()->user()->id; + return [ + "echo-private:custom.{$userId},ServiceStatusChanged" => 'serviceStatusChanged', + ]; + } + public function serviceStatusChanged() + { + $this->service->refresh(); + } public function render() { return view('livewire.project.service.navbar'); } - public function checkStatus() { + public function checkStatus() + { $this->service->refresh(); } public function deploy() { + $this->checkDeployments(); + if ($this->isDeploymentProgress) { + $this->dispatch('error', 'There is a deployment in progress.'); + return; + } $this->service->parse(); $activity = StartService::run($this->service); $this->dispatch('newMonitorActivity', $activity->id); diff --git a/app/Livewire/Sponsorship.php b/app/Livewire/Sponsorship.php index 992498d79..e38f04d27 100644 --- a/app/Livewire/Sponsorship.php +++ b/app/Livewire/Sponsorship.php @@ -8,12 +8,12 @@ class Sponsorship extends Component { public function getListeners() { - $teamId = auth()->user()->currentTeam()->id; + $userId = auth()->user()->id; return [ - "echo-private:custom.{$teamId},TestEvent" => 'testEvent', + "echo-private:custom.{$userId},TestEvent" => 'testEvent', ]; } - public function testEvent() + public function testEvent($asd) { $this->dispatch('success', 'Realtime events configured!'); } diff --git a/app/Models/Service.php b/app/Models/Service.php index 8b7202a65..b7fd6b07e 100644 --- a/app/Models/Service.php +++ b/app/Models/Service.php @@ -5,7 +5,6 @@ namespace App\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Support\Collection; -use Symfony\Component\Yaml\Yaml; use Illuminate\Support\Str; class Service extends BaseModel @@ -207,7 +206,6 @@ class Service extends BaseModel break; } } - ray($fields); $databases = $this->databases()->get(); foreach ($databases as $database) { diff --git a/bootstrap/helpers/remoteProcess.php b/bootstrap/helpers/remoteProcess.php index 2fe90415e..91e42c5be 100644 --- a/bootstrap/helpers/remoteProcess.php +++ b/bootstrap/helpers/remoteProcess.php @@ -24,6 +24,7 @@ function remote_process( ?string $type_uuid = null, ?Model $model = null, bool $ignore_errors = false, + $callEventOnFinish = null ): Activity { if (is_null($type)) { $type = ActivityTypes::INLINE->value; @@ -47,18 +48,12 @@ function remote_process( type: $type, type_uuid: $type_uuid, model: $model, - ignore_errors: $ignore_errors + ignore_errors: $ignore_errors, + call_event_on_finish: $callEventOnFinish, ), ])(); } -// function removePrivateKeyFromSshAgent(Server $server) -// { -// if (data_get($server, 'privateKey.private_key') === null) { -// throw new \Exception("Server {$server->name} does not have a private key"); -// } -// // processWithEnv()->run("echo '{$server->privateKey->private_key}' | ssh-add -d -"); -// } function savePrivateKeyToFs(Server $server) { if (data_get($server, 'privateKey.private_key') === null) { diff --git a/resources/views/livewire/project/service/modal.blade.php b/resources/views/livewire/project/service/modal.blade.php index 2333379d0..59888f0d1 100644 --- a/resources/views/livewire/project/service/modal.blade.php +++ b/resources/views/livewire/project/service/modal.blade.php @@ -1,5 +1,5 @@
- + diff --git a/routes/web.php b/routes/web.php index 8578282b9..1d46c4a83 100644 --- a/routes/web.php +++ b/routes/web.php @@ -48,7 +48,7 @@ Route::get('/api/v1/test/realtime', function () { if (auth()->user()?->currentTeam()->id !== 0) { return redirect('/'); } - event(new \App\Events\TestEvent()); + event(new \App\Events\TestEvent('asd')); return 'Look at your other tab.'; })->middleware('auth');