diff --git a/app/Console/Commands/ServicesGenerate.php b/app/Console/Commands/ServicesGenerate.php index 802b3180f..75df4756b 100644 --- a/app/Console/Commands/ServicesGenerate.php +++ b/app/Console/Commands/ServicesGenerate.php @@ -73,6 +73,18 @@ private function process_file($file) } else { $slogan = str($file)->headline()->value(); } + $logo = collect(preg_grep('/^# logo:/', explode("\n", $content)))->values(); + if ($logo->count() > 0) { + $logo = str($logo[0])->after('# logo:')->trim()->value(); + } else { + $logo = 'svgs/unknown.svg'; + } + $minversion = collect(preg_grep('/^# minversion:/', explode("\n", $content)))->values(); + if ($minversion->count() > 0) { + $minversion = str($minversion[0])->after('# minversion:')->trim()->value(); + } else { + $minversion = '0.0.0'; + } $env_file = collect(preg_grep('/^# env_file:/', explode("\n", $content)))->values(); if ($env_file->count() > 0) { $env_file = str($env_file[0])->after('# env_file:')->trim()->value(); @@ -96,6 +108,8 @@ private function process_file($file) 'slogan' => $slogan, 'compose' => $yaml, 'tags' => $tags, + 'logo' => $logo, + 'minversion' => $minversion, ]; if ($env_file) { $env_file_content = file_get_contents(base_path("templates/compose/$env_file")); diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php index bba2da818..76fcbfc1f 100644 --- a/app/Console/Kernel.php +++ b/app/Console/Kernel.php @@ -4,7 +4,6 @@ use App\Jobs\CheckLogDrainContainerJob; use App\Jobs\CleanupInstanceStuffsJob; -use App\Jobs\ComplexContainerStatusJob; use App\Jobs\DatabaseBackupJob; use App\Jobs\ScheduledTaskJob; use App\Jobs\InstanceAutoUpdateJob; diff --git a/app/Jobs/ApplicationDeploymentJob.php b/app/Jobs/ApplicationDeploymentJob.php index e135188a7..f3e8c4129 100644 --- a/app/Jobs/ApplicationDeploymentJob.php +++ b/app/Jobs/ApplicationDeploymentJob.php @@ -66,6 +66,7 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted private Server $mainServer; private ?ApplicationPreview $preview = null; private ?string $git_type = null; + private bool $only_this_server = false; private string $container_name; private ?string $currently_running_container_name = null; @@ -115,6 +116,7 @@ public function __construct(int $application_deployment_queue_id) $this->commit = $this->application_deployment_queue->commit; $this->force_rebuild = $this->application_deployment_queue->force_rebuild; $this->restart_only = $this->application_deployment_queue->restart_only; + $this->only_this_server = $this->application_deployment_queue->only_this_server; $this->git_type = data_get($this->application_deployment_queue, 'git_type'); @@ -331,7 +333,11 @@ private function deploy_simple_dockerfile() private function deploy_dockerimage_buildpack() { $this->dockerImage = $this->application->docker_registry_image_name; - $this->dockerImageTag = $this->application->docker_registry_image_tag; + if (str($this->application->docker_registry_image_tag)->isEmpty()) { + $this->dockerImageTag = 'latest'; + } else { + $this->dockerImageTag = $this->application->docker_registry_image_tag; + } ray("echo 'Starting deployment of {$this->dockerImage}:{$this->dockerImageTag} to {$this->server->name}.'"); $this->application_deployment_queue->addLogEntry("Starting deployment of {$this->dockerImage}:{$this->dockerImageTag} to {$this->server->name}."); $this->generate_image_names(); @@ -887,7 +893,7 @@ private function deploy_to_additional_destinations() destination: $destination, no_questions_asked: true, ); - $this->application_deployment_queue->addLogEntry("Deploying to additional server: {$server->name}. Click here to see the deployment status: " . route('project.application.deployment.show', [ + $this->application_deployment_queue->addLogEntry("Deployment to {$server->name}. Logs: " . route('project.application.deployment.show', [ 'project_uuid' => data_get($this->application, 'environment.project.uuid'), 'application_uuid' => data_get($this->application, 'uuid'), 'deployment_uuid' => $deployment_uuid, @@ -1619,7 +1625,9 @@ private function next(string $status) return; } if ($status === ApplicationDeploymentStatus::FINISHED->value) { - $this->deploy_to_additional_destinations(); + if (!$this->only_this_server) { + $this->deploy_to_additional_destinations(); + } $this->application->environment->project->team?->notify(new DeploymentSuccess($this->application, $this->deployment_uuid, $this->preview)); } } diff --git a/app/Jobs/ContainerStatusJob.php b/app/Jobs/ContainerStatusJob.php index 1612e2191..fbdd555a1 100644 --- a/app/Jobs/ContainerStatusJob.php +++ b/app/Jobs/ContainerStatusJob.php @@ -44,17 +44,19 @@ public function uniqueId(): int public function handle() { $applications = $this->server->applications(); + $skip_these_applications = collect([]); foreach ($applications as $application) { if ($application->additional_servers->count() > 0) { - $is_main_server = $application->destination->server->id === $this->server->id; - if ($is_main_server) { - ComplexStatusCheck::run($application); - $applications = $applications->filter(function ($value, $key) use ($application) { - return $value->id !== $application->id; - }); - } + $skip_these_applications->push($application); + ComplexStatusCheck::run($application); + $applications = $applications->filter(function ($value, $key) use ($application) { + return $value->id !== $application->id; + }); } } + $applications = $applications->filter(function ($value, $key) use ($skip_these_applications) { + return !$skip_these_applications->pluck('id')->contains($value->id); + }); if (!$this->server->isFunctional()) { return 'Server is not ready.'; diff --git a/app/Jobs/GithubAppPermissionJob.php b/app/Jobs/GithubAppPermissionJob.php new file mode 100644 index 000000000..deb414a13 --- /dev/null +++ b/app/Jobs/GithubAppPermissionJob.php @@ -0,0 +1,59 @@ +github_app->uuid))]; + } + + public function uniqueId(): int + { + return $this->github_app->uuid; + } + + public function handle() + { + try { + $github_access_token = generate_github_jwt_token($this->github_app); + $response = Http::withHeaders([ + 'Authorization' => "Bearer $github_access_token", + 'Accept' => 'application/vnd.github+json' + ])->get("{$this->github_app->api_url}/app"); + $response = $response->json(); + $permissions = data_get($response, 'permissions'); + $this->github_app->contents = data_get($permissions, 'contents'); + $this->github_app->metadata = data_get($permissions, 'metadata'); + $this->github_app->pull_requests = data_get($permissions, 'pull_requests'); + $this->github_app->administration = data_get($permissions, 'administration'); + $this->github_app->save(); + $this->github_app->makeVisible('client_secret')->makeVisible('webhook_secret'); + } catch (\Throwable $e) { + send_internal_notification('GithubAppPermissionJob failed with: ' . $e->getMessage()); + ray($e->getMessage()); + throw $e; + } + } +} diff --git a/app/Livewire/Notifications/EmailSettings.php b/app/Livewire/Notifications/EmailSettings.php index cdbaef051..b6152907d 100644 --- a/app/Livewire/Notifications/EmailSettings.php +++ b/app/Livewire/Notifications/EmailSettings.php @@ -63,7 +63,7 @@ public function submitFromFields() ]); $this->team->save(); refreshSession(); - $this->dispatch('success', 'Settings saved successfully.'); + $this->dispatch('success', 'Settings saved.'); } catch (\Throwable $e) { return handleError($e, $this); } @@ -71,7 +71,7 @@ public function submitFromFields() public function sendTestNotification() { $this->team?->notify(new Test($this->emails)); - $this->dispatch('success', 'Test Email sent successfully.'); + $this->dispatch('success', 'Test Email sent.'); } public function instantSaveInstance() { @@ -83,7 +83,7 @@ public function instantSaveInstance() $this->team->resend_enabled = false; $this->team->save(); refreshSession(); - $this->dispatch('success', 'Settings saved successfully.'); + $this->dispatch('success', 'Settings saved.'); } catch (\Throwable $e) { return handleError($e, $this); } @@ -131,7 +131,7 @@ public function submit() ]); $this->team->save(); refreshSession(); - $this->dispatch('success', 'Settings saved successfully.'); + $this->dispatch('success', 'Settings saved.'); } catch (\Throwable $e) { $this->team->smtp_enabled = false; return handleError($e, $this); @@ -148,7 +148,7 @@ public function submitResend() ]); $this->team->save(); refreshSession(); - $this->dispatch('success', 'Settings saved successfully.'); + $this->dispatch('success', 'Settings saved.'); } catch (\Throwable $e) { $this->team->resend_enabled = false; return handleError($e, $this); diff --git a/app/Livewire/Profile/Index.php b/app/Livewire/Profile/Index.php index 0a2a34766..3499d4ff9 100644 --- a/app/Livewire/Profile/Index.php +++ b/app/Livewire/Profile/Index.php @@ -27,7 +27,7 @@ public function submit() 'name' => $this->name, ]); - $this->dispatch('success', 'Profile updated successfully.'); + $this->dispatch('success', 'Profile updated'); } catch (\Throwable $e) { return handleError($e, $this); } diff --git a/app/Livewire/Project/Application/General.php b/app/Livewire/Project/Application/General.php index 732be62d0..37b650281 100644 --- a/app/Livewire/Project/Application/General.php +++ b/app/Livewire/Project/Application/General.php @@ -232,7 +232,6 @@ public function submit($showToaster = true) if (data_get($this->application, 'build_pack') === 'dockerimage') { $this->validate([ 'application.docker_registry_image_name' => 'required', - 'application.docker_registry_image_tag' => 'required', ]); } if (data_get($this->application, 'fqdn')) { diff --git a/app/Livewire/Project/Application/Heading.php b/app/Livewire/Project/Application/Heading.php index 01ab13c4e..3047f9f23 100644 --- a/app/Livewire/Project/Application/Heading.php +++ b/app/Livewire/Project/Application/Heading.php @@ -33,15 +33,11 @@ public function check_status($showNotification = false) { if ($this->application->destination->server->isFunctional()) { dispatch(new ContainerStatusJob($this->application->destination->server)); - // $this->application->refresh(); - // $this->application->previews->each(function ($preview) { - // $preview->refresh(); - // }); } else { dispatch(new ServerStatusJob($this->application->destination->server)); } - if ($showNotification) $this->dispatch('success', "Application status updated."); + if ($showNotification) $this->dispatch('success', "Success", "Application status updated."); } public function force_deploy_without_cache() diff --git a/app/Livewire/Project/Application/Preview/Form.php b/app/Livewire/Project/Application/Preview/Form.php index 0da8b1d76..6826e154b 100644 --- a/app/Livewire/Project/Application/Preview/Form.php +++ b/app/Livewire/Project/Application/Preview/Form.php @@ -46,7 +46,7 @@ public function submit() $this->validate(); $this->application->preview_url_template = str_replace(' ', '', $this->application->preview_url_template); $this->application->save(); - $this->dispatch('success', 'Preview url template updated successfully.'); + $this->dispatch('success', 'Preview url template updated.'); $this->generate_real_url(); } } diff --git a/app/Livewire/Project/Database/BackupExecutions.php b/app/Livewire/Project/Database/BackupExecutions.php index f1918f990..c78a8cbee 100644 --- a/app/Livewire/Project/Database/BackupExecutions.php +++ b/app/Livewire/Project/Database/BackupExecutions.php @@ -33,7 +33,7 @@ public function deleteBackup($exeuctionId) delete_backup_locally($execution->filename, $execution->scheduledDatabaseBackup->database->destination->server); } $execution->delete(); - $this->dispatch('success', 'Backup deleted successfully.'); + $this->dispatch('success', 'Backup deleted.'); $this->dispatch('refreshBackupExecutions'); } public function download($exeuctionId) diff --git a/app/Livewire/Project/Database/Mariadb/General.php b/app/Livewire/Project/Database/Mariadb/General.php index 305633cba..9b15c6c3c 100644 --- a/app/Livewire/Project/Database/Mariadb/General.php +++ b/app/Livewire/Project/Database/Mariadb/General.php @@ -59,7 +59,7 @@ public function instantSaveAdvanced() { return; } $this->database->save(); - $this->dispatch('success', 'Database updated successfully.'); + $this->dispatch('success', 'Database updated.'); $this->dispatch('success', 'You need to restart the service for the changes to take effect.'); } catch (Exception $e) { return handleError($e, $this); @@ -73,7 +73,7 @@ public function submit() } $this->validate(); $this->database->save(); - $this->dispatch('success', 'Database updated successfully.'); + $this->dispatch('success', 'Database updated.'); } catch (Exception $e) { return handleError($e, $this); } diff --git a/app/Livewire/Project/Database/Mongodb/General.php b/app/Livewire/Project/Database/Mongodb/General.php index 70f54cc3f..cd3ea0630 100644 --- a/app/Livewire/Project/Database/Mongodb/General.php +++ b/app/Livewire/Project/Database/Mongodb/General.php @@ -58,7 +58,7 @@ public function instantSaveAdvanced() return; } $this->database->save(); - $this->dispatch('success', 'Database updated successfully.'); + $this->dispatch('success', 'Database updated.'); $this->dispatch('success', 'You need to restart the service for the changes to take effect.'); } catch (Exception $e) { return handleError($e, $this); @@ -75,7 +75,7 @@ public function submit() } $this->validate(); $this->database->save(); - $this->dispatch('success', 'Database updated successfully.'); + $this->dispatch('success', 'Database updated.'); } catch (Exception $e) { return handleError($e, $this); } diff --git a/app/Livewire/Project/Database/Mysql/General.php b/app/Livewire/Project/Database/Mysql/General.php index 98b16a112..2470a934b 100644 --- a/app/Livewire/Project/Database/Mysql/General.php +++ b/app/Livewire/Project/Database/Mysql/General.php @@ -60,7 +60,7 @@ public function instantSaveAdvanced() return; } $this->database->save(); - $this->dispatch('success', 'Database updated successfully.'); + $this->dispatch('success', 'Database updated.'); $this->dispatch('success', 'You need to restart the service for the changes to take effect.'); } catch (Exception $e) { return handleError($e, $this); @@ -74,7 +74,7 @@ public function submit() } $this->validate(); $this->database->save(); - $this->dispatch('success', 'Database updated successfully.'); + $this->dispatch('success', 'Database updated.'); } catch (Exception $e) { return handleError($e, $this); } diff --git a/app/Livewire/Project/Database/Postgresql/General.php b/app/Livewire/Project/Database/Postgresql/General.php index 6fa5df97c..43f559140 100644 --- a/app/Livewire/Project/Database/Postgresql/General.php +++ b/app/Livewire/Project/Database/Postgresql/General.php @@ -66,7 +66,7 @@ public function instantSaveAdvanced() { return; } $this->database->save(); - $this->dispatch('success', 'Database updated successfully.'); + $this->dispatch('success', 'Database updated.'); $this->dispatch('success', 'You need to restart the service for the changes to take effect.'); } catch (Exception $e) { return handleError($e, $this); @@ -105,7 +105,7 @@ public function save_init_script($script) $this->database->init_scripts = filter($this->database->init_scripts, fn ($s) => $s['filename'] !== $script['filename']); $this->database->init_scripts = array_merge($this->database->init_scripts, [$script]); $this->database->save(); - $this->dispatch('success', 'Init script saved successfully.'); + $this->dispatch('success', 'Init script saved.'); } public function delete_init_script($script) @@ -116,7 +116,7 @@ public function delete_init_script($script) $this->database->init_scripts = $collection->filter(fn ($s) => $s['filename'] !== $script['filename'])->toArray(); $this->database->save(); $this->refresh(); - $this->dispatch('success', 'Init script deleted successfully.'); + $this->dispatch('success', 'Init script deleted.'); return; } } @@ -148,7 +148,7 @@ public function save_new_init_script() ] ]); $this->database->save(); - $this->dispatch('success', 'Init script added successfully.'); + $this->dispatch('success', 'Init script added.'); $this->new_content = ''; $this->new_filename = ''; } @@ -161,7 +161,7 @@ public function submit() } $this->validate(); $this->database->save(); - $this->dispatch('success', 'Database updated successfully.'); + $this->dispatch('success', 'Database updated.'); } catch (Exception $e) { return handleError($e, $this); } diff --git a/app/Livewire/Project/Database/Redis/General.php b/app/Livewire/Project/Database/Redis/General.php index c328a6195..07c161de5 100644 --- a/app/Livewire/Project/Database/Redis/General.php +++ b/app/Livewire/Project/Database/Redis/General.php @@ -52,7 +52,7 @@ public function instantSaveAdvanced() { return; } $this->database->save(); - $this->dispatch('success', 'Database updated successfully.'); + $this->dispatch('success', 'Database updated.'); $this->dispatch('success', 'You need to restart the service for the changes to take effect.'); } catch (Exception $e) { return handleError($e, $this); @@ -66,7 +66,7 @@ public function submit() $this->database->redis_conf = null; } $this->database->save(); - $this->dispatch('success', 'Database updated successfully.'); + $this->dispatch('success', 'Database updated.'); } catch (Exception $e) { return handleError($e, $this); } diff --git a/app/Livewire/Project/Database/ScheduledBackups.php b/app/Livewire/Project/Database/ScheduledBackups.php index 2fc4d069e..399fddac4 100644 --- a/app/Livewire/Project/Database/ScheduledBackups.php +++ b/app/Livewire/Project/Database/ScheduledBackups.php @@ -38,7 +38,7 @@ public function setSelectedBackup($backupId) { public function delete($scheduled_backup_id): void { $this->database->scheduledBackups->find($scheduled_backup_id)->delete(); - $this->dispatch('success', 'Scheduled backup deleted successfully.'); + $this->dispatch('success', 'Scheduled backup deleted.'); $this->refreshScheduledBackups(); } diff --git a/app/Livewire/Project/New/Select.php b/app/Livewire/Project/New/Select.php index 1c49ac7ad..8178590a3 100644 --- a/app/Livewire/Project/New/Select.php +++ b/app/Livewire/Project/New/Select.php @@ -71,10 +71,10 @@ public function updatedSelectedEnvironment() // } // } - public function loadServices() + public function loadServices(bool $force = false) { try { - if (count($this->allServices) > 0) { + if (count($this->allServices) > 0 && !$force) { if (!$this->search) { $this->services = $this->allServices; return; diff --git a/app/Livewire/Project/Service/Database.php b/app/Livewire/Project/Service/Database.php index e7be1ff2e..8dec97852 100644 --- a/app/Livewire/Project/Service/Database.php +++ b/app/Livewire/Project/Service/Database.php @@ -77,7 +77,7 @@ public function submit() $this->validate(); $this->database->save(); updateCompose($this->database); - $this->dispatch('success', 'Database saved successfully.'); + $this->dispatch('success', 'Database saved.'); } catch (\Throwable $e) { ray($e); } finally { diff --git a/app/Livewire/Project/Service/FileStorage.php b/app/Livewire/Project/Service/FileStorage.php index da85a1a6e..2abfcdf5e 100644 --- a/app/Livewire/Project/Service/FileStorage.php +++ b/app/Livewire/Project/Service/FileStorage.php @@ -42,7 +42,7 @@ public function submit() } $this->fileStorage->save(); $this->fileStorage->saveStorageOnServer(); - $this->dispatch('success', 'File updated successfully.'); + $this->dispatch('success', 'File updated.'); } catch (\Throwable $e) { $this->fileStorage->setRawAttributes($original); $this->fileStorage->save(); diff --git a/app/Livewire/Project/Service/Navbar.php b/app/Livewire/Project/Service/Navbar.php index 2eb9f938c..fda86321b 100644 --- a/app/Livewire/Project/Service/Navbar.php +++ b/app/Livewire/Project/Service/Navbar.php @@ -64,9 +64,9 @@ public function stop(bool $forceCleanup = false) StopService::run($this->service); $this->service->refresh(); if ($forceCleanup) { - $this->dispatch('success', 'Force cleanup service successfully.'); + $this->dispatch('success', 'Force cleanup service.'); } else { - $this->dispatch('success', 'Service stopped successfully.'); + $this->dispatch('success', 'Service stopped.'); } ServiceStatusChanged::dispatch(); } diff --git a/app/Livewire/Project/Service/ServiceApplicationView.php b/app/Livewire/Project/Service/ServiceApplicationView.php index 53532a855..2bae41a80 100644 --- a/app/Livewire/Project/Service/ServiceApplicationView.php +++ b/app/Livewire/Project/Service/ServiceApplicationView.php @@ -41,7 +41,7 @@ public function delete() { try { $this->application->delete(); - $this->dispatch('success', 'Application deleted successfully.'); + $this->dispatch('success', 'Application deleted.'); return redirect()->route('project.service.configuration', $this->parameters); } catch (\Throwable $e) { return handleError($e, $this); @@ -58,7 +58,7 @@ public function submit() $this->validate(); $this->application->save(); updateCompose($this->application); - $this->dispatch('success', 'Application saved successfully.'); + $this->dispatch('success', 'Application saved.'); } catch (\Throwable $e) { return handleError($e, $this); } finally { diff --git a/app/Livewire/Project/Service/StackForm.php b/app/Livewire/Project/Service/StackForm.php index 44672fe64..1ec63a761 100644 --- a/app/Livewire/Project/Service/StackForm.php +++ b/app/Livewire/Project/Service/StackForm.php @@ -48,7 +48,7 @@ public function saveCompose($raw) public function instantSave() { $this->service->save(); - $this->dispatch('success', 'Service settings saved successfully.'); + $this->dispatch('success', 'Service settings saved.'); } public function submit() @@ -62,7 +62,7 @@ public function submit() $this->service->saveComposeConfigs(); $this->dispatch('refreshStacks'); $this->dispatch('refreshEnvs'); - $this->dispatch('success', 'Service saved successfully.'); + $this->dispatch('success', 'Service saved.'); } catch (\Throwable $e) { return handleError($e, $this); } diff --git a/app/Livewire/Project/Shared/Destination.php b/app/Livewire/Project/Shared/Destination.php index 6981886bf..787b9da20 100644 --- a/app/Livewire/Project/Shared/Destination.php +++ b/app/Livewire/Project/Shared/Destination.php @@ -4,6 +4,7 @@ use App\Actions\Application\StopApplicationOneServer; use App\Events\ApplicationStatusChanged; +use App\Jobs\ContainerStatusJob; use App\Models\Server; use App\Models\StandaloneDocker; use Livewire\Component; @@ -40,6 +41,17 @@ public function loadData() $this->networks = $this->networks->reject(function ($network) { return $this->resource->destination->server->id == $network->server->id; }); + if ($this->resource?->additional_servers?->count() > 0) { + $this->networks = $this->networks->reject(function ($network) { + return $this->resource->additional_servers->pluck('id')->contains($network->server->id); + }); + } + } + public function stop(int $server_id) + { + $server = Server::find($server_id); + StopApplicationOneServer::run($this->resource, $server); + $this->refreshServers(); } public function redeploy(int $network_id, int $server_id) { @@ -55,6 +67,7 @@ public function redeploy(int $network_id, int $server_id) application: $this->resource, server: $server, destination: $destination, + only_this_server: true, no_questions_asked: true, ); return redirect()->route('project.application.deployment.show', [ @@ -64,12 +77,29 @@ public function redeploy(int $network_id, int $server_id) 'environment_name' => data_get($this->resource, 'environment.name'), ]); } + public function promote(int $network_id, int $server_id) + { + $main_destination = $this->resource->destination; + $this->resource->update([ + 'destination_id' => $network_id, + 'destination_type' => StandaloneDocker::class, + ]); + $this->resource->additional_networks()->detach($network_id, ['server_id' => $server_id]); + $this->resource->additional_networks()->attach($main_destination->id, ['server_id' => $main_destination->server->id]); + $this->refreshServers(); + } + public function refreshServers() + { + ContainerStatusJob::dispatchSync($this->resource->destination->server); + $this->loadData(); + $this->dispatch('refresh'); + ApplicationStatusChanged::dispatch(data_get($this->resource, 'environment.project.team.id')); + } public function addServer(int $network_id, int $server_id) { $this->resource->additional_networks()->attach($network_id, ['server_id' => $server_id]); - $this->resource->load(['additional_networks']); - ApplicationStatusChanged::dispatch(data_get($this->resource, 'environment.project.team.id')); $this->loadData(); + ApplicationStatusChanged::dispatch(data_get($this->resource, 'environment.project.team.id')); } public function removeServer(int $network_id, int $server_id) { @@ -80,8 +110,7 @@ public function removeServer(int $network_id, int $server_id) $server = Server::find($server_id); StopApplicationOneServer::run($this->resource, $server); $this->resource->additional_networks()->detach($network_id, ['server_id' => $server_id]); - $this->resource->load(['additional_networks']); - ApplicationStatusChanged::dispatch(data_get($this->resource, 'environment.project.team.id')); $this->loadData(); + ApplicationStatusChanged::dispatch(data_get($this->resource, 'environment.project.team.id')); } } diff --git a/app/Livewire/Project/Shared/EnvironmentVariable/All.php b/app/Livewire/Project/Shared/EnvironmentVariable/All.php index 28aac7ce3..3a304d3e9 100644 --- a/app/Livewire/Project/Shared/EnvironmentVariable/All.php +++ b/app/Livewire/Project/Shared/EnvironmentVariable/All.php @@ -120,9 +120,9 @@ public function saveVariables($isPreview) } } if ($isPreview) { - $this->dispatch('success', 'Preview environment variables updated successfully.'); + $this->dispatch('success', 'Preview environment variables updated.'); } else { - $this->dispatch('success', 'Environment variables updated successfully.'); + $this->dispatch('success', 'Environment variables updated.'); } $this->refreshEnvs(); } diff --git a/app/Livewire/Project/Shared/EnvironmentVariable/Show.php b/app/Livewire/Project/Shared/EnvironmentVariable/Show.php index 1494707e7..9252c44f8 100644 --- a/app/Livewire/Project/Shared/EnvironmentVariable/Show.php +++ b/app/Livewire/Project/Shared/EnvironmentVariable/Show.php @@ -90,7 +90,7 @@ public function submit() } $this->serialize(); $this->env->save(); - $this->dispatch('success', 'Environment variable updated successfully.'); + $this->dispatch('success', 'Environment variable updated.'); $this->dispatch('refreshEnvs'); } catch (\Exception $e) { return handleError($e); diff --git a/app/Livewire/Project/Shared/ResourceLimits.php b/app/Livewire/Project/Shared/ResourceLimits.php index 8b010530c..a326a9a0b 100644 --- a/app/Livewire/Project/Shared/ResourceLimits.php +++ b/app/Livewire/Project/Shared/ResourceLimits.php @@ -52,7 +52,7 @@ public function submit() } $this->validate(); $this->resource->save(); - $this->dispatch('success', 'Resource limits updated successfully.'); + $this->dispatch('success', 'Resource limits updated.'); } catch (\Throwable $e) { return handleError($e, $this); } diff --git a/app/Livewire/Project/Shared/ScheduledTask/All.php b/app/Livewire/Project/Shared/ScheduledTask/All.php index 4a876e72a..975d695fa 100644 --- a/app/Livewire/Project/Shared/ScheduledTask/All.php +++ b/app/Livewire/Project/Shared/ScheduledTask/All.php @@ -48,7 +48,7 @@ public function submit($data) } $task->save(); $this->refreshTasks(); - $this->dispatch('success', 'Scheduled task added successfully.'); + $this->dispatch('success', 'Scheduled task added.'); } catch (\Throwable $e) { return handleError($e, $this); } diff --git a/app/Livewire/Project/Shared/ScheduledTask/Show.php b/app/Livewire/Project/Shared/ScheduledTask/Show.php index 23cb0e41a..87b752509 100644 --- a/app/Livewire/Project/Shared/ScheduledTask/Show.php +++ b/app/Livewire/Project/Shared/ScheduledTask/Show.php @@ -49,7 +49,7 @@ public function submit() { $this->validate(); $this->task->save(); - $this->dispatch('success', 'Scheduled task updated successfully.'); + $this->dispatch('success', 'Scheduled task updated.'); $this->dispatch('refreshTasks'); } diff --git a/app/Livewire/Server/Form.php b/app/Livewire/Server/Form.php index 239fa86bd..098a7c1ff 100644 --- a/app/Livewire/Server/Form.php +++ b/app/Livewire/Server/Form.php @@ -64,7 +64,7 @@ public function instantSave() refresh_server_connection($this->server->privateKey); $this->validateServer(false); $this->server->settings->save(); - $this->dispatch('success', 'Server updated successfully.'); + $this->dispatch('success', 'Server updated.'); } catch (\Throwable $e) { return handleError($e, $this); } @@ -88,7 +88,7 @@ public function checkLocalhostConnection() } public function validateServer($install = true) { - $this->dispatch('validateServer', $install); + $this->dispatch('init', $install); } public function submit() @@ -113,6 +113,6 @@ public function submit() $this->server->settings->cleanup_after_percentage = $this->cleanup_after_percentage; $this->server->settings->save(); $this->server->save(); - $this->dispatch('success', 'Server updated successfully.'); + $this->dispatch('success', 'Server updated.'); } } diff --git a/app/Livewire/Server/LogDrains.php b/app/Livewire/Server/LogDrains.php index b922cc0c9..4eca682d4 100644 --- a/app/Livewire/Server/LogDrains.php +++ b/app/Livewire/Server/LogDrains.php @@ -60,7 +60,7 @@ public function configureLogDrain() return; } $this->dispatch('serverRefresh'); - $this->dispatch('success', 'Log drain service started successfully.'); + $this->dispatch('success', 'Log drain service started.'); } catch (\Throwable $e) { return handleError($e, $this); } @@ -126,7 +126,7 @@ public function submit(string $type) ]); } $this->server->settings->save(); - $this->dispatch('success', 'Settings saved successfully.'); + $this->dispatch('success', 'Settings saved.'); return true; } catch (\Throwable $e) { if ($type === 'newrelic') { diff --git a/app/Livewire/Server/Proxy/DynamicConfigurationNavbar.php b/app/Livewire/Server/Proxy/DynamicConfigurationNavbar.php new file mode 100644 index 000000000..ee46a3fff --- /dev/null +++ b/app/Livewire/Server/Proxy/DynamicConfigurationNavbar.php @@ -0,0 +1,28 @@ +whereId($this->server_id)->first(); + $proxy_path = get_proxy_path(); + $file = str_replace('|', '.', $fileName); + instant_remote_process(["rm -f {$proxy_path}/dynamic/{$file}"], $server); + $this->dispatch('success', 'File deleted.'); + $this->dispatch('loadDynamicConfigurations'); + $this->dispatch('refresh'); + } + public function render() + { + return view('livewire.server.proxy.dynamic-configuration-navbar'); + } +} diff --git a/app/Livewire/Server/Proxy/DynamicConfigurations.php b/app/Livewire/Server/Proxy/DynamicConfigurations.php new file mode 100644 index 000000000..6e52f9d4a --- /dev/null +++ b/app/Livewire/Server/Proxy/DynamicConfigurations.php @@ -0,0 +1,51 @@ + '$refresh']; + protected $rules = [ + 'contents.*' => 'nullable|string', + ]; + public function loadDynamicConfigurations() + { + $proxy_path = get_proxy_path(); + $files = instant_remote_process(["mkdir -p $proxy_path/dynamic && ls -1 {$proxy_path}/dynamic"], $this->server); + $files = collect(explode("\n", $files))->filter(fn ($file) => !empty($file)); + $files = $files->map(fn ($file) => trim($file)); + $files = $files->sort(); + if ($files->contains('coolify.yaml')) { + $files = $files->filter(fn ($file) => $file !== 'coolify.yaml')->prepend('coolify.yaml'); + } + $contents = collect([]); + foreach ($files as $file) { + $without_extension = str_replace('.', '|', $file); + $contents[$without_extension] = instant_remote_process(["cat {$proxy_path}/dynamic/{$file}"], $this->server); + } + $this->contents = $contents; + } + public function mount() + { + $this->parameters = get_route_parameters(); + try { + $this->server = Server::ownedByCurrentTeam()->whereUuid(request()->server_uuid)->first(); + if (is_null($this->server)) { + return redirect()->route('server.index'); + } + } catch (\Throwable $e) { + return handleError($e, $this); + } + } + public function render() + { + return view('livewire.server.proxy.dynamic-configurations'); + } +} diff --git a/app/Livewire/Server/Proxy/NewDynamicConfiguration.php b/app/Livewire/Server/Proxy/NewDynamicConfiguration.php new file mode 100644 index 000000000..c9ceb41ee --- /dev/null +++ b/app/Livewire/Server/Proxy/NewDynamicConfiguration.php @@ -0,0 +1,74 @@ +parameters = get_route_parameters(); + if ($this->fileName !== '') { + $this->fileName = str_replace('|', '.', $this->fileName); + } + } + public function addDynamicConfiguration() + { + try { + $this->validate([ + 'fileName' => 'required', + 'value' => 'required', + ]); + + if (data_get($this->parameters, 'server_uuid')) { + $this->server = Server::ownedByCurrentTeam()->whereUuid(data_get($this->parameters, 'server_uuid'))->first(); + } + if (!is_null($this->server_id)) { + $this->server = Server::ownedByCurrentTeam()->whereId($this->server_id)->first(); + } + if (is_null($this->server)) { + return redirect()->route('server.index'); + } + if (!str($this->fileName)->endsWith('.yaml') && !str($this->fileName)->endsWith('.yml')) { + $this->fileName = "{$this->fileName}.yaml"; + } + if ($this->fileName === 'coolify.yaml') { + $this->dispatch('error', 'File name is reserved.'); + return; + } + $proxy_path = get_proxy_path(); + $file = "{$proxy_path}/dynamic/{$this->fileName}"; + if ($this->newFile) { + $exists = instant_remote_process(["test -f $file && echo 1 || echo 0"], $this->server); + if ($exists == 1) { + $this->dispatch('error', 'File already exists'); + return; + } + } + $yaml = Yaml::parse($this->value); + $yaml = Yaml::dump($yaml, 10, 2); + $this->value = $yaml; + $base64_value = base64_encode($this->value); + instant_remote_process(["echo '{$base64_value}' | base64 -d > {$file}"], $this->server); + $this->dispatch('loadDynamicConfigurations'); + $this->dispatch('dynamic-configuration-added'); + $this->dispatch('success', 'Dynamic configuration saved.'); + } catch (\Throwable $e) { + return handleError($e, $this); + } + } + public function render() + { + return view('livewire.server.proxy.new-dynamic-configuration'); + } +} diff --git a/app/Livewire/Server/ValidateAndInstall.php b/app/Livewire/Server/ValidateAndInstall.php index b5c46fa32..ff623e972 100644 --- a/app/Livewire/Server/ValidateAndInstall.php +++ b/app/Livewire/Server/ValidateAndInstall.php @@ -2,6 +2,7 @@ namespace App\Livewire\Server; +use App\Actions\Proxy\CheckProxy; use App\Actions\Proxy\StartProxy; use App\Models\Server; use Livewire\Component; @@ -21,7 +22,15 @@ class ValidateAndInstall extends Component public $error = null; public bool $ask = false; - protected $listeners = ['validateServer' => 'init', 'validateDockerEngine', 'validateServerNow' => 'validateServer']; + protected $listeners = [ + 'init', + 'validateConnection', + 'validateOS', + 'validateDockerEngine', + 'validateDockerVersion', + 'startProxy', + 'refresh' => '$refresh', + ]; public function init(bool $install = true) { @@ -35,31 +44,29 @@ public function init(bool $install = true) $this->error = null; $this->number_of_tries = 0; if (!$this->ask) { - $this->dispatch('validateServerNow'); + $this->dispatch('validateConnection'); } } - public function startValidatingAfterAsking() { + public function startValidatingAfterAsking() + { $this->ask = false; $this->init(); } - public function validateServer() + public function startProxy() { try { - $this->validateConnection(); - $this->validateOS(); - $this->validateDockerEngine(); - - if ($this->server->isSwarm()) { - $swarmInstalled = $this->server->validateDockerSwarm(); - if ($swarmInstalled) { - $this->dispatch('success', 'Docker Swarm is initiated.'); + $shouldStart = CheckProxy::run($this->server); + if ($shouldStart) { + $proxy = StartProxy::run($this->server, false); + if ($proxy === 'OK') { + $this->proxy_started = true; + } else { + throw new \Exception("Proxy could not be started."); } } else { - $proxy = StartProxy::run($this->server); - if ($proxy) { - $this->proxy_started = true; - } + $this->proxy_started = true; } + } catch (\Throwable $e) { return handleError($e, $this); } @@ -71,6 +78,7 @@ public function validateConnection() $this->error = 'Server is not reachable. Please validate your configuration and connection.

Check this documentation for further help.'; return; } + $this->dispatch('validateOS'); } public function validateOS() { @@ -79,6 +87,7 @@ public function validateOS() $this->error = 'Server OS type is not supported. Please install Docker manually before continuing: documentation.'; return; } + $this->dispatch('validateDockerEngine'); } public function validateDockerEngine() { @@ -90,29 +99,39 @@ public function validateDockerEngine() $this->error = 'Docker Engine could not be installed. Please install Docker manually before continuing: documentation.'; return; } else { - $activity = $this->server->installDocker(); - $this->number_of_tries++; - $this->dispatch('newActivityMonitor', $activity->id, 'validateDockerEngine'); + if ($this->number_of_tries == 0) { + $activity = $this->server->installDocker(); + $this->number_of_tries++; + $this->dispatch('newActivityMonitor', $activity->id, 'init'); + } return; } } else { $this->error = 'Docker Engine is not installed. Please install Docker manually before continuing: documentation.'; return; } - } else { - $this->validateDockerVersion(); } + $this->dispatch('validateDockerVersion'); } public function validateDockerVersion() { - $this->docker_version = $this->server->validateDockerEngineVersion(); - if ($this->docker_version) { - $this->dispatch('serverInstalled'); - $this->dispatch('success', 'Server validated successfully.'); + if ($this->server->isSwarm()) { + $swarmInstalled = $this->server->validateDockerSwarm(); + if ($swarmInstalled) { + $this->dispatch('success', 'Docker Swarm is initiated.'); + } } else { - $this->error = 'Docker Engine version is not 22+. Please install Docker manually before continuing: documentation.'; - return; + $this->docker_version = $this->server->validateDockerEngineVersion(); + if ($this->docker_version) { + $this->dispatch('serverInstalled'); + $this->dispatch('success', 'Server validated.'); + } else { + $this->error = 'Docker Engine version is not 22+. Please install Docker manually before continuing: documentation.'; + return; + } } + + $this->dispatch('startProxy'); } public function render() { diff --git a/app/Livewire/Settings/Backup.php b/app/Livewire/Settings/Backup.php index 519fe1bd8..67a457774 100644 --- a/app/Livewire/Settings/Backup.php +++ b/app/Livewire/Settings/Backup.php @@ -81,6 +81,6 @@ public function backup_now() } public function submit() { - $this->dispatch('success', 'Backup updated successfully.'); + $this->dispatch('success', 'Backup updated.'); } } diff --git a/app/Livewire/Settings/Email.php b/app/Livewire/Settings/Email.php index 471c18e9c..3563e2e64 100644 --- a/app/Livewire/Settings/Email.php +++ b/app/Livewire/Settings/Email.php @@ -49,7 +49,7 @@ public function submitFromFields() { 'settings.smtp_from_name' => 'required', ]); $this->settings->save(); - $this->dispatch('success', 'Settings saved successfully.'); + $this->dispatch('success', 'Settings saved.'); } catch (\Throwable $e) { return handleError($e, $this); } @@ -61,7 +61,7 @@ public function submitResend() { 'settings.resend_api_key' => 'required' ]); $this->settings->save(); - $this->dispatch('success', 'Settings saved successfully.'); + $this->dispatch('success', 'Settings saved.'); } catch (\Throwable $e) { $this->settings->resend_enabled = false; return handleError($e, $this); @@ -98,7 +98,7 @@ public function submit() 'settings.smtp_timeout' => 'nullable', ]); $this->settings->save(); - $this->dispatch('success', 'Settings saved successfully.'); + $this->dispatch('success', 'Settings saved.'); } catch (\Throwable $e) { return handleError($e, $this); } diff --git a/app/Livewire/Source/Github/Change.php b/app/Livewire/Source/Github/Change.php index 020e9c6ad..61c4ffcda 100644 --- a/app/Livewire/Source/Github/Change.php +++ b/app/Livewire/Source/Github/Change.php @@ -2,8 +2,10 @@ namespace App\Livewire\Source\Github; +use App\Jobs\GithubAppPermissionJob; use App\Models\GithubApp; use App\Models\InstanceSettings; +use Illuminate\Support\Facades\Http; use Livewire\Component; class Change extends Component @@ -15,6 +17,7 @@ class Change extends Component public ?bool $default_permissions = true; public ?bool $preview_deployment_permissions = true; + public ?bool $administration = false; public $parameters; public ?GithubApp $github_app; @@ -34,8 +37,52 @@ class Change extends Component 'github_app.client_secret' => 'required|string', 'github_app.webhook_secret' => 'required|string', 'github_app.is_system_wide' => 'required|bool', + 'github_app.contents' => 'nullable|string', + 'github_app.metadata' => 'nullable|string', + 'github_app.pull_requests' => 'nullable|string', + 'github_app.administration' => 'nullable|string', ]; + public function checkPermissions() + { + GithubAppPermissionJob::dispatchSync($this->github_app); + $this->github_app->refresh()->makeVisible('client_secret')->makeVisible('webhook_secret'); + $this->dispatch('success', 'Github App permissions updated.'); + } + // public function check() + // { + + // Need administration:read:write permission + // https://docs.github.com/en/rest/actions/self-hosted-runners?apiVersion=2022-11-28#list-self-hosted-runners-for-a-repository + + + // $github_access_token = generate_github_installation_token($this->github_app); + // $repositories = Http::withToken($github_access_token)->get("{$this->github_app->api_url}/installation/repositories?per_page=100"); + // $runners_by_repository = collect([]); + // $repositories = $repositories->json()['repositories']; + // foreach ($repositories as $repository) { + // $runners_downloads = Http::withToken($github_access_token)->get("{$this->github_app->api_url}/repos/{$repository['full_name']}/actions/runners/downloads"); + // $runners = Http::withToken($github_access_token)->get("{$this->github_app->api_url}/repos/{$repository['full_name']}/actions/runners"); + // $token = Http::withHeaders([ + // 'Authorization' => "Bearer $github_access_token", + // 'Accept' => 'application/vnd.github+json' + // ])->withBody(null)->post("{$this->github_app->api_url}/repos/{$repository['full_name']}/actions/runners/registration-token"); + // $token = $token->json(); + // $remove_token = Http::withHeaders([ + // 'Authorization' => "Bearer $github_access_token", + // 'Accept' => 'application/vnd.github+json' + // ])->withBody(null)->post("{$this->github_app->api_url}/repos/{$repository['full_name']}/actions/runners/remove-token"); + // $remove_token = $remove_token->json(); + // $runners_by_repository->put($repository['full_name'], [ + // 'token' => $token, + // 'remove_token' => $remove_token, + // 'runners' => $runners->json(), + // 'runners_downloads' => $runners_downloads->json() + // ]); + // } + + // ray($runners_by_repository); + // } public function mount() { $github_app_uuid = request()->github_app_uuid; @@ -103,7 +150,7 @@ public function submit() 'github_app.is_system_wide' => 'required|bool', ]); $this->github_app->save(); - $this->dispatch('success', 'Github App updated successfully.'); + $this->dispatch('success', 'Github App updated.'); } catch (\Throwable $e) { return handleError($e, $this); } @@ -111,6 +158,13 @@ public function submit() public function instantSave() { + try { + $this->github_app->makeVisible('client_secret')->makeVisible('webhook_secret'); + $this->github_app->save(); + $this->dispatch('success', 'Github App updated.'); + } catch (\Throwable $e) { + return handleError($e, $this); + } } public function delete() diff --git a/app/Livewire/Team/Index.php b/app/Livewire/Team/Index.php index b7482e671..1822620f8 100644 --- a/app/Livewire/Team/Index.php +++ b/app/Livewire/Team/Index.php @@ -37,7 +37,7 @@ public function submit() try { $this->team->save(); refreshSession(); - $this->dispatch('success', 'Team updated successfully.'); + $this->dispatch('success', 'Team updated.'); } catch (\Throwable $e) { return handleError($e, $this); } diff --git a/app/Livewire/Team/InviteLink.php b/app/Livewire/Team/InviteLink.php index 5f9db3f84..cc9054888 100644 --- a/app/Livewire/Team/InviteLink.php +++ b/app/Livewire/Team/InviteLink.php @@ -79,7 +79,7 @@ private function generate_invite_link(bool $sendEmail = false) ]); $mail->subject('You have been invited to ' . currentTeam()->name . ' on ' . config('app.name') . '.'); send_user_an_email($mail, $this->email); - $this->dispatch('success', 'Invitation sent via email successfully.'); + $this->dispatch('success', 'Invitation sent via email.'); $this->dispatch('refreshInvitations'); return; } else { diff --git a/app/Models/Application.php b/app/Models/Application.php index b3838608f..7ebabf1b4 100644 --- a/app/Models/Application.php +++ b/app/Models/Application.php @@ -6,7 +6,6 @@ use Illuminate\Database\Eloquent\Casts\Attribute; use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\SoftDeletes; -use Illuminate\Support\Collection; use Spatie\Activitylog\Models\Activity; use Illuminate\Support\Str; use RuntimeException; @@ -274,15 +273,11 @@ public function status(): Attribute foreach ($additional_servers_status as $status) { $server_status = str($status)->before(':')->value(); $server_health = str($status)->after(':')->value() ?? 'unhealthy'; - if ($server_status !== 'running') { - if ($main_server_status !== $server_status) { - $complex_status = 'degraded'; - } + if ($main_server_status !== $server_status) { + $complex_status = 'degraded'; } - if ($server_health !== 'healthy') { - if ($main_server_health !== $server_health) { - $complex_health = 'unhealthy'; - } + if ($main_server_health !== $server_health) { + $complex_health = 'unhealthy'; } } return "$complex_status:$complex_health"; diff --git a/app/Models/LocalFileVolume.php b/app/Models/LocalFileVolume.php index 76a15f655..3e032db0f 100644 --- a/app/Models/LocalFileVolume.php +++ b/app/Models/LocalFileVolume.php @@ -57,6 +57,7 @@ public function saveStorageOnServer() if ($content) { $content = base64_encode($content); $commands->push("echo '$content' | base64 -d > $path"); + $commands->push("chmod +x $path"); } } else if ($isDir == 'NOK' && $fileVolume->is_directory) { $commands->push("mkdir -p $path > /dev/null 2>&1 || true"); diff --git a/app/Models/Server.php b/app/Models/Server.php index 76ed8c8a9..016efd5f7 100644 --- a/app/Models/Server.php +++ b/app/Models/Server.php @@ -398,10 +398,10 @@ public function validateOS(): bool | Stringable } }); if ($supported->count() === 1) { - ray('supported'); + // ray('supported'); return str($supported->first()); } else { - ray('not supported'); + // ray('not supported'); return false; } } @@ -468,6 +468,16 @@ public function validateDockerEngine($throwError = false) } return false; } + try { + instant_remote_process(["docker version"], $this); + } catch (\Throwable $e) { + $this->settings->is_usable = false; + $this->settings->save(); + if ($throwError) { + throw new \Exception('Server is not usable. Docker Engine is not running.'); + } + return false; + } $this->settings->is_usable = true; $this->settings->save(); $this->validateCoolifyNetwork(isSwarm: false, isBuildServer: $this->settings->is_build_server); diff --git a/app/View/Components/ResourceView.php b/app/View/Components/ResourceView.php new file mode 100644 index 000000000..98efddc00 --- /dev/null +++ b/app/View/Components/ResourceView.php @@ -0,0 +1,31 @@ +status = $resource->status; } /** diff --git a/bootstrap/helpers/applications.php b/bootstrap/helpers/applications.php index f921c2df8..bf3f15514 100644 --- a/bootstrap/helpers/applications.php +++ b/bootstrap/helpers/applications.php @@ -8,7 +8,7 @@ use App\Models\StandaloneDocker; use Spatie\Url\Url; -function queue_application_deployment(Application $application, string $deployment_uuid, int | null $pull_request_id = 0, string $commit = 'HEAD', bool $force_rebuild = false, bool $is_webhook = false, bool $restart_only = false, ?string $git_type = null, bool $no_questions_asked = false, Server $server = null, StandaloneDocker $destination = null) +function queue_application_deployment(Application $application, string $deployment_uuid, int | null $pull_request_id = 0, string $commit = 'HEAD', bool $force_rebuild = false, bool $is_webhook = false, bool $restart_only = false, ?string $git_type = null, bool $no_questions_asked = false, Server $server = null, StandaloneDocker $destination = null, bool $only_this_server = false) { $application_id = $application->id; $deployment_link = Url::fromString($application->link() . "/deployment/{$deployment_uuid}"); @@ -37,7 +37,8 @@ function queue_application_deployment(Application $application, string $deployme 'is_webhook' => $is_webhook, 'restart_only' => $restart_only, 'commit' => $commit, - 'git_type' => $git_type + 'git_type' => $git_type, + 'only_this_server' => $only_this_server ]); if ($no_questions_asked) { diff --git a/bootstrap/helpers/docker.php b/bootstrap/helpers/docker.php index 7b367c63c..370c05930 100644 --- a/bootstrap/helpers/docker.php +++ b/bootstrap/helpers/docker.php @@ -212,7 +212,7 @@ function generateServiceSpecificFqdns(ServiceApplication|Application $resource, } return $payload; } -function fqdnLabelsForTraefik(string $uuid, Collection $domains, bool $is_force_https_enabled = false, $onlyPort = null, ?Collection $serviceLabels = null, ?bool $is_gzip_enabled = true) +function fqdnLabelsForTraefik(string $uuid, Collection $domains, bool $is_force_https_enabled = false, $onlyPort = null, ?Collection $serviceLabels = null, ?bool $is_gzip_enabled = true, ?string $service_name = null) { $labels = collect([]); $labels->push('traefik.enable=true'); @@ -264,6 +264,10 @@ function fqdnLabelsForTraefik(string $uuid, Collection $domains, bool $is_force_ } $http_label = "http-{$loop}-{$uuid}"; $https_label = "https-{$loop}-{$uuid}"; + if ($service_name) { + $http_label = "http-{$loop}-{$uuid}-{$service_name}"; + $https_label = "https-{$loop}-{$uuid}-{$service_name}"; + } if ($schema === 'https') { // Set labels for https diff --git a/bootstrap/helpers/github.php b/bootstrap/helpers/github.php index 16633168f..5d759e651 100644 --- a/bootstrap/helpers/github.php +++ b/bootstrap/helpers/github.php @@ -86,3 +86,8 @@ function get_installation_path(GithubApp $source) $installation_path = $github->html_url === 'https://github.com' ? 'apps' : 'github-apps'; return "$github->html_url/$installation_path/$name/installations/new"; } +function get_permissions_path(GithubApp $source) { + $github = GithubApp::where('uuid', $source->uuid)->first(); + $name = Str::of(Str::kebab($github->name)); + return "$github->html_url/settings/apps/$name/permissions"; +} diff --git a/bootstrap/helpers/proxy.php b/bootstrap/helpers/proxy.php index 19403a505..1bc1bdc28 100644 --- a/bootstrap/helpers/proxy.php +++ b/bootstrap/helpers/proxy.php @@ -140,7 +140,9 @@ function generate_default_proxy_configuration(Server $server) "--entrypoints.http.address=:80", "--entrypoints.https.address=:443", "--entrypoints.http.http.encodequerysemicolons=true", + "--entryPoints.http.http2.maxConcurrentStreams=50", "--entrypoints.https.http.encodequerysemicolons=true", + "--entryPoints.https.http2.maxConcurrentStreams=50", "--providers.docker.exposedbydefault=false", "--providers.file.directory=/traefik/dynamic/", "--providers.file.watch=true", diff --git a/bootstrap/helpers/services.php b/bootstrap/helpers/services.php index aa7d6fd54..c46c1e542 100644 --- a/bootstrap/helpers/services.php +++ b/bootstrap/helpers/services.php @@ -4,8 +4,8 @@ use App\Models\Service; use App\Models\ServiceApplication; use App\Models\ServiceDatabase; -use Illuminate\Support\Facades\Storage; use Illuminate\Support\Str; +use Spatie\Url\Url; use Symfony\Component\Yaml\Yaml; function replaceRegex(?string $name = null) @@ -95,12 +95,17 @@ function updateCompose($resource) // Update FQDN $variableName = "SERVICE_FQDN_" . Str::of($resource->name)->upper(); $generatedEnv = EnvironmentVariable::where('service_id', $resource->service_id)->where('key', $variableName)->first(); + $fqdn = Url::fromString($resource->fqdn); + $fqdn = $fqdn->getScheme() . '://' . $fqdn->getHost(); if ($generatedEnv) { - $generatedEnv->value = $resource->fqdn; + $generatedEnv->value = $fqdn; $generatedEnv->save(); } $variableName = "SERVICE_URL_" . Str::of($resource->name)->upper(); $generatedEnv = EnvironmentVariable::where('service_id', $resource->service_id)->where('key', $variableName)->first(); + $url = Url::fromString($resource->fqdn); + $url = $url->getHost(); + ray($url); if ($generatedEnv) { $url = Str::of($resource->fqdn)->after('://'); $generatedEnv->value = $url; diff --git a/bootstrap/helpers/shared.php b/bootstrap/helpers/shared.php index f7939c9c3..4a49f34a2 100644 --- a/bootstrap/helpers/shared.php +++ b/bootstrap/helpers/shared.php @@ -104,13 +104,13 @@ function handleError(?Throwable $error = null, ?Livewire\Component $livewire = n ray($error); if ($error instanceof TooManyRequestsException) { if (isset($livewire)) { - return $livewire->dispatch('error', "Too many requests.", "Please try again in {$error->secondsUntilAvailable} seconds."); + return $livewire->dispatch('error', 'Too many requests. Please try again in {$error->secondsUntilAvailable} seconds.'); } return "Too many requests. Please try again in {$error->secondsUntilAvailable} seconds."; } if ($error instanceof UniqueConstraintViolationException) { if (isset($livewire)) { - return $livewire->dispatch('error', "Duplicate entry found.", "Please use a different name."); + return $livewire->dispatch('error', 'Duplicate entry found. Please use a different name.'); } return "Duplicate entry found. Please use a different name."; } @@ -125,9 +125,6 @@ function handleError(?Throwable $error = null, ?Livewire\Component $livewire = n } if (isset($livewire)) { - if (str($message)->length() > 20) { - return $livewire->dispatch('error', 'Error occured', $message); - } return $livewire->dispatch('error', $message); } throw new Exception($message); @@ -975,7 +972,7 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal ]); } if (!$isDatabase) { - if ($command->value() === 'FQDN' && is_null($savedService->fqdn)) { + if ($command->value() === 'FQDN' && is_null($savedService->fqdn) && !$foundEnv) { $savedService->fqdn = $fqdn; $savedService->save(); } @@ -1039,7 +1036,7 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal $serviceLabels = $serviceLabels->merge($defaultLabels); if (!$isDatabase && $fqdns->count() > 0) { if ($fqdns) { - $serviceLabels = $serviceLabels->merge(fqdnLabelsForTraefik($resource->uuid, $fqdns, true, serviceLabels: $serviceLabels, is_gzip_enabled: $savedService->isGzipEnabled())); + $serviceLabels = $serviceLabels->merge(fqdnLabelsForTraefik($resource->uuid, $fqdns, true, serviceLabels: $serviceLabels, is_gzip_enabled: $savedService->isGzipEnabled(), service_name: $serviceName)); } } if ($resource->server->isLogDrainEnabled() && $savedService->isLogDrainEnabled()) { @@ -1480,7 +1477,7 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal return $preview_fqdn; }); } - $serviceLabels = $serviceLabels->merge(fqdnLabelsForTraefik($uuid, $fqdns,serviceLabels: $serviceLabels)); + $serviceLabels = $serviceLabels->merge(fqdnLabelsForTraefik($uuid, $fqdns, serviceLabels: $serviceLabels)); } } } diff --git a/config/sentry.php b/config/sentry.php index c974623b0..f537dc4d2 100644 --- a/config/sentry.php +++ b/config/sentry.php @@ -7,7 +7,7 @@ // The release version of your application // Example with dynamic git hash: trim(exec('git --git-dir ' . base_path('.git') . ' log --pretty="%h" -n1 HEAD')) - 'release' => '4.0.0-beta.221', + 'release' => '4.0.0-beta.222', // When left empty or `null` the Laravel environment will be used 'environment' => config('app.env'), diff --git a/config/version.php b/config/version.php index c67555702..7fca7b055 100644 --- a/config/version.php +++ b/config/version.php @@ -1,3 +1,3 @@ string('contents')->nullable(); + $table->string('metadata')->nullable(); + $table->string('pull_requests')->nullable(); + $table->string('administration')->nullable(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('github_apps', function (Blueprint $table) { + $table->dropColumn('contents'); + $table->dropColumn('metadata'); + $table->dropColumn('pull_requests'); + $table->dropColumn('administration'); + }); + } +}; diff --git a/database/migrations/2024_02_22_090900_add_only_this_server_deployment.php b/database/migrations/2024_02_22_090900_add_only_this_server_deployment.php new file mode 100644 index 000000000..8dd9e1031 --- /dev/null +++ b/database/migrations/2024_02_22_090900_add_only_this_server_deployment.php @@ -0,0 +1,28 @@ +boolean('only_this_server')->default(false); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('application_deployment_queues', function (Blueprint $table) { + $table->dropColumn('only_this_server'); + }); + } +}; diff --git a/public/svgs/appsmith.svg b/public/svgs/appsmith.svg new file mode 100644 index 000000000..87517796f --- /dev/null +++ b/public/svgs/appsmith.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/public/svgs/appwrite.svg b/public/svgs/appwrite.svg new file mode 100644 index 000000000..dc58a8110 --- /dev/null +++ b/public/svgs/appwrite.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/svgs/babybuddy.png b/public/svgs/babybuddy.png new file mode 100644 index 000000000..36623f744 Binary files /dev/null and b/public/svgs/babybuddy.png differ diff --git a/public/svgs/bitwarden.svg b/public/svgs/bitwarden.svg new file mode 100644 index 000000000..888e50b2b --- /dev/null +++ b/public/svgs/bitwarden.svg @@ -0,0 +1,59 @@ + + + +image/svg+xml \ No newline at end of file diff --git a/public/svgs/code-server.svg b/public/svgs/code-server.svg new file mode 100644 index 000000000..8b589eef2 --- /dev/null +++ b/public/svgs/code-server.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/public/svgs/directus.svg b/public/svgs/directus.svg new file mode 100644 index 000000000..13dd08851 --- /dev/null +++ b/public/svgs/directus.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/svgs/docker-registry.png b/public/svgs/docker-registry.png new file mode 100644 index 000000000..4fa75b2a7 Binary files /dev/null and b/public/svgs/docker-registry.png differ diff --git a/public/svgs/docker.svg b/public/svgs/docker.svg new file mode 100644 index 000000000..48b4b4a27 --- /dev/null +++ b/public/svgs/docker.svg @@ -0,0 +1 @@ + diff --git a/public/svgs/dokuwiki.png b/public/svgs/dokuwiki.png new file mode 100644 index 000000000..a1f499569 Binary files /dev/null and b/public/svgs/dokuwiki.png differ diff --git a/public/svgs/duplicati.webp b/public/svgs/duplicati.webp new file mode 100644 index 000000000..5bc803779 Binary files /dev/null and b/public/svgs/duplicati.webp differ diff --git a/public/svgs/emby.png b/public/svgs/emby.png new file mode 100644 index 000000000..ca84b6964 Binary files /dev/null and b/public/svgs/emby.png differ diff --git a/public/svgs/fider.svg b/public/svgs/fider.svg new file mode 100644 index 000000000..0c7f03324 --- /dev/null +++ b/public/svgs/fider.svg @@ -0,0 +1 @@ + diff --git a/public/svgs/filebrowser.svg b/public/svgs/filebrowser.svg new file mode 100644 index 000000000..5e78eccff --- /dev/null +++ b/public/svgs/filebrowser.svg @@ -0,0 +1,147 @@ + +image/svg+xml + + + + + \ No newline at end of file diff --git a/public/svgs/formbricks.png b/public/svgs/formbricks.png new file mode 100644 index 000000000..3f2194c20 Binary files /dev/null and b/public/svgs/formbricks.png differ diff --git a/public/svgs/ghost.svg b/public/svgs/ghost.svg new file mode 100644 index 000000000..682b10eda --- /dev/null +++ b/public/svgs/ghost.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/public/svgs/git.svg b/public/svgs/git.svg new file mode 100644 index 000000000..93f25f923 --- /dev/null +++ b/public/svgs/git.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/svgs/gitea.svg b/public/svgs/gitea.svg new file mode 100644 index 000000000..281c748ef --- /dev/null +++ b/public/svgs/gitea.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + + diff --git a/public/svgs/github.svg b/public/svgs/github.svg new file mode 100644 index 000000000..6c77b4144 --- /dev/null +++ b/public/svgs/github.svg @@ -0,0 +1 @@ + diff --git a/public/svgs/glitchtip.png b/public/svgs/glitchtip.png new file mode 100644 index 000000000..866317528 Binary files /dev/null and b/public/svgs/glitchtip.png differ diff --git a/public/svgs/grafana.svg b/public/svgs/grafana.svg new file mode 100644 index 000000000..038701973 --- /dev/null +++ b/public/svgs/grafana.svg @@ -0,0 +1 @@ + diff --git a/public/svgs/grocy.svg b/public/svgs/grocy.svg new file mode 100644 index 000000000..24bb0d252 --- /dev/null +++ b/public/svgs/grocy.svg @@ -0,0 +1,21 @@ + + + + +Created by potrace 1.16, written by Peter Selinger 2001-2019 + + + + + diff --git a/public/svgs/jellyfin.svg b/public/svgs/jellyfin.svg new file mode 100644 index 000000000..fbf03077c --- /dev/null +++ b/public/svgs/jellyfin.svg @@ -0,0 +1,15 @@ + diff --git a/public/svgs/mariadb.svg b/public/svgs/mariadb.svg new file mode 100644 index 000000000..ed5b44104 --- /dev/null +++ b/public/svgs/mariadb.svg @@ -0,0 +1 @@ + diff --git a/public/svgs/meilisearch.svg b/public/svgs/meilisearch.svg new file mode 100644 index 000000000..85c35a455 --- /dev/null +++ b/public/svgs/meilisearch.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/public/svgs/metabase.svg b/public/svgs/metabase.svg new file mode 100644 index 000000000..255d169db --- /dev/null +++ b/public/svgs/metabase.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/svgs/minio.svg b/public/svgs/minio.svg new file mode 100644 index 000000000..0496de20f --- /dev/null +++ b/public/svgs/minio.svg @@ -0,0 +1 @@ + diff --git a/public/svgs/mongodb.svg b/public/svgs/mongodb.svg new file mode 100644 index 000000000..2cfad65e1 --- /dev/null +++ b/public/svgs/mongodb.svg @@ -0,0 +1 @@ + diff --git a/public/svgs/moodle.png b/public/svgs/moodle.png new file mode 100644 index 000000000..340f425b1 Binary files /dev/null and b/public/svgs/moodle.png differ diff --git a/public/svgs/mysql.svg b/public/svgs/mysql.svg new file mode 100644 index 000000000..2b393ca07 --- /dev/null +++ b/public/svgs/mysql.svg @@ -0,0 +1 @@ + diff --git a/public/svgs/n8n.png b/public/svgs/n8n.png new file mode 100644 index 000000000..6ef98587b Binary files /dev/null and b/public/svgs/n8n.png differ diff --git a/public/svgs/nextcloud.svg b/public/svgs/nextcloud.svg new file mode 100644 index 000000000..c9938c99f --- /dev/null +++ b/public/svgs/nextcloud.svg @@ -0,0 +1,73 @@ + + + +image/svg+xml + + + + + + \ No newline at end of file diff --git a/public/svgs/nocodb.svg b/public/svgs/nocodb.svg new file mode 100644 index 000000000..d4c96f9be --- /dev/null +++ b/public/svgs/nocodb.svg @@ -0,0 +1,10 @@ + + + NocoDB + + + + + + + \ No newline at end of file diff --git a/public/svgs/openblocks.svg b/public/svgs/openblocks.svg new file mode 100644 index 000000000..2de5ee88f --- /dev/null +++ b/public/svgs/openblocks.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/public/svgs/phpmyadmin.svg b/public/svgs/phpmyadmin.svg new file mode 100644 index 000000000..1e32d14f3 --- /dev/null +++ b/public/svgs/phpmyadmin.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/svgs/pocketbase.svg b/public/svgs/pocketbase.svg new file mode 100644 index 000000000..5b5de956b --- /dev/null +++ b/public/svgs/pocketbase.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/public/svgs/postgres.svg b/public/svgs/postgres.svg new file mode 100644 index 000000000..ad4d4d224 --- /dev/null +++ b/public/svgs/postgres.svg @@ -0,0 +1 @@ + diff --git a/public/svgs/posthog.svg b/public/svgs/posthog.svg new file mode 100644 index 000000000..c7eb64fd4 --- /dev/null +++ b/public/svgs/posthog.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/public/svgs/redis.svg b/public/svgs/redis.svg new file mode 100644 index 000000000..3c7d88737 --- /dev/null +++ b/public/svgs/redis.svg @@ -0,0 +1 @@ + diff --git a/public/svgs/stirling.png b/public/svgs/stirling.png new file mode 100644 index 000000000..5edc6eae2 Binary files /dev/null and b/public/svgs/stirling.png differ diff --git a/public/svgs/syncthing.svg b/public/svgs/syncthing.svg new file mode 100644 index 000000000..6a036026b --- /dev/null +++ b/public/svgs/syncthing.svg @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/svgs/trigger.avif b/public/svgs/trigger.avif new file mode 100644 index 000000000..66500da9f Binary files /dev/null and b/public/svgs/trigger.avif differ diff --git a/public/svgs/trigger.png b/public/svgs/trigger.png new file mode 100644 index 000000000..72999559b Binary files /dev/null and b/public/svgs/trigger.png differ diff --git a/public/svgs/umami.svg b/public/svgs/umami.svg new file mode 100644 index 000000000..b900e2976 --- /dev/null +++ b/public/svgs/umami.svg @@ -0,0 +1 @@ +Created by potrace 1.11, written by Peter Selinger 2001-2013 diff --git a/public/svgs/unknown.svg b/public/svgs/unknown.svg new file mode 100644 index 000000000..d7752c454 --- /dev/null +++ b/public/svgs/unknown.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/svgs/uptime-kuma.svg b/public/svgs/uptime-kuma.svg new file mode 100644 index 000000000..c4217915d --- /dev/null +++ b/public/svgs/uptime-kuma.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/public/svgs/weblate.webp b/public/svgs/weblate.webp new file mode 100644 index 000000000..fae61d602 Binary files /dev/null and b/public/svgs/weblate.webp differ diff --git a/public/svgs/whoogle-search.png b/public/svgs/whoogle-search.png new file mode 100644 index 000000000..2b895c194 Binary files /dev/null and b/public/svgs/whoogle-search.png differ diff --git a/public/svgs/wordpress.svg b/public/svgs/wordpress.svg new file mode 100644 index 000000000..e8eb70d4f --- /dev/null +++ b/public/svgs/wordpress.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/resources/views/components/proxy/options.blade.php b/resources/views/components/proxy/options.blade.php deleted file mode 100644 index 04a6f04ba..000000000 --- a/resources/views/components/proxy/options.blade.php +++ /dev/null @@ -1,47 +0,0 @@ -@props(['proxy_settings']) -
- -
- -
- -
- -
- Visit Dashboard -
- -
- -
- -
- -
diff --git a/resources/views/components/resource-view.blade.php b/resources/views/components/resource-view.blade.php new file mode 100644 index 000000000..e4872dd21 --- /dev/null +++ b/resources/views/components/resource-view.blade.php @@ -0,0 +1,31 @@ +
!$upgrade, + 'hover:border-red-500 cursor-not-allowed ' => $upgrade, +]) @if (!$upgrade) wire:click={{ $wire }} @endif> +
+ {{ $logo }} +
+
+ {{ $title }} +
+ @if($upgrade) +
{{ $upgrade }}
+ @else + + @endif +
+
+ @isset($documentation) +
+
+ + Docs + +
+ @endisset + +
diff --git a/resources/views/components/resources/breadcrumbs.blade.php b/resources/views/components/resources/breadcrumbs.blade.php index baa46fa91..6e2b234a3 100644 --- a/resources/views/components/resources/breadcrumbs.blade.php +++ b/resources/views/components/resources/breadcrumbs.blade.php @@ -41,7 +41,7 @@ @if ($resource->getMorphClass() == 'App\Models\Service') @else - + @endif diff --git a/resources/views/components/server/sidebar.blade.php b/resources/views/components/server/sidebar.blade.php index 9aa50bb21..86bb92a87 100644 --- a/resources/views/components/server/sidebar.blade.php +++ b/resources/views/components/server/sidebar.blade.php @@ -1,12 +1,16 @@
@if ($server->isFunctional())
-
+ x-transition:leave="transform transition ease-in-out duration-100 sm:duration-300" x-transition:leave-start="translate-x-0" x-transition:leave-end="translate-x-full" @class([ - 'max-w-md w-screen' => !$fullScreen, + 'max-w-xl w-screen' => !$fullScreen, 'max-w-4xl w-screen' => $fullScreen, ])>
-

+

{{ $title }}

+ --}} @else - + --}} @endif @empty -
No service found. Please try to reload the list!
+
No service found. Please try to reload the list!
@endforelse @endif
diff --git a/resources/views/livewire/project/resource/index.blade.php b/resources/views/livewire/project/resource/index.blade.php index adbc352cf..ac59b0c18 100644 --- a/resources/views/livewire/project/resource/index.blade.php +++ b/resources/views/livewire/project/resource/index.blade.php @@ -67,7 +67,7 @@ class="items-center justify-center box">+ Add New Resource
-
+
diff --git a/resources/views/livewire/project/shared/destination.blade.php b/resources/views/livewire/project/shared/destination.blade.php index 385183e7c..b5596ea21 100644 --- a/resources/views/livewire/project/shared/destination.blade.php +++ b/resources/views/livewire/project/shared/destination.blade.php @@ -4,7 +4,7 @@
-
Main Server
+
Primary Server
@if (str($resource->realStatus())->startsWith('running'))
@@ -21,7 +21,11 @@
@if ($resource?->additional_networks?->count() > 0) Redeploy + wire:click="redeploy('{{ data_get($resource, 'destination.id') }}','{{ data_get($resource, 'destination.server.id') }}')">Deploy + @if (str($resource->realStatus())->startsWith('running')) + Stop + @endif @endif
@if ($resource?->additional_networks?->count() > 0) @@ -41,16 +45,23 @@ class="absolute bg-error -top-1 -left-1 badge badge-xs">
Network: {{ data_get($destination, 'network') }}
-
Redeploy + wire:click="redeploy('{{ data_get($destination, 'id') }}','{{ data_get($destination, 'server.id') }}')">Deploy + Promote + to Primary + @if (data_get_str($destination, 'pivot.status')->startsWith('running')) + Stop + @endif This will stop the running application in this server and remove it as a deployment destination.

