From 953bcfb5bb862c5a079dae678fa2939492db2222 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Fri, 8 Sep 2023 12:23:46 +0200 Subject: [PATCH 1/5] fix: db backup job --- app/Jobs/DatabaseBackupJob.php | 4 ++++ config/sentry.php | 2 +- config/version.php | 2 +- versions.json | 2 +- 4 files changed, 7 insertions(+), 3 deletions(-) diff --git a/app/Jobs/DatabaseBackupJob.php b/app/Jobs/DatabaseBackupJob.php index 98972f7af..aaef43883 100644 --- a/app/Jobs/DatabaseBackupJob.php +++ b/app/Jobs/DatabaseBackupJob.php @@ -46,6 +46,10 @@ class DatabaseBackupJob implements ShouldQueue $this->backup = $backup; $this->team = Team::find($backup->team_id); $this->database = $this->backup->database; + if (!$this->database) { + ray('Database not found'); + return; + } $this->database_type = $this->database->type(); $this->server = $this->database->destination->server; $this->database_status = $this->database->status; diff --git a/config/sentry.php b/config/sentry.php index 1cf53df07..d8316f2a6 100644 --- a/config/sentry.php +++ b/config/sentry.php @@ -7,7 +7,7 @@ return [ // 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.27', + 'release' => '4.0.0-beta.28', 'server_name' => env('APP_ID', 'coolify'), // 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 0f148cc4e..6ded6b968 100644 --- a/config/version.php +++ b/config/version.php @@ -1,3 +1,3 @@ Date: Fri, 8 Sep 2023 14:15:28 +0200 Subject: [PATCH 2/5] feat: Telegram topics separation --- .../Notifications/TelegramSettings.php | 4 ++ app/Jobs/SendMessageToTelegramJob.php | 5 +- app/Models/Team.php | 2 +- .../Channels/TelegramChannel.php | 20 ++++++- ...2_071056_update_telegram_notifications.php | 29 ++++++++++ .../notifications/telegram-settings.blade.php | 57 +++++++++++++------ 6 files changed, 95 insertions(+), 22 deletions(-) create mode 100644 database/migrations/2023_08_22_071056_update_telegram_notifications.php diff --git a/app/Http/Livewire/Notifications/TelegramSettings.php b/app/Http/Livewire/Notifications/TelegramSettings.php index be7081012..d6c6c8395 100644 --- a/app/Http/Livewire/Notifications/TelegramSettings.php +++ b/app/Http/Livewire/Notifications/TelegramSettings.php @@ -17,6 +17,10 @@ class TelegramSettings extends Component 'team.telegram_notifications_deployments' => 'nullable|boolean', 'team.telegram_notifications_status_changes' => 'nullable|boolean', 'team.telegram_notifications_database_backups' => 'nullable|boolean', + 'team.telegram_notifications_test_message_thread_id' => 'nullable|string', + 'team.telegram_notifications_deployments_message_thread_id' => 'nullable|string', + 'team.telegram_notifications_status_changes_message_thread_id' => 'nullable|string', + 'team.telegram_notifications_database_backups_message_thread_id' => 'nullable|string', ]; protected $validationAttributes = [ 'team.telegram_token' => 'Token', diff --git a/app/Jobs/SendMessageToTelegramJob.php b/app/Jobs/SendMessageToTelegramJob.php index 08afbab23..1fa1347c4 100644 --- a/app/Jobs/SendMessageToTelegramJob.php +++ b/app/Jobs/SendMessageToTelegramJob.php @@ -31,6 +31,7 @@ class SendMessageToTelegramJob implements ShouldQueue public array $buttons, public string $token, public string $chatId, + public ?string $topicId = null, ) { } @@ -63,7 +64,9 @@ class SendMessageToTelegramJob implements ShouldQueue 'chat_id' => $this->chatId, 'text' => $this->text, ]; - ray($payload); + if ($this->topicId) { + $payload['message_thread_id'] = $this->topicId; + } $response = Http::post($url, $payload); if ($response->failed()) { throw new \Exception('Telegram notification failed with ' . $response->status() . ' status code.' . $response->body()); diff --git a/app/Models/Team.php b/app/Models/Team.php index 2d7ef3c9e..485811a17 100644 --- a/app/Models/Team.php +++ b/app/Models/Team.php @@ -28,7 +28,7 @@ class Team extends Model implements SendsDiscord, SendsEmail { return [ "token" => data_get($this, 'telegram_token', null), - "chat_id" => data_get($this, 'telegram_chat_id', null) + "chat_id" => data_get($this, 'telegram_chat_id', null), ]; } diff --git a/app/Notifications/Channels/TelegramChannel.php b/app/Notifications/Channels/TelegramChannel.php index 938ef5d25..5dbc7e049 100644 --- a/app/Notifications/Channels/TelegramChannel.php +++ b/app/Notifications/Channels/TelegramChannel.php @@ -10,16 +10,30 @@ class TelegramChannel { $data = $notification->toTelegram($notifiable); $telegramData = $notifiable->routeNotificationForTelegram(); - $message = data_get($data, 'message'); $buttons = data_get($data, 'buttons', []); - ray($message, $buttons); $telegramToken = data_get($telegramData, 'token'); $chatId = data_get($telegramData, 'chat_id'); + $topicId = null; + $topicsInstance = get_class($notification); + switch ($topicsInstance) { + case 'App\Notifications\StatusChange': + $topicId = data_get($notifiable, 'telegram_notifications_status_changes_message_thread_id'); + break; + case 'App\Notifications\Test': + $topicId = data_get($notifiable, 'telegram_notifications_test_message_thread_id'); + break; + case 'App\Notifications\Deployment': + $topicId = data_get($notifiable, 'telegram_notifications_deployments_message_thread_id'); + break; + case 'App\Notifications\DatabaseBackup': + $topicId = data_get($notifiable, 'telegram_notifications_database_backups_message_thread_id'); + break; + } if (!$telegramToken || !$chatId || !$message) { throw new \Exception('Telegram token, chat id and message are required'); } - dispatch(new SendMessageToTelegramJob($message, $buttons, $telegramToken, $chatId)); + dispatch(new SendMessageToTelegramJob($message, $buttons, $telegramToken, $chatId, $topicId)); } } diff --git a/database/migrations/2023_08_22_071056_update_telegram_notifications.php b/database/migrations/2023_08_22_071056_update_telegram_notifications.php new file mode 100644 index 000000000..6e1da18e3 --- /dev/null +++ b/database/migrations/2023_08_22_071056_update_telegram_notifications.php @@ -0,0 +1,29 @@ +text('telegram_notifications_test_message_thread_id')->nullable(); + $table->text('telegram_notifications_deployments_message_thread_id')->nullable(); + $table->text('telegram_notifications_status_changes_message_thread_id')->nullable(); + $table->text('telegram_notifications_database_backups_message_thread_id')->nullable(); + }); + } + + public function down(): void + { + Schema::table('teams', function (Blueprint $table) { + $table->dropColumn('telegram_message_thread_id'); + $table->dropColumn('telegram_notifications_test_message_thread_id'); + $table->dropColumn('telegram_notifications_deployments_message_thread_id'); + $table->dropColumn('telegram_notifications_status_changes_message_thread_id'); + $table->dropColumn('telegram_notifications_database_backups_message_thread_id'); + }); + } +}; diff --git a/resources/views/livewire/notifications/telegram-settings.blade.php b/resources/views/livewire/notifications/telegram-settings.blade.php index 654ca106d..12b62af4d 100644 --- a/resources/views/livewire/notifications/telegram-settings.blade.php +++ b/resources/views/livewire/notifications/telegram-settings.blade.php @@ -16,27 +16,50 @@
- - +
- @if (data_get($team, 'telegram_enabled')) -

Subscribe to events

-
+

Subscribe to events

+
@if (isDev()) - +

Test

+
+ + +
@endif -

General

- -

Applications

- -

Databases

- +

Container Status Changes

+
+ + +
+

Application Deployments

+
+ + +
+

Backup Status

+
+ + +
- @endif + @endif +
From e4a51cc1163d531eb08eeab826a912bb270d7341 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Fri, 8 Sep 2023 16:16:28 +0200 Subject: [PATCH 3/5] fix: sentry 4459819517 --- app/Notifications/Channels/TelegramChannel.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Notifications/Channels/TelegramChannel.php b/app/Notifications/Channels/TelegramChannel.php index 5dbc7e049..1401bb324 100644 --- a/app/Notifications/Channels/TelegramChannel.php +++ b/app/Notifications/Channels/TelegramChannel.php @@ -32,7 +32,7 @@ class TelegramChannel break; } if (!$telegramToken || !$chatId || !$message) { - throw new \Exception('Telegram token, chat id and message are required'); + return; } dispatch(new SendMessageToTelegramJob($message, $buttons, $telegramToken, $chatId, $topicId)); } From f6737f21dd9998c75addaab93abaf43c8b72260c Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Fri, 8 Sep 2023 16:16:59 +0200 Subject: [PATCH 4/5] feat: developer view for env variables --- .../Shared/EnvironmentVariable/All.php | 67 ++++++++++++++++++- app/Http/Middleware/IsBoardingFlow.php | 2 +- app/Models/Application.php | 4 +- app/Models/EnvironmentVariable.php | 17 +++-- bootstrap/helpers/shared.php | 22 ++++++ .../shared/environment-variable/all.blade.php | 45 +++++++++---- 6 files changed, 131 insertions(+), 26 deletions(-) diff --git a/app/Http/Livewire/Project/Shared/EnvironmentVariable/All.php b/app/Http/Livewire/Project/Shared/EnvironmentVariable/All.php index 70bfd42a1..899060085 100644 --- a/app/Http/Livewire/Project/Shared/EnvironmentVariable/All.php +++ b/app/Http/Livewire/Project/Shared/EnvironmentVariable/All.php @@ -5,21 +5,84 @@ namespace App\Http\Livewire\Project\Shared\EnvironmentVariable; use App\Models\EnvironmentVariable; use Livewire\Component; use Visus\Cuid2\Cuid2; +use Str; class All extends Component { public $resource; + public bool $showPreview = false; public string|null $modalId = null; + public ?string $variables = null; + public ?string $variablesPreview = null; + public string $view = 'normal'; protected $listeners = ['refreshEnvs', 'submit']; public function mount() { + $resourceClass = get_class($this->resource); + $resourceWithPreviews = ['App\Models\Application']; + $simpleDockerfile = !is_null(data_get($this->resource, 'dockerfile')); + if (Str::of($resourceClass)->contains($resourceWithPreviews) && !$simpleDockerfile) { + $this->showPreview = true; + } $this->modalId = new Cuid2(7); + $this->getDevView(); + } + public function getDevView() + { + $this->variables = $this->resource->environment_variables->map(function ($item) { + return "$item->key=$item->value"; + })->sort()->join(' +'); + if ($this->showPreview) { + $this->variablesPreview = $this->resource->environment_variables_preview->map(function ($item) { + return "$item->key=$item->value"; + })->sort()->join(' +'); + } + } + public function switch() + { + $this->view = $this->view === 'normal' ? 'dev' : 'normal'; + } + public function saveVariables($isPreview) + { + if ($isPreview) { + $variables = parseEnvFormatToArray($this->variablesPreview); + $existingVariables = $this->resource->environment_variables_preview(); + $this->resource->environment_variables_preview()->delete(); + } else { + $variables = parseEnvFormatToArray($this->variables); + $existingVariables = $this->resource->environment_variables(); + $this->resource->environment_variables()->delete(); + } + foreach ($variables as $key => $variable) { + $found = $existingVariables->where('key', $key)->first(); + if ($found) { + $found->value = $variable; + $found->save(); + continue; + } else { + $environment = new EnvironmentVariable(); + $environment->key = $key; + $environment->value = $variable; + $environment->is_build_time = false; + $environment->is_preview = $isPreview ? true : false; + if ($this->resource->type() === 'application') { + $environment->application_id = $this->resource->id; + } + if ($this->resource->type() === 'standalone-postgresql') { + $environment->standalone_postgresql_id = $this->resource->id; + } + $environment->save(); + } + } + $this->refreshEnvs(); } - public function refreshEnvs() { $this->resource->refresh(); + $this->getDevView(); } public function submit($data) @@ -43,7 +106,7 @@ class All extends Component $environment->standalone_postgresql_id = $this->resource->id; } $environment->save(); - $this->resource->refresh(); + $this->refreshEnvs(); $this->emit('success', 'Environment variable added successfully.'); } catch (\Exception $e) { return general_error_handler(err: $e, that: $this); diff --git a/app/Http/Middleware/IsBoardingFlow.php b/app/Http/Middleware/IsBoardingFlow.php index e0542a57a..5858fe191 100644 --- a/app/Http/Middleware/IsBoardingFlow.php +++ b/app/Http/Middleware/IsBoardingFlow.php @@ -15,7 +15,7 @@ class IsBoardingFlow */ public function handle(Request $request, Closure $next): Response { - ray()->showQueries()->color('orange'); + // ray()->showQueries()->color('orange'); if (showBoarding() && !in_array($request->path(), allowedPathsForBoardingAccounts())) { return redirect('boarding'); } diff --git a/app/Models/Application.php b/app/Models/Application.php index 6b730edee..72d2be60f 100644 --- a/app/Models/Application.php +++ b/app/Models/Application.php @@ -105,7 +105,7 @@ class Application extends BaseModel public function environment_variables(): HasMany { - return $this->hasMany(EnvironmentVariable::class)->where('is_preview', false); + return $this->hasMany(EnvironmentVariable::class)->where('is_preview', false)->orderBy('key', 'asc'); } public function runtime_environment_variables(): HasMany @@ -127,7 +127,7 @@ class Application extends BaseModel public function environment_variables_preview(): HasMany { - return $this->hasMany(EnvironmentVariable::class)->where('is_preview', true); + return $this->hasMany(EnvironmentVariable::class)->where('is_preview', true)->orderBy('key', 'asc'); } public function runtime_environment_variables_preview(): HasMany diff --git a/app/Models/EnvironmentVariable.php b/app/Models/EnvironmentVariable.php index 62a08c87f..3f348c42e 100644 --- a/app/Models/EnvironmentVariable.php +++ b/app/Models/EnvironmentVariable.php @@ -20,13 +20,16 @@ class EnvironmentVariable extends Model { static::created(function ($environment_variable) { if ($environment_variable->application_id && !$environment_variable->is_preview) { - ModelsEnvironmentVariable::create([ - 'key' => $environment_variable->key, - 'value' => $environment_variable->value, - 'is_build_time' => $environment_variable->is_build_time, - 'application_id' => $environment_variable->application_id, - 'is_preview' => true, - ]); + $found = ModelsEnvironmentVariable::where('key', $environment_variable->key)->where('application_id', $environment_variable->application_id)->where('is_preview',true)->first(); + if (!$found) { + ModelsEnvironmentVariable::create([ + 'key' => $environment_variable->key, + 'value' => $environment_variable->value, + 'is_build_time' => $environment_variable->is_build_time, + 'application_id' => $environment_variable->application_id, + 'is_preview' => true, + ]); + } } }); } diff --git a/bootstrap/helpers/shared.php b/bootstrap/helpers/shared.php index 15f8fc0db..161675301 100644 --- a/bootstrap/helpers/shared.php +++ b/bootstrap/helpers/shared.php @@ -296,3 +296,25 @@ function setNotificationChannels($notifiable, $event) } return $channels; } +function parseEnvFormatToArray($env_file_contents) { + $env_array = array(); + $lines = explode("\n", $env_file_contents); + foreach ($lines as $line) { + if ($line === '' || substr($line, 0, 1) === '#') { + continue; + } + $equals_pos = strpos($line, '='); + if ($equals_pos !== false) { + $key = substr($line, 0, $equals_pos); + $value = substr($line, $equals_pos + 1); + if (substr($value, 0, 1) === '"' && substr($value, -1) === '"') { + $value = substr($value, 1, -1); + } + elseif (substr($value, 0, 1) === "'" && substr($value, -1) === "'") { + $value = substr($value, 1, -1); + } + $env_array[$key] = $value; + } + } + return $env_array; +} diff --git a/resources/views/livewire/project/shared/environment-variable/all.blade.php b/resources/views/livewire/project/shared/environment-variable/all.blade.php index b7b6b8340..9ffb6b217 100644 --- a/resources/views/livewire/project/shared/environment-variable/all.blade.php +++ b/resources/views/livewire/project/shared/environment-variable/all.blade.php @@ -4,23 +4,40 @@

Environment Variables

+ Add + {{ $view === 'normal' ? 'Developer view' : 'Normal view' }} -
Environment (secrets) variables for this resource.
+
Environment variables (secrets) for this resource.
- @forelse ($resource->environment_variables as $env) - - @empty -
No environment variables found.
- @endforelse - @if ($resource->type() === 'application' && $resource->environment_variables_preview->count() > 0) -
-

Preview Deployments

-
Environment (secrets) variables for Preview Deployments.
-
- @foreach ($resource->environment_variables_preview as $env) + @if ($view === 'normal') + @forelse ($resource->environment_variables as $env) - @endforeach + @empty +
No environment variables found.
+ @endforelse + @if ($resource->type() === 'application' && $resource->environment_variables_preview->count() > 0 && $showPreview) +
+

Preview Deployments

+
Environment (secrets) variables for Preview Deployments.
+
+ @foreach ($resource->environment_variables_preview as $env) + + @endforeach + @endif + @else +
+ + Save +
+ @if ($showPreview) +
+ + Save +
+ @endif @endif From 8afa98a1ca76de124c94c9ad69559be6d710818f Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Fri, 8 Sep 2023 16:19:45 +0200 Subject: [PATCH 5/5] fix: sentry 4451028626 --- app/Models/StandaloneDocker.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Models/StandaloneDocker.php b/app/Models/StandaloneDocker.php index 6ecc46a97..6f2ea7673 100644 --- a/app/Models/StandaloneDocker.php +++ b/app/Models/StandaloneDocker.php @@ -23,6 +23,6 @@ class StandaloneDocker extends BaseModel public function attachedTo() { - return $this->applications->count() > 0 || $this->databases->count() > 0; + return $this->applications?->count() > 0 || $this->databases?->count() > 0; } }