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 @@
+
+
+
+
\ 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 @@
+
+
\ 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 @@
+
+
+
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 @@
+
+
+
+
\ 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 @@
+
+
\ 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 @@
+
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'])
-