Please think again.
+
@endforeach @endif diff --git a/resources/views/livewire/project/shared/get-logs.blade.php b/resources/views/livewire/project/shared/get-logs.blade.php index 959aa8fa5..9ca5c6abb 100644 --- a/resources/views/livewire/project/shared/get-logs.blade.php +++ b/resources/views/livewire/project/shared/get-logs.blade.php @@ -1,82 +1,87 @@ -
-
-

Container: {{ $container }}

- @if ($streamLogs) - - @endif -
-
- - -
-
- - Refresh -
-
-
- - - - - -
{{ $outputs }}
+
+
+
+

Container: {{ $container }}

+ @if ($streamLogs) + + @endif
-
- +
- function toggleScroll() { - this.alwaysScroll = !this.alwaysScroll; - - if (this.alwaysScroll) { - this.intervalId = setInterval(() => { - const screen = document.getElementById('screen'); - const logs = document.getElementById('logs'); - if (screen.scrollTop !== logs.scrollHeight) { - screen.scrollTop = logs.scrollHeight; - } - }, 100); - } else { - clearInterval(this.intervalId); - this.intervalId = null; - } - } - - function goTop() { - this.alwaysScroll = false; - clearInterval(this.intervalId); - const screen = document.getElementById('screen'); - screen.scrollTop = 0; - } -
diff --git a/resources/views/livewire/server/form.blade.php b/resources/views/livewire/server/form.blade.php index 9d97a88fa..4e4e11845 100644 --- a/resources/views/livewire/server/form.blade.php +++ b/resources/views/livewire/server/form.blade.php @@ -10,15 +10,17 @@ @else Save - - Validate & configure - - - - - Revalidate server - - + @if ($server->isFunctional()) + + Validate & configure + + + + + Revalidate server + + + @endif @endif
@if ($server->isFunctional()) diff --git a/resources/views/livewire/server/proxy/dynamic-configuration-navbar.blade.php b/resources/views/livewire/server/proxy/dynamic-configuration-navbar.blade.php new file mode 100644 index 000000000..c2a5dade9 --- /dev/null +++ b/resources/views/livewire/server/proxy/dynamic-configuration-navbar.blade.php @@ -0,0 +1,15 @@ +
+

