From c26209f187a8e85b434a9994e3f01eb2fa3fd412 Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Thu, 27 Mar 2025 10:47:08 +0100 Subject: [PATCH 01/17] refactor(nightly): update version numbers and enhance upgrade script --- other/nightly/install.sh | 6 +++--- other/nightly/upgrade.sh | 3 ++- scripts/install.sh | 6 +++--- scripts/upgrade.sh | 3 ++- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/other/nightly/install.sh b/other/nightly/install.sh index 7e8c4482a..f0fcdfb4e 100755 --- a/other/nightly/install.sh +++ b/other/nightly/install.sh @@ -20,7 +20,7 @@ DATE=$(date +"%Y%m%d-%H%M%S") OS_TYPE=$(grep -w "ID" /etc/os-release | cut -d "=" -f 2 | tr -d '"') ENV_FILE="/data/coolify/source/.env" -VERSION="19" +VERSION="20" DOCKER_VERSION="27.0" # TODO: Ask for a user CURRENT_USER=$USER @@ -803,9 +803,9 @@ echo -e " - Please wait." getAJoke if [[ $- == *x* ]]; then - bash -x /data/coolify/source/upgrade.sh "${LATEST_VERSION:-latest}" "${LATEST_HELPER_VERSION:-latest}" + bash -x /data/coolify/source/upgrade.sh "${LATEST_VERSION:-latest}" "${LATEST_HELPER_VERSION:-latest}" "${REGISTRY_URL:-ghcr.io}" else - bash /data/coolify/source/upgrade.sh "${LATEST_VERSION:-latest}" "${LATEST_HELPER_VERSION:-latest}" + bash /data/coolify/source/upgrade.sh "${LATEST_VERSION:-latest}" "${LATEST_HELPER_VERSION:-latest}" "${REGISTRY_URL:-ghcr.io}" fi echo " - Coolify installed successfully." rm -f $ENV_FILE-$DATE diff --git a/other/nightly/upgrade.sh b/other/nightly/upgrade.sh index 54958ba56..0b031ca75 100644 --- a/other/nightly/upgrade.sh +++ b/other/nightly/upgrade.sh @@ -1,10 +1,11 @@ #!/bin/bash ## Do not modify this file. You will lose the ability to autoupdate! -VERSION="14" +VERSION="15" CDN="https://cdn.coollabs.io/coolify-nightly" LATEST_IMAGE=${1:-latest} LATEST_HELPER_VERSION=${2:-latest} +REGISTRY_URL=${3:-ghcr.io} DATE=$(date +%Y-%m-%d-%H-%M-%S) LOGFILE="/data/coolify/source/upgrade-${DATE}.log" diff --git a/scripts/install.sh b/scripts/install.sh index ac9e469bd..bc3b5b084 100755 --- a/scripts/install.sh +++ b/scripts/install.sh @@ -20,7 +20,7 @@ DATE=$(date +"%Y%m%d-%H%M%S") OS_TYPE=$(grep -w "ID" /etc/os-release | cut -d "=" -f 2 | tr -d '"') ENV_FILE="/data/coolify/source/.env" -VERSION="19" +VERSION="20" DOCKER_VERSION="27.0" # TODO: Ask for a user CURRENT_USER=$USER @@ -803,9 +803,9 @@ echo -e " - Please wait." getAJoke if [[ $- == *x* ]]; then - bash -x /data/coolify/source/upgrade.sh "${LATEST_VERSION:-latest}" "${LATEST_HELPER_VERSION:-latest}" + bash -x /data/coolify/source/upgrade.sh "${LATEST_VERSION:-latest}" "${LATEST_HELPER_VERSION:-latest}" "${REGISTRY_URL:-ghcr.io}" else - bash /data/coolify/source/upgrade.sh "${LATEST_VERSION:-latest}" "${LATEST_HELPER_VERSION:-latest}" + bash /data/coolify/source/upgrade.sh "${LATEST_VERSION:-latest}" "${LATEST_HELPER_VERSION:-latest}" "${REGISTRY_URL:-ghcr.io}" fi echo " - Coolify installed successfully." rm -f $ENV_FILE-$DATE diff --git a/scripts/upgrade.sh b/scripts/upgrade.sh index e3db2ea81..e59f4d138 100644 --- a/scripts/upgrade.sh +++ b/scripts/upgrade.sh @@ -1,10 +1,11 @@ #!/bin/bash ## Do not modify this file. You will lose the ability to autoupdate! -VERSION="14" +VERSION="15" CDN="https://cdn.coollabs.io/coolify" LATEST_IMAGE=${1:-latest} LATEST_HELPER_VERSION=${2:-latest} +REGISTRY_URL=${3:-ghcr.io} DATE=$(date +%Y-%m-%d-%H-%M-%S) LOGFILE="/data/coolify/source/upgrade-${DATE}.log" From ac7922ca44f86d7b4a09e30ed0ba5085a4d5558a Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Thu, 27 Mar 2025 10:48:30 +0100 Subject: [PATCH 02/17] refactor(versions): update version numbers for coolify and nightly --- config/constants.php | 2 +- other/nightly/versions.json | 4 ++-- versions.json | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/config/constants.php b/config/constants.php index 6746f72b2..c3f177f67 100644 --- a/config/constants.php +++ b/config/constants.php @@ -2,7 +2,7 @@ return [ 'coolify' => [ - 'version' => '4.0.0-beta.400', + 'version' => '4.0.0-beta.401', 'helper_version' => '1.0.7', 'realtime_version' => '1.0.6', 'self_hosted' => env('SELF_HOSTED', true), diff --git a/other/nightly/versions.json b/other/nightly/versions.json index 1b46548ec..03c56756d 100644 --- a/other/nightly/versions.json +++ b/other/nightly/versions.json @@ -1,10 +1,10 @@ { "coolify": { "v4": { - "version": "4.0.0-beta.400" + "version": "4.0.0-beta.401" }, "nightly": { - "version": "4.0.0-beta.401" + "version": "4.0.0-beta.402" }, "helper": { "version": "1.0.7" diff --git a/versions.json b/versions.json index 1b46548ec..03c56756d 100644 --- a/versions.json +++ b/versions.json @@ -1,10 +1,10 @@ { "coolify": { "v4": { - "version": "4.0.0-beta.400" + "version": "4.0.0-beta.401" }, "nightly": { - "version": "4.0.0-beta.401" + "version": "4.0.0-beta.402" }, "helper": { "version": "1.0.7" From 09636b413e962ad2f775a7855e12c535e22f81b8 Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Fri, 28 Mar 2025 14:55:13 +0100 Subject: [PATCH 03/17] refactor(email): validate team membership for email recipients --- app/Notifications/Channels/EmailChannel.php | 41 +++++++++++++++++++-- 1 file changed, 37 insertions(+), 4 deletions(-) diff --git a/app/Notifications/Channels/EmailChannel.php b/app/Notifications/Channels/EmailChannel.php index 4cdf8d08f..8287fd24b 100644 --- a/app/Notifications/Channels/EmailChannel.php +++ b/app/Notifications/Channels/EmailChannel.php @@ -2,6 +2,7 @@ namespace App\Notifications\Channels; +use App\Models\Team; use App\Services\ConfigurationRepository; use Exception; use Illuminate\Mail\Message; @@ -20,14 +21,36 @@ class EmailChannel public function send(SendsEmail $notifiable, Notification $notification): void { try { - $this->bootConfigs($notifiable); + $team = data_get($notifiable, 'id'); + $members = Team::find($team)->members; + $mailerType = $this->bootConfigs($notifiable); + $recipients = $notifiable->getRecipients(); if (count($recipients) === 0) { throw new Exception('No email recipients found'); } + foreach ($recipients as $recipient) { + // check if the recipient is part of the team + if (! $members->contains('email', $recipient)) { + $emailSettings = $notifiable->emailNotificationSettings; + data_set($emailSettings, 'smtp_password', '********'); + data_set($emailSettings, 'resend_api_key', '********'); + send_internal_notification(sprintf( + "Recipient is not part of the team: %s\nTeam: %s\nNotification: %s\nNotifiable: %s\nMailer Type: %s\nEmail Settings:\n%s", + $recipient, + $team, + get_class($notification), + get_class($notifiable), + $mailerType, + json_encode($emailSettings, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES) + )); + throw new Exception('Recipient is not part of the team'); + } + } $mailMessage = $notification->toMail($notifiable); - Mail::send( + + Mail::mailer($mailerType)->send( [], [], fn (Message $message) => $message @@ -52,7 +75,7 @@ class EmailChannel } } - private function bootConfigs($notifiable): void + private function bootConfigs($notifiable): string { $emailSettings = $notifiable->emailNotificationSettings; @@ -62,9 +85,19 @@ class EmailChannel throw new Exception('No email settings found.'); } - return; + return $type; } $this->configRepository->updateMailConfig($emailSettings); + + if ($emailSettings->resend_enabled) { + return 'resend'; + } + + if ($emailSettings->smtp_enabled) { + return 'smtp'; + } + + throw new Exception('No email settings found.'); } } From 2a08f4d653cafe0d53c5513c9841146768a1c3af Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Fri, 28 Mar 2025 15:09:38 +0100 Subject: [PATCH 04/17] refactor(shared): simplify deployment status check logic --- bootstrap/helpers/shared.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/bootstrap/helpers/shared.php b/bootstrap/helpers/shared.php index 60e71cd9c..ff8ac4c8a 100644 --- a/bootstrap/helpers/shared.php +++ b/bootstrap/helpers/shared.php @@ -1254,9 +1254,8 @@ function isAnyDeploymentInprogress() foreach ($runningJobs as $runningJob) { $horizonJobStatus = getJobStatus($runningJob->horizon_job_id); if ($horizonJobStatus === 'unknown') { - return true; + $horizonJobIds[] = $runningJob->horizon_job_id; } - $horizonJobIds[] = $runningJob->horizon_job_id; } if (count($horizonJobIds) === 0) { echo "No deployments in progress.\n"; From 735fcaad3333706d621c098bc24ee33c4ced39d0 Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Fri, 28 Mar 2025 15:30:21 +0100 Subject: [PATCH 05/17] refactor(shared): add logging for running deployment jobs --- bootstrap/helpers/shared.php | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/bootstrap/helpers/shared.php b/bootstrap/helpers/shared.php index ff8ac4c8a..45982a3f6 100644 --- a/bootstrap/helpers/shared.php +++ b/bootstrap/helpers/shared.php @@ -1250,6 +1250,17 @@ function get_public_ips() function isAnyDeploymentInprogress() { $runningJobs = ApplicationDeploymentQueue::where('horizon_job_worker', gethostname())->where('status', ApplicationDeploymentStatus::IN_PROGRESS->value)->get(); + $basicDetails = $runningJobs->map(function ($job) { + return [ + 'id' => $job->id, + 'created_at' => $job->created_at, + 'application_id' => $job->application_id, + 'server_id' => $job->server_id, + 'horizon_job_id' => $job->horizon_job_id, + 'status' => $job->status, + ]; + }); + echo 'Running jobs: '.json_encode($basicDetails)."\n"; $horizonJobIds = []; foreach ($runningJobs as $runningJob) { $horizonJobStatus = getJobStatus($runningJob->horizon_job_id); From f060b7d3d29947cabc5eeadce689d88b095600af Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Fri, 28 Mar 2025 15:42:25 +0100 Subject: [PATCH 06/17] refactor(shared): enhance job status check to include 'reserved' --- bootstrap/helpers/shared.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bootstrap/helpers/shared.php b/bootstrap/helpers/shared.php index 45982a3f6..7dc636587 100644 --- a/bootstrap/helpers/shared.php +++ b/bootstrap/helpers/shared.php @@ -1264,7 +1264,7 @@ function isAnyDeploymentInprogress() $horizonJobIds = []; foreach ($runningJobs as $runningJob) { $horizonJobStatus = getJobStatus($runningJob->horizon_job_id); - if ($horizonJobStatus === 'unknown') { + if ($horizonJobStatus === 'unknown' || $horizonJobStatus === 'reserved') { $horizonJobIds[] = $runningJob->horizon_job_id; } } From 39cb270eb7244e0ad71c551f81c62221a8e909c7 Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Fri, 28 Mar 2025 18:44:03 +0100 Subject: [PATCH 07/17] refactor(email): improve error handling by passing context to handleError --- app/Livewire/SettingsEmail.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Livewire/SettingsEmail.php b/app/Livewire/SettingsEmail.php index 4205594a5..858f3b187 100644 --- a/app/Livewire/SettingsEmail.php +++ b/app/Livewire/SettingsEmail.php @@ -235,7 +235,7 @@ class SettingsEmail extends Component throw new \Exception('Too many messages sent!'); } } catch (\Throwable $e) { - return handleError($e); + return handleError($e, $this); } } } From 2b046c4bc4d214f24a64ddb6c46920d7f38f2eb4 Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Fri, 28 Mar 2025 18:44:10 +0100 Subject: [PATCH 08/17] refactor(email): streamline email sending logic and improve configuration handling --- app/Notifications/Channels/EmailChannel.php | 133 +++++++------------- 1 file changed, 47 insertions(+), 86 deletions(-) diff --git a/app/Notifications/Channels/EmailChannel.php b/app/Notifications/Channels/EmailChannel.php index 8287fd24b..c9bf8d54a 100644 --- a/app/Notifications/Channels/EmailChannel.php +++ b/app/Notifications/Channels/EmailChannel.php @@ -2,102 +2,63 @@ namespace App\Notifications\Channels; -use App\Models\Team; -use App\Services\ConfigurationRepository; -use Exception; -use Illuminate\Mail\Message; use Illuminate\Notifications\Notification; -use Illuminate\Support\Facades\Mail; +use Resend; class EmailChannel { - private ConfigurationRepository $configRepository; - - public function __construct(ConfigurationRepository $configRepository) - { - $this->configRepository = $configRepository; - } + public function __construct() {} public function send(SendsEmail $notifiable, Notification $notification): void { - try { - $team = data_get($notifiable, 'id'); - $members = Team::find($team)->members; - $mailerType = $this->bootConfigs($notifiable); + $useInstanceEmailSettings = $notifiable->emailNotificationSettings->use_instance_email_settings; + if ($useInstanceEmailSettings) { + $settings = instanceSettings(); + } else { + $settings = $notifiable->emailNotificationSettings; + } + $isResendEnabled = $settings->resend_enabled; + $isSmtpEnabled = $settings->smtp_enabled; + $recipients = $notifiable->getRecipients(); + $mailMessage = $notification->toMail($notifiable); - $recipients = $notifiable->getRecipients(); - if (count($recipients) === 0) { - throw new Exception('No email recipients found'); - } - foreach ($recipients as $recipient) { - // check if the recipient is part of the team - if (! $members->contains('email', $recipient)) { - $emailSettings = $notifiable->emailNotificationSettings; - data_set($emailSettings, 'smtp_password', '********'); - data_set($emailSettings, 'resend_api_key', '********'); - send_internal_notification(sprintf( - "Recipient is not part of the team: %s\nTeam: %s\nNotification: %s\nNotifiable: %s\nMailer Type: %s\nEmail Settings:\n%s", - $recipient, - $team, - get_class($notification), - get_class($notifiable), - $mailerType, - json_encode($emailSettings, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES) - )); - throw new Exception('Recipient is not part of the team'); - } - } + if ($isResendEnabled) { + $resend = Resend::client($settings->resend_api_key); + $resend->emails->send([ + 'from' => $settings->smtp_from_address, + 'to' => $recipients, + 'subject' => $mailMessage->subject, + 'html' => (string) $mailMessage->render(), + ]); + } elseif ($isSmtpEnabled) { + $encryption = match (strtolower($settings->smtp_encryption)) { + 'starttls' => null, + 'tls' => 'tls', + 'none' => null, + default => null, + }; - $mailMessage = $notification->toMail($notifiable); - - Mail::mailer($mailerType)->send( - [], - [], - fn (Message $message) => $message - ->to($recipients) - ->subject($mailMessage->subject) - ->html((string) $mailMessage->render()) + $transport = new \Symfony\Component\Mailer\Transport\Smtp\EsmtpTransport( + $settings->smtp_host, + $settings->smtp_port, + $encryption ); - } catch (Exception $e) { - $error = $e->getMessage(); - if ($error === 'No email settings found.') { - throw $e; - } - $message = "EmailChannel error: {$e->getMessage()}. Failed to send email to:"; - if (isset($recipients)) { - $message .= implode(', ', $recipients); - } - if (isset($mailMessage)) { - $message .= " with subject: {$mailMessage->subject}"; - } - send_internal_notification($message); - throw $e; + $transport->setUsername($settings->smtp_username); + $transport->setPassword($settings->smtp_password); + + $mailer = new \Symfony\Component\Mailer\Mailer($transport); + + $fromEmail = $settings->smtp_from_address ?? 'noreply@localhost'; + $fromName = $settings->smtp_from_name ?? 'System'; + $from = new \Symfony\Component\Mime\Address($fromEmail, $fromName); + + $email = (new \Symfony\Component\Mime\Email) + ->from($from) + ->to(...$recipients) + ->subject($mailMessage->subject) + ->html((string) $mailMessage->render()); + + $mailer->send($email); } } - - private function bootConfigs($notifiable): string - { - $emailSettings = $notifiable->emailNotificationSettings; - - if ($emailSettings->use_instance_email_settings) { - $type = set_transanctional_email_settings(); - if (blank($type)) { - throw new Exception('No email settings found.'); - } - - return $type; - } - - $this->configRepository->updateMailConfig($emailSettings); - - if ($emailSettings->resend_enabled) { - return 'resend'; - } - - if ($emailSettings->smtp_enabled) { - return 'smtp'; - } - - throw new Exception('No email settings found.'); - } } From 6d9887afbad09f5826a90430ca09f05dfd7ca002 Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Fri, 28 Mar 2025 18:46:46 +0100 Subject: [PATCH 09/17] refactor(email): remove unnecessary whitespace in email sending logic --- app/Notifications/Channels/EmailChannel.php | 1 - 1 file changed, 1 deletion(-) diff --git a/app/Notifications/Channels/EmailChannel.php b/app/Notifications/Channels/EmailChannel.php index c9bf8d54a..e29b99f5f 100644 --- a/app/Notifications/Channels/EmailChannel.php +++ b/app/Notifications/Channels/EmailChannel.php @@ -51,7 +51,6 @@ class EmailChannel $fromEmail = $settings->smtp_from_address ?? 'noreply@localhost'; $fromName = $settings->smtp_from_name ?? 'System'; $from = new \Symfony\Component\Mime\Address($fromEmail, $fromName); - $email = (new \Symfony\Component\Mime\Email) ->from($from) ->to(...$recipients) From ebb81aff68c7a445901d6af223a448936941a61d Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Fri, 28 Mar 2025 19:09:36 +0100 Subject: [PATCH 10/17] refactor(email): allow custom email recipients in email sending logic --- app/Notifications/Channels/EmailChannel.php | 7 ++++++- resources/views/livewire/notifications/email.blade.php | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/app/Notifications/Channels/EmailChannel.php b/app/Notifications/Channels/EmailChannel.php index e29b99f5f..582d9a1e4 100644 --- a/app/Notifications/Channels/EmailChannel.php +++ b/app/Notifications/Channels/EmailChannel.php @@ -12,6 +12,7 @@ class EmailChannel public function send(SendsEmail $notifiable, Notification $notification): void { $useInstanceEmailSettings = $notifiable->emailNotificationSettings->use_instance_email_settings; + $customEmails = data_get($notification, 'emails', null); if ($useInstanceEmailSettings) { $settings = instanceSettings(); } else { @@ -19,7 +20,11 @@ class EmailChannel } $isResendEnabled = $settings->resend_enabled; $isSmtpEnabled = $settings->smtp_enabled; - $recipients = $notifiable->getRecipients(); + if ($customEmails) { + $recipients = [$customEmails]; + } else { + $recipients = $notifiable->getRecipients(); + } $mailMessage = $notification->toMail($notifiable); if ($isResendEnabled) { diff --git a/resources/views/livewire/notifications/email.blade.php b/resources/views/livewire/notifications/email.blade.php index 7b0878b25..194cb3b43 100644 --- a/resources/views/livewire/notifications/email.blade.php +++ b/resources/views/livewire/notifications/email.blade.php @@ -14,7 +14,7 @@
+ id="testEmailAddress" label="Recipient" required /> Send Email From d110c93ba9c5e6ddf805c02917ab2882db2c419a Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Fri, 28 Mar 2025 20:44:28 +0100 Subject: [PATCH 11/17] refactor(email): enhance sender information formatting in email logic --- app/Notifications/Channels/EmailChannel.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/Notifications/Channels/EmailChannel.php b/app/Notifications/Channels/EmailChannel.php index 582d9a1e4..a452ef8dd 100644 --- a/app/Notifications/Channels/EmailChannel.php +++ b/app/Notifications/Channels/EmailChannel.php @@ -29,8 +29,9 @@ class EmailChannel if ($isResendEnabled) { $resend = Resend::client($settings->resend_api_key); + $from = "{$settings->smtp_from_name} <{$settings->smtp_from_address}>"; $resend->emails->send([ - 'from' => $settings->smtp_from_address, + 'from' => $from, 'to' => $recipients, 'subject' => $mailMessage->subject, 'html' => (string) $mailMessage->render(), From 0b413780148a8a68588aff623e68996a1bcf13b0 Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Fri, 28 Mar 2025 20:54:27 +0100 Subject: [PATCH 12/17] refactor(proxy): remove redundant stop call in restart method --- app/Livewire/Server/Proxy/Deploy.php | 1 - 1 file changed, 1 deletion(-) diff --git a/app/Livewire/Server/Proxy/Deploy.php b/app/Livewire/Server/Proxy/Deploy.php index f823ff3d4..4a7e4124e 100644 --- a/app/Livewire/Server/Proxy/Deploy.php +++ b/app/Livewire/Server/Proxy/Deploy.php @@ -65,7 +65,6 @@ class Deploy extends Component public function restart() { try { - $this->stop(); $this->dispatch('checkProxy'); } catch (\Throwable $e) { return handleError($e, $this); From 7686ebfd6ce622740018795a568aba76410e1ba4 Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Fri, 28 Mar 2025 21:05:34 +0100 Subject: [PATCH 13/17] refactor(file-storage): add loadStorageOnServer method for improved error handling --- app/Livewire/Project/Service/FileStorage.php | 13 ++++++++++++- .../livewire/project/service/file-storage.blade.php | 1 + 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/app/Livewire/Project/Service/FileStorage.php b/app/Livewire/Project/Service/FileStorage.php index 4d070bc0c..5b88c15eb 100644 --- a/app/Livewire/Project/Service/FileStorage.php +++ b/app/Livewire/Project/Service/FileStorage.php @@ -49,7 +49,6 @@ class FileStorage extends Component $this->workdir = null; $this->fs_path = $this->fileStorage->fs_path; } - $this->fileStorage->loadStorageOnServer(); } public function convertToDirectory() @@ -68,6 +67,18 @@ class FileStorage extends Component } } + public function loadStorageOnServer() + { + try { + $this->fileStorage->loadStorageOnServer(); + $this->dispatch('success', 'File storage loaded from server.'); + } catch (\Throwable $e) { + return handleError($e, $this); + } finally { + $this->dispatch('refreshStorages'); + } + } + public function convertToFile() { try { diff --git a/resources/views/livewire/project/service/file-storage.blade.php b/resources/views/livewire/project/service/file-storage.blade.php index 6010000c4..c1479a9f9 100644 --- a/resources/views/livewire/project/service/file-storage.blade.php +++ b/resources/views/livewire/project/service/file-storage.blade.php @@ -39,6 +39,7 @@ confirmationLabel="Please confirm the execution of the actions by entering the Filepath below" shortConfirmationLabel="Filepath" :confirmWithPassword="false" step2ButtonText="Convert to directory" /> @endif + Load from server Date: Fri, 28 Mar 2025 21:11:28 +0100 Subject: [PATCH 14/17] refactor(docker): parse and sanitize YAML compose file before encoding --- bootstrap/helpers/docker.php | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/bootstrap/helpers/docker.php b/bootstrap/helpers/docker.php index 80e19d80f..de80adbef 100644 --- a/bootstrap/helpers/docker.php +++ b/bootstrap/helpers/docker.php @@ -8,6 +8,7 @@ use App\Models\ServiceApplication; use Illuminate\Support\Collection; use Illuminate\Support\Str; use Spatie\Url\Url; +use Symfony\Component\Yaml\Yaml; use Visus\Cuid2\Cuid2; function getCurrentApplicationContainerStatus(Server $server, int $id, ?int $pullRequestId = null, ?bool $includePullrequests = false): Collection @@ -834,7 +835,15 @@ function validateComposeFile(string $compose, int $server_id): string|Throwable if (! $server) { throw new \Exception('Server not found'); } - $base64_compose = base64_encode($compose); + $yaml_compose = Yaml::parse($compose); + foreach ($yaml_compose['services'] as $service_name => $service) { + foreach ($service['volumes'] as $volume_name => $volume) { + if (data_get($volume, 'type') === 'bind' && data_get($volume, 'content')) { + unset($yaml_compose['services'][$service_name]['volumes'][$volume_name]['content']); + } + } + } + $base64_compose = base64_encode(Yaml::dump($yaml_compose)); instant_remote_process([ "echo {$base64_compose} | base64 -d | tee /tmp/{$uuid}.yml > /dev/null", "chmod 600 /tmp/{$uuid}.yml", From 0bb47dfa566bb4635cb17988eccd5fb74bd525f2 Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Fri, 28 Mar 2025 22:10:15 +0100 Subject: [PATCH 15/17] refactor(file-storage): improve layout and structure of input fields --- .../project/service/file-storage.blade.php | 17 ++--- .../project/shared/storages/show.blade.php | 76 ++++++++++--------- 2 files changed, 47 insertions(+), 46 deletions(-) diff --git a/resources/views/livewire/project/service/file-storage.blade.php b/resources/views/livewire/project/service/file-storage.blade.php index c1479a9f9..594f9f7cc 100644 --- a/resources/views/livewire/project/service/file-storage.blade.php +++ b/resources/views/livewire/project/service/file-storage.blade.php @@ -1,16 +1,9 @@ -
+
- {{-- @if (data_get($resource, 'build_pack') === 'dockercompose') -

{{ data_get($resource, 'name', 'unknown') }}

- @endif --}} - @if ($fileStorage->is_directory) -

Directory Mount

- @else -

File Mount

- @endif - - - +
+ + +
diff --git a/resources/views/livewire/project/shared/storages/show.blade.php b/resources/views/livewire/project/shared/storages/show.blade.php index f64e5d77b..339942ccb 100644 --- a/resources/views/livewire/project/shared/storages/show.blade.php +++ b/resources/views/livewire/project/shared/storages/show.blade.php @@ -2,45 +2,53 @@ @if ($isReadOnly) @if ($isFirst) - @if ( - $storage->resource_type === 'App\Models\ServiceApplication' || - $storage->resource_type === 'App\Models\ServiceDatabase') - - @else - - @endif - @if ($isService || $startedAt) - - - @else - - - - Update - - @endif +
+ @if ( + $storage->resource_type === 'App\Models\ServiceApplication' || + $storage->resource_type === 'App\Models\ServiceDatabase') + + @else + + @endif + @if ($isService || $startedAt) + + + @else + + + + Update + + @endif +
@else - - - +
+ + + +
@endif @else @if ($isFirst) - - - +
+ + + +
@else - - - +
+ + + +
@endif
From c2941abe572f1881bdcbe456fcabd09318995f2d Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Fri, 28 Mar 2025 22:10:33 +0100 Subject: [PATCH 16/17] fix(file-storage): double save on compose volumes --- app/Models/LocalFileVolume.php | 15 +++++++ bootstrap/helpers/shared.php | 73 ++++++++++++++++------------------ 2 files changed, 49 insertions(+), 39 deletions(-) diff --git a/app/Models/LocalFileVolume.php b/app/Models/LocalFileVolume.php index a3bbbc64a..1a5430c5b 100644 --- a/app/Models/LocalFileVolume.php +++ b/app/Models/LocalFileVolume.php @@ -176,4 +176,19 @@ class LocalFileVolume extends BaseModel return instant_remote_process($commands, $server); } + + // Accessor for convenient access + protected function plainMountPath(): Attribute + { + return Attribute::make( + get: fn () => $this->mount_path, + set: fn ($value) => $this->mount_path = $value + ); + } + + // Scope for searching + public function scopeWherePlainMountPath($query, $path) + { + return $query->get()->where('plain_mount_path', $path); + } } diff --git a/bootstrap/helpers/shared.php b/bootstrap/helpers/shared.php index 7dc636587..218ca1b37 100644 --- a/bootstrap/helpers/shared.php +++ b/bootstrap/helpers/shared.php @@ -1363,21 +1363,15 @@ function parseServiceVolumes($serviceVolumes, $resource, $topLevelVolumes, $pull $source = $source."-pr-$pull_request_id"; } if (! $resource?->settings?->is_preserve_repository_enabled || $foundConfig?->is_based_on_git) { - LocalFileVolume::updateOrCreate( - [ - 'mount_path' => $target, - 'resource_id' => $resource->id, - 'resource_type' => get_class($resource), - ], - [ - 'fs_path' => $source, - 'mount_path' => $target, - 'content' => $content, - 'is_directory' => $isDirectory, - 'resource_id' => $resource->id, - 'resource_type' => get_class($resource), - ] - ); + $volume = LocalFileVolume::wherePlainMountPath($target)->first() ?? new LocalFileVolume; + $volume->fill([ + 'fs_path' => $source, + 'mount_path' => $target, + 'content' => $content, + 'is_directory' => $isDirectory, + 'resource_id' => $resource->id, + 'resource_type' => get_class($resource), + ])->save(); } } elseif ($type->value() === 'volume') { if ($topLevelVolumes->has($source->value())) { @@ -1675,21 +1669,28 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal if ($source->value() === '/tmp' || $source->value() === '/tmp/') { return $volume; } - LocalFileVolume::updateOrCreate( - [ - 'mount_path' => $target, - 'resource_id' => $savedService->id, - 'resource_type' => get_class($savedService), - ], - [ + + $existingVolume = LocalFileVolume::wherePlainMountPath($target)->first(); + + if ($existingVolume) { + $existingVolume->update([ 'fs_path' => $source, 'mount_path' => $target, 'content' => $content, 'is_directory' => $isDirectory, 'resource_id' => $savedService->id, 'resource_type' => get_class($savedService), - ] - ); + ]); + } else { + LocalFileVolume::create([ + 'fs_path' => $source, + 'mount_path' => $target, + 'content' => $content, + 'is_directory' => $isDirectory, + 'resource_id' => $savedService->id, + 'resource_type' => get_class($savedService), + ]); + } } elseif ($type->value() === 'volume') { if ($topLevelVolumes->has($source->value())) { $v = $topLevelVolumes->get($source->value()); @@ -3327,21 +3328,15 @@ function newParser(Application|Service $resource, int $pull_request_id = 0, ?int if ($isApplication && $isPullRequest) { $source = $source."-pr-$pullRequestId"; } - LocalFileVolume::updateOrCreate( - [ - 'mount_path' => $target, - 'resource_id' => $originalResource->id, - 'resource_type' => get_class($originalResource), - ], - [ - 'fs_path' => $source, - 'mount_path' => $target, - 'content' => $content, - 'is_directory' => $isDirectory, - 'resource_id' => $originalResource->id, - 'resource_type' => get_class($originalResource), - ] - ); + $volume = LocalFileVolume::wherePlainMountPath($target)->first() ?? new LocalFileVolume; + $volume->fill([ + 'fs_path' => $source, + 'mount_path' => $target, + 'content' => $content, + 'is_directory' => $isDirectory, + 'resource_id' => $originalResource->id, + 'resource_type' => get_class($originalResource), + ])->save(); if (isDev()) { if ((int) $resource->compose_parsing_version >= 4) { if ($isApplication) { From d124abef2f46f53235166a74f6e379786b05fecf Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Fri, 28 Mar 2025 22:18:07 +0100 Subject: [PATCH 17/17] refactor(email): update label for test email recipient input --- resources/views/livewire/settings-email.blade.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/views/livewire/settings-email.blade.php b/resources/views/livewire/settings-email.blade.php index 02523bbcc..4376cbf92 100644 --- a/resources/views/livewire/settings-email.blade.php +++ b/resources/views/livewire/settings-email.blade.php @@ -13,7 +13,7 @@ + label="Recipient" required /> Send Email