File: {{ str_replace('|', '.', $fileName) }}

+
+ + Edit Configuration + + + + + +
+ Delete +
diff --git a/resources/views/livewire/server/proxy/dynamic-configurations.blade.php b/resources/views/livewire/server/proxy/dynamic-configurations.blade.php new file mode 100644 index 000000000..c89c4274f --- /dev/null +++ b/resources/views/livewire/server/proxy/dynamic-configurations.blade.php @@ -0,0 +1,55 @@ +
+ +
+ +
+ @if ($server->isFunctional()) +
+
+
+

Dynamic Configurations

+ Reload + + New Dynamic Configuration + + + + + +
+
You can add dynamic Traefik configurations here.
+
+
+
+ +
+
+ @if ($contents?->isNotEmpty()) + @foreach ($contents as $fileName => $value) +
+ @if (str_replace('|', '.', $fileName) === 'coolify.yaml') +
+

File: {{ str_replace('|', '.', $fileName) }}

+
+ + @else + + + @endif +
+ @endforeach + @else +
No dynamic configurations found.
+ @endif +
+ + @endif +
+
+
diff --git a/resources/views/livewire/server/proxy/logs.blade.php b/resources/views/livewire/server/proxy/logs.blade.php index 58e718424..496464541 100644 --- a/resources/views/livewire/server/proxy/logs.blade.php +++ b/resources/views/livewire/server/proxy/logs.blade.php @@ -3,6 +3,7 @@
+

Logs

diff --git a/resources/views/livewire/server/proxy/new-dynamic-configuration.blade.php b/resources/views/livewire/server/proxy/new-dynamic-configuration.blade.php new file mode 100644 index 000000000..9e98b0ed4 --- /dev/null +++ b/resources/views/livewire/server/proxy/new-dynamic-configuration.blade.php @@ -0,0 +1,5 @@ +
+ + + Save + diff --git a/resources/views/livewire/server/validate-and-install.blade.php b/resources/views/livewire/server/validate-and-install.blade.php index 35d5ab06a..8d50c3608 100644 --- a/resources/views/livewire/server/validate-and-install.blade.php +++ b/resources/views/livewire/server/validate-and-install.blade.php @@ -3,7 +3,7 @@ This will revalidate the server, install / update Docker Engine, Docker Compose and all related configuration. It will also restart Docker Engine, so your running containers will be unreachable for the time being. - Continue + Continue @else @if ($uptime)
Server is reachable:
@else @if ($error) -
Server is reachable: Supported OS type:
@else -
+
@endif @endif @endif @@ -85,8 +85,22 @@ d="m243.28 68.24l-24-23.56a16 16 0 0 0-22.58 0L104 136l-.11-.11l-36.64-35.27a16 16 0 0 0-22.57.06l-24 24a16 16 0 0 0 0 22.61l71.62 72a16 16 0 0 0 22.63 0l128.4-128.38a16 16 0 0 0-.05-22.67M103.62 208L32 136l24-24l.11.11l36.64 35.27a16 16 0 0 0 22.52 0L208.06 56L232 79.6Z" />
+ @isset($docker_version) +
Minimum Docker version: + + + + +
+ @else +
+ @endisset @if ($proxy_started) -
Proxy Started: Proxy started:
@else @if ($error) -
Proxy Started: Proxy started:
@else -
+
@endif @endif @else @@ -120,20 +134,7 @@ @endif @endif - @isset($docker_version) -
Minimum Docker version installed: - - - - -
- @endisset - - + @isset($error)
{!! $error !!}
@endisset diff --git a/resources/views/livewire/source/github/change.blade.php b/resources/views/livewire/source/github/change.blade.php index 941d616c8..2eae0a8bd 100644 --- a/resources/views/livewire/source/github/change.blade.php +++ b/resources/views/livewire/source/github/change.blade.php @@ -32,39 +32,64 @@ Install Repositories on GitHub @else - @if (!isCloud()) -
- +
+
+ +
- @endif -
- - -
-
- - -
-
- @if ($github_app->html_url === 'https://github.com') - - - @else - - + @if (!isCloud()) +
+ +
@endif -
-
- - -
-
- - - +
+ + +
+
+ @if ($github_app->html_url === 'https://github.com') + + + @else + + + @endif +
+
+ + +
+
+ + + +
+
+

Permissions

+ Refetch + + + Update + + + +
+
+ + + {{-- --}} + +
@endif @@ -89,7 +114,7 @@

Register a GitHub App

+ x-on:click.prevent="createGithubApp('{{ $webhook_endpoint }}','{{ $preview_deployment_permissions }}',{{ $administration }})"> Register Now
@@ -114,17 +139,18 @@
@endif -
- + - + {{-- --}}