From 42c143d19e6775b38509226568804e624cc42157 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Thu, 28 Mar 2024 09:01:40 +0100 Subject: [PATCH 01/20] ui: backup executions --- config/sentry.php | 2 +- config/version.php | 2 +- .../livewire/project/database/backup-executions.blade.php | 4 ++-- versions.json | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/config/sentry.php b/config/sentry.php index 89345d082..bef8d46c8 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.248', + 'release' => '4.0.0-beta.249', // 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 642ee812d..cabb9ad06 100644 --- a/config/version.php +++ b/config/version.php @@ -1,3 +1,3 @@ @forelse($executions as $execution)
data_get($execution, 'status') === 'success', 'border-red-500' => data_get($execution, 'status') === 'failed', ])> @@ -23,7 +23,7 @@
@if (data_get($execution, 'status') === 'success') - Download @endif diff --git a/versions.json b/versions.json index 80acebb25..a88c686c8 100644 --- a/versions.json +++ b/versions.json @@ -1,7 +1,7 @@ { "coolify": { "v4": { - "version": "4.0.0-beta.248" + "version": "4.0.0-beta.249" } } } From 5db045f3927a6e304717571e9c529c4d36b18670 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Thu, 28 Mar 2024 09:20:21 +0100 Subject: [PATCH 02/20] Refactor deployment index.blade.php to add flex-col class --- .../livewire/project/application/deployment/index.blade.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/views/livewire/project/application/deployment/index.blade.php b/resources/views/livewire/project/application/deployment/index.blade.php index 03a8a0d8a..aaffeaee1 100644 --- a/resources/views/livewire/project/application/deployment/index.blade.php +++ b/resources/views/livewire/project/application/deployment/index.blade.php @@ -27,7 +27,7 @@ @endif @forelse ($deployments as $deployment) data_get($deployment, 'status') === 'queued', 'border-warning hover:bg-warning hover:text-black' => From db5ff7f16d6785a524c0a38fc30d27e2b62ec6dd Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Thu, 28 Mar 2024 09:25:42 +0100 Subject: [PATCH 03/20] Update CSS and Blade file --- resources/css/app.css | 3 +++ .../livewire/project/application/deployment/index.blade.php | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/resources/css/app.css b/resources/css/app.css index b7965ebbc..3f5a4f48c 100644 --- a/resources/css/app.css +++ b/resources/css/app.css @@ -203,6 +203,9 @@ tr td:first-child { .box-without-bg { @apply flex p-2 transition-colors dark:hover:text-white hover:no-underline min-h-[4rem] border border-neutral-200 dark:border-black; } +.box-without-bg-without-border { + @apply flex p-2 transition-colors dark:hover:text-white hover:no-underline min-h-[4rem] ; +} .on-box { @apply rounded hover:bg-neutral-300 dark:hover:bg-coolgray-500/20; diff --git a/resources/views/livewire/project/application/deployment/index.blade.php b/resources/views/livewire/project/application/deployment/index.blade.php index aaffeaee1..e47fab967 100644 --- a/resources/views/livewire/project/application/deployment/index.blade.php +++ b/resources/views/livewire/project/application/deployment/index.blade.php @@ -27,7 +27,7 @@ @endif @forelse ($deployments as $deployment) data_get($deployment, 'status') === 'queued', 'border-warning hover:bg-warning hover:text-black' => From 971b17b36414e89715197164165eb0b8fce79675 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Thu, 28 Mar 2024 12:30:06 +0100 Subject: [PATCH 04/20] ui fixes --- resources/css/app.css | 4 ++-- resources/views/components/internal-link.blade.php | 4 +++- resources/views/components/pricing-plans.blade.php | 4 ++-- .../views/livewire/server/resources.blade.php | 14 +++++++------- .../views/livewire/source/github/change.blade.php | 6 +++--- .../views/livewire/team/invitations.blade.php | 6 +++--- .../views/livewire/team/member/index.blade.php | 4 ++-- 7 files changed, 22 insertions(+), 20 deletions(-) diff --git a/resources/css/app.css b/resources/css/app.css index 3f5a4f48c..c2ca9f612 100644 --- a/resources/css/app.css +++ b/resources/css/app.css @@ -78,7 +78,7 @@ label { } table { - @apply min-w-full divide-y dark:divide-coolgray-200 divide-neutral-300; + @apply min-w-full divide-y dark:divide-coolgray-200 divide-neutral-300 ; } thead { @@ -90,7 +90,7 @@ tbody { } tr { - @apply text-neutral-400; + @apply text-black dark:text-neutral-400 dark:hover:bg-black hover:bg-neutral-200; } tr th { diff --git a/resources/views/components/internal-link.blade.php b/resources/views/components/internal-link.blade.php index 19fe52635..cedea2a40 100644 --- a/resources/views/components/internal-link.blade.php +++ b/resources/views/components/internal-link.blade.php @@ -1 +1,3 @@ - + + + diff --git a/resources/views/components/pricing-plans.blade.php b/resources/views/components/pricing-plans.blade.php index ca71bf93e..5977323f2 100644 --- a/resources/views/components/pricing-plans.blade.php +++ b/resources/views/components/pricing-plans.blade.php @@ -48,7 +48,7 @@
+ class="grid max-w-sm grid-cols-1 -mt-16 divide-y divide-neutral-200 dark:divide-coolgray-500 isolate gap-y-16 sm:mx-auto lg:-mx-8 lg:mt-0 lg:max-w-none lg:grid-cols-3 lg:divide-x lg:divide-y-0 xl:-mx-4">

Basic

@@ -186,7 +186,7 @@
-
+

Ultimate

diff --git a/resources/views/livewire/server/resources.blade.php b/resources/views/livewire/server/resources.blade.php index 378547f1a..225636ca8 100644 --- a/resources/views/livewire/server/resources.blade.php +++ b/resources/views/livewire/server/resources.blade.php @@ -24,7 +24,7 @@

- +
- + @forelse ($server->definedResources()->sortBy('name',SORT_NATURAL) as $resource) - + - +
@@ -43,16 +43,16 @@
{{ data_get($resource->project(), 'name') }} {{ data_get($resource, 'environment.name') }} {{ $resource->name }} @@ -96,7 +96,7 @@
- +
- + @forelse ($unmanagedContainers->sortBy('name',SORT_NATURAL) as $resource) - + diff --git a/resources/views/livewire/source/github/change.blade.php b/resources/views/livewire/source/github/change.blade.php index c883c6e27..b1f0cf709 100644 --- a/resources/views/livewire/source/github/change.blade.php +++ b/resources/views/livewire/source/github/change.blade.php @@ -107,7 +107,7 @@
-
@@ -113,9 +113,9 @@
{{ data_get($resource, 'Names') }}
+
- + @forelse ($applications->sortBy('name',SORT_NATURAL) as $resource) - + diff --git a/resources/views/livewire/team/invitations.blade.php b/resources/views/livewire/team/invitations.blade.php index c9ca4d6b7..f318e4d61 100644 --- a/resources/views/livewire/team/invitations.blade.php +++ b/resources/views/livewire/team/invitations.blade.php @@ -6,7 +6,7 @@
-
@@ -121,9 +121,9 @@
{{ data_get($resource->project(), 'name') }}
+
- + @foreach ($invitations as $invite) - + diff --git a/resources/views/livewire/team/member/index.blade.php b/resources/views/livewire/team/member/index.blade.php index 6a6cc0fd2..41cd61d82 100644 --- a/resources/views/livewire/team/member/index.blade.php +++ b/resources/views/livewire/team/member/index.blade.php @@ -7,7 +7,7 @@
-
Email @@ -20,9 +20,9 @@
{{ $invite->email }} {{ $invite->via }} {{ $invite->role }}
+
- + @foreach (currentTeam()->members as $member) @endforeach From 51d716253f196e89c983fa25db1439818d79ea61 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Thu, 28 Mar 2024 15:05:12 +0100 Subject: [PATCH 05/20] feat: watch paths --- app/Http/Controllers/Webhook/Github.php | 44 +++++++++++++------ app/Livewire/Project/Application/General.php | 2 + app/Models/Application.php | 21 +++++++++ bootstrap/helpers/applications.php | 1 + ...4_03_28_114620_add_watch_paths_to_apps.php | 28 ++++++++++++ resources/css/app.css | 2 +- .../project/application/general.blade.php | 8 +++- 7 files changed, 91 insertions(+), 15 deletions(-) create mode 100644 database/migrations/2024_03_28_114620_add_watch_paths_to_apps.php diff --git a/app/Http/Controllers/Webhook/Github.php b/app/Http/Controllers/Webhook/Github.php index 02ba017ca..433d29c58 100644 --- a/app/Http/Controllers/Webhook/Github.php +++ b/app/Http/Controllers/Webhook/Github.php @@ -204,6 +204,7 @@ class Github extends Controller } public function normal(Request $request) { + ray('asdf'); try { $return_payloads = collect([]); $id = null; @@ -266,6 +267,10 @@ class Github extends Controller if (Str::isMatch('/refs\/heads\/*/', $branch)) { $branch = Str::after($branch, 'refs/heads/'); } + $added_files = data_get($payload, 'commits.*.added'); + $removed_files = data_get($payload, 'commits.*.removed'); + $modified_files = data_get($payload, 'commits.*.modified'); + $changed_files = collect($added_files)->concat($removed_files)->concat($modified_files)->unique()->flatten(); ray('Webhook GitHub Push Event: ' . $id . ' with branch: ' . $branch); } if ($x_github_event === 'pull_request') { @@ -306,19 +311,32 @@ class Github extends Controller } if ($x_github_event === 'push') { if ($application->isDeployable()) { - ray('Deploying ' . $application->name . ' with branch ' . $branch); - $deployment_uuid = new Cuid2(7); - queue_application_deployment( - application: $application, - deployment_uuid: $deployment_uuid, - force_rebuild: false, - is_webhook: true - ); - $return_payloads->push([ - 'application' => $application->name, - 'status' => 'success', - 'message' => 'Deployment queued.', - ]); + $watch_files_trigger = $application->watchPathCheck($changed_files); + if (!$watch_files_trigger) { + $return_payloads->push([ + 'application' => $application->name, + 'status' => 'failed', + 'message' => 'Watch paths does not have the changed files. Deployment ignored.', + 'details' => [ + 'changed_files' => $changed_files, + 'watch_paths' => $application->watch_paths, + ], + ]); + } else { + ray('Deploying ' . $application->name . ' with branch ' . $branch); + $deployment_uuid = new Cuid2(7); + queue_application_deployment( + application: $application, + deployment_uuid: $deployment_uuid, + force_rebuild: false, + is_webhook: true, + ); + $return_payloads->push([ + 'application' => $application->name, + 'status' => 'success', + 'message' => 'Deployment queued.', + ]); + } } else { $return_payloads->push([ 'application' => $application->name, diff --git a/app/Livewire/Project/Application/General.php b/app/Livewire/Project/Application/General.php index 9485cdd03..c6b8f2e51 100644 --- a/app/Livewire/Project/Application/General.php +++ b/app/Livewire/Project/Application/General.php @@ -73,6 +73,7 @@ class General extends Component 'application.settings.is_static' => 'boolean|required', 'application.settings.is_raw_compose_deployment_enabled' => 'boolean|required', 'application.settings.is_build_server_enabled' => 'boolean|required', + 'application.watch_paths' => 'nullable', ]; protected $validationAttributes = [ 'application.name' => 'name', @@ -108,6 +109,7 @@ class General extends Component 'application.settings.is_static' => 'Is static', 'application.settings.is_raw_compose_deployment_enabled' => 'Is raw compose deployment enabled', 'application.settings.is_build_server_enabled' => 'Is build server enabled', + 'application.watch_paths' => 'Watch paths', ]; public function mount() { diff --git a/app/Models/Application.php b/app/Models/Application.php index bc3b27bb0..fc03f8b1e 100644 --- a/app/Models/Application.php +++ b/app/Models/Application.php @@ -6,6 +6,7 @@ use App\Enums\ApplicationDeploymentStatus; 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; @@ -903,4 +904,24 @@ class Application extends BaseModel : explode(',', $this->fqdn), ); } + public function watchPaths(): Attribute + { + return Attribute::make( + set: function ($value) { + if ($value) { + return trim($value); + } + } + ); + } + public function watchPathCheck(Collection $modified_files): bool + { + $watch_paths = collect(explode("\n", $this->watch_paths)); + $matches = $modified_files->filter(function ($file) use ($watch_paths) { + return $watch_paths->contains(function ($glob) use ($file) { + return fnmatch($glob, $file); + }); + }); + return $matches->count() > 0; + } } diff --git a/bootstrap/helpers/applications.php b/bootstrap/helpers/applications.php index bf3f15514..8d810da0f 100644 --- a/bootstrap/helpers/applications.php +++ b/bootstrap/helpers/applications.php @@ -6,6 +6,7 @@ use App\Models\Application; use App\Models\ApplicationDeploymentQueue; use App\Models\Server; use App\Models\StandaloneDocker; +use Illuminate\Support\Collection; 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, bool $only_this_server = false) diff --git a/database/migrations/2024_03_28_114620_add_watch_paths_to_apps.php b/database/migrations/2024_03_28_114620_add_watch_paths_to_apps.php new file mode 100644 index 000000000..d58adcd62 --- /dev/null +++ b/database/migrations/2024_03_28_114620_add_watch_paths_to_apps.php @@ -0,0 +1,28 @@ +longText('watch_paths')->nullable(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('applications', function (Blueprint $table) { + $table->dropColumn('watch_paths'); + }); + } +}; diff --git a/resources/css/app.css b/resources/css/app.css index c2ca9f612..5976e2285 100644 --- a/resources/css/app.css +++ b/resources/css/app.css @@ -13,7 +13,7 @@ body { .input, .select { - @apply text-black dark:bg-coolgray-100 dark:text-white ring-neutral-300 dark:ring-coolgray-300; + @apply text-black dark:bg-coolgray-100 dark:text-white ring-neutral-200 dark:ring-coolgray-300; } /* Readonly */ diff --git a/resources/views/livewire/project/application/general.blade.php b/resources/views/livewire/project/application/general.blade.php index 44578c23c..e89431365 100644 --- a/resources/views/livewire/project/application/general.blade.php +++ b/resources/views/livewire/project/application/general.blade.php @@ -148,7 +148,8 @@ id="application.start_command" label="Start Command" />
Nixpacks will detect the required configuration automatically. - Framework Specific Docs + Framework + Specific Docs
@endif @endif @@ -201,7 +202,12 @@ label="Publish Directory" /> @endif @endif + + @if ($this->application->is_github_based()) + + @endif
The following options are for advanced use cases. Only modify them if you know what are you doing.
From d569c8d31f2a05ae7adc96c79f694aa026aa4bcc Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Thu, 28 Mar 2024 15:18:05 +0100 Subject: [PATCH 06/20] fix: search services --- app/Livewire/Project/New/Select.php | 4 ++++ resources/views/livewire/project/new/select.blade.php | 6 +++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/app/Livewire/Project/New/Select.php b/app/Livewire/Project/New/Select.php index b1842547e..2662cff09 100644 --- a/app/Livewire/Project/New/Select.php +++ b/app/Livewire/Project/New/Select.php @@ -70,6 +70,10 @@ class Select extends Component // } // } + public function updatedSearch() + { + $this->loadServices(); + } public function loadServices(bool $force = false) { try { diff --git a/resources/views/livewire/project/new/select.blade.php b/resources/views/livewire/project/new/select.blade.php index c3030f304..eea43a8bd 100644 --- a/resources/views/livewire/project/new/select.blade.php +++ b/resources/views/livewire/project/new/select.blade.php @@ -1,4 +1,4 @@ -
+

New Resource

@@ -377,12 +377,12 @@

Services

Reload List -
Trademarks Policy: The respective trademarks mentioned here are owned by the respective companies, and use of them does not imply any affiliation or endorsement.
+ @if ($loadingServices) @else From 171f6f46080188111a2c5bdbec3fb52ad0b347b6 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Sat, 30 Mar 2024 00:23:48 +0100 Subject: [PATCH 07/20] fix: trial users subscription page --- app/Livewire/Subscription/Index.php | 2 +- bootstrap/helpers/shared.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/Livewire/Subscription/Index.php b/app/Livewire/Subscription/Index.php index c87f7d0b6..1444187ac 100644 --- a/app/Livewire/Subscription/Index.php +++ b/app/Livewire/Subscription/Index.php @@ -15,7 +15,7 @@ class Index extends Component if (!isCloud()) { return redirect(RouteServiceProvider::HOME); } - if (data_get(currentTeam(), 'subscription')) { + if (data_get(currentTeam(), 'subscription') && isSubscriptionActive()) { return redirect()->route('subscription.show'); } $this->settings = InstanceSettings::get(); diff --git a/bootstrap/helpers/shared.php b/bootstrap/helpers/shared.php index 023a65107..baee4ce15 100644 --- a/bootstrap/helpers/shared.php +++ b/bootstrap/helpers/shared.php @@ -282,7 +282,7 @@ function base_url(bool $withPort = true): string function isSubscribed() { - return auth()->user()->currentTeam()->subscription()->exists() || auth()->user()->isInstanceAdmin(); + return isSubscriptionActive() || auth()->user()->isInstanceAdmin(); } function isDev(): bool { From 7a92ecfa30fa1be03824eb3afc6c18664fb6dd52 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Sat, 30 Mar 2024 18:58:41 +0100 Subject: [PATCH 08/20] fix: async public key loading --- app/Livewire/Security/PrivateKey/Show.php | 6 ++++-- .../views/livewire/security/private-key/show.blade.php | 6 +++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/app/Livewire/Security/PrivateKey/Show.php b/app/Livewire/Security/PrivateKey/Show.php index 0540b2e29..0a292731b 100644 --- a/app/Livewire/Security/PrivateKey/Show.php +++ b/app/Livewire/Security/PrivateKey/Show.php @@ -8,7 +8,7 @@ use Livewire\Component; class Show extends Component { public PrivateKey $private_key; - public $public_key; + public $public_key = "Loading..."; protected $rules = [ 'private_key.name' => 'required|string', 'private_key.description' => 'nullable|string', @@ -25,11 +25,13 @@ class Show extends Component { try { $this->private_key = PrivateKey::ownedByCurrentTeam(['name', 'description', 'private_key', 'is_git_related'])->whereUuid(request()->private_key_uuid)->firstOrFail(); - $this->public_key = $this->private_key->publicKey(); }catch(\Throwable $e) { return handleError($e, $this); } } + public function loadPublicKey() { + $this->public_key = $this->private_key->publicKey(); + } public function delete() { try { diff --git a/resources/views/livewire/security/private-key/show.blade.php b/resources/views/livewire/security/private-key/show.blade.php index b56fab610..9935f5565 100644 --- a/resources/views/livewire/security/private-key/show.blade.php +++ b/resources/views/livewire/security/private-key/show.blade.php @@ -1,4 +1,4 @@ -
+
@@ -22,11 +22,11 @@
Private Key *
-
Edit
-
Hide
From 7aca4930db5a390855d53a450cc26cef24e7ea1b Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Sun, 31 Mar 2024 18:38:26 +0200 Subject: [PATCH 09/20] fix: unfunctional server should see resources --- app/Models/Server.php | 33 +- .../views/livewire/server/resources.blade.php | 282 +++++++++--------- 2 files changed, 157 insertions(+), 158 deletions(-) diff --git a/app/Models/Server.php b/app/Models/Server.php index 08235a26d..10af2915d 100644 --- a/app/Models/Server.php +++ b/app/Models/Server.php @@ -550,21 +550,26 @@ $schema://$host { } public function loadUnmanagedContainers() { - if ($this->isFunctional()) { - $containers = instant_remote_process(["docker ps -a --format '{{json .}}' "], $this); - $containers = format_docker_command_output_to_json($containers); - $containers = $containers->map(function ($container) { - $labels = data_get($container, 'Labels'); - if (!str($labels)->contains("coolify.managed")) { - return $container; - } - return null; - }); - $containers = $containers->filter(); - return collect($containers); - } else { - return collect([]); + try { + if ($this->isFunctional()) { + $containers = instant_remote_process(["docker ps -a --format '{{json .}}' "], $this); + $containers = format_docker_command_output_to_json($containers); + $containers = $containers->map(function ($container) { + $labels = data_get($container, 'Labels'); + if (!str($labels)->contains("coolify.managed")) { + return $container; + } + return null; + }); + $containers = $containers->filter(); + return collect($containers); + } else { + return collect([]); + } + } catch (\Throwable $e) { + return handleError($e); } + } public function hasDefinedResources() { diff --git a/resources/views/livewire/server/resources.blade.php b/resources/views/livewire/server/resources.blade.php index 225636ca8..8c888b131 100644 --- a/resources/views/livewire/server/resources.blade.php +++ b/resources/views/livewire/server/resources.blade.php @@ -1,165 +1,159 @@
- @if ($server->isFunctional()) -
- -
-
+
+ +
+
+
+
+

Resources

+ Refresh +
+
Here you can find all resources that are managed by Coolify.
+
+ @if ($server->definedResources()->count() > 0)
-
-

Resources

- Refresh -
-
Here you can find all resources that are managed by Coolify.
-
- @if ($server->definedResources()->count() > 0)
-
-
-
-
-
Name @@ -17,7 +17,7 @@ Actions
- +
+
+
+
+ + + + + + + + + + + @forelse ($server->definedResources()->sortBy('name',SORT_NATURAL) as $resource) - - - - - + + + + + - - - @forelse ($server->definedResources()->sortBy('name',SORT_NATURAL) as $resource) - - - - - - - - @empty - @endforelse - -
+ Project + + Environment + Name + + Type + + Status +
- Project - - Environment - Name - - Type - - Status - + {{ data_get($resource->project(), 'name') }} + + {{ data_get($resource, 'environment.name') }} + + {{ $resource->name }} + + + {{ str($resource->type())->headline() }} + @if ($resource->type() === 'service') + + @else + + @endif +
- {{ data_get($resource->project(), 'name') }} - - {{ data_get($resource, 'environment.name') }} - {{ $resource->name }} - - - {{ str($resource->type())->headline() }} - @if ($resource->type() === 'service') - - @else - - @endif -
-
+ @empty + @endforelse +
- @else -
No resources found.
- @endif -
-
-
-
-

Resources

- Refresh -
-
Here you can find all other containers running on the server.
- @if ($unmanagedContainers->count() > 0) + @else +
No resources found.
+ @endif +
+
+
+
+

Resources

+ Refresh +
+
Here you can find all other containers running on the server.
+
+ @if ($unmanagedContainers->count() > 0) +
-
-
-
-
- - +
+
+
+
+ + + + + + + + + + @forelse ($unmanagedContainers->sortBy('name',SORT_NATURAL) as $resource) - - - - + + + + - - - @forelse ($unmanagedContainers->sortBy('name',SORT_NATURAL) as $resource) - - - - - - - @empty - @endforelse - -
+ Name + + Image + + Status + + Action +
- Name - - Image - - Status - - Action - + {{ data_get($resource, 'Names') }} + + {{ data_get($resource, 'Image') }} + + {{ data_get($resource, 'State') }} + + @if (data_get($resource, 'State') === 'running') + Restart + Stop + @elseif (data_get($resource, 'State') === 'exited') + Start + @elseif (data_get($resource, 'State') === 'restarting') + Stop + @endif +
- {{ data_get($resource, 'Names') }} - - {{ data_get($resource, 'Image') }} - - {{ data_get($resource, 'State') }} - - @if (data_get($resource, 'State') === 'running') - Restart - Stop - @elseif (data_get($resource, 'State') === 'exited') - Start - @elseif (data_get($resource, 'State') === 'restarting') - Stop - @endif -
-
+ @empty + @endforelse + +
- @else -
No resources found.
- @endif -
+
+ @else +
No resources found.
+ @endif
- @else -
Server is not validated. Validate first.
- @endif + From 6b21dc132dad607217fe0bebcdda0964b3b74cdb Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Mon, 1 Apr 2024 09:40:39 +0200 Subject: [PATCH 10/20] Refactor subscription active check for Stripe --- bootstrap/helpers/subscriptions.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bootstrap/helpers/subscriptions.php b/bootstrap/helpers/subscriptions.php index 928bbbcaf..5158c4e7e 100644 --- a/bootstrap/helpers/subscriptions.php +++ b/bootstrap/helpers/subscriptions.php @@ -66,7 +66,7 @@ function isSubscriptionActive() // return $subscription->paddle_status === 'active'; // } if (isStripe()) { - return $subscription->stripe_invoice_paid === true && $subscription->stripe_cancel_at_period_end === false; + return $subscription->stripe_invoice_paid === true; } return false; } From 75b9f4fcbfc3e6b482748480c38e42dfa3cbcb4b Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Tue, 2 Apr 2024 15:00:01 +0200 Subject: [PATCH 11/20] Add search functionality and display active/inactive subscribers in Admin Dashboard --- app/Livewire/Admin/Index.php | 36 +++++++++++++++++-- .../views/livewire/admin/index.blade.php | 30 +++++++++++----- 2 files changed, 56 insertions(+), 10 deletions(-) diff --git a/app/Livewire/Admin/Index.php b/app/Livewire/Admin/Index.php index 60bd6f5ea..b72bc8e35 100644 --- a/app/Livewire/Admin/Index.php +++ b/app/Livewire/Admin/Index.php @@ -8,7 +8,31 @@ use Livewire\Component; class Index extends Component { - public $users = []; + public $active_subscribers = []; + public $inactive_subscribers = []; + public $search = ''; + public function submitSearch() { + if ($this->search !== "") { + $this->inactive_subscribers = User::whereDoesntHave('teams', function ($query) { + $query->whereRelation('subscription', 'stripe_subscription_id', '!=', null); + })->where(function ($query) { + $query->where('name', 'like', "%{$this->search}%") + ->orWhere('email', 'like', "%{$this->search}%"); + })->get()->filter(function ($user) { + return $user->id !== 0; + }); + $this->active_subscribers = User::whereHas('teams', function ($query) { + $query->whereRelation('subscription', 'stripe_subscription_id', '!=', null); + })->where(function ($query) { + $query->where('name', 'like', "%{$this->search}%") + ->orWhere('email', 'like', "%{$this->search}%"); + })->get()->filter(function ($user) { + return $user->id !== 0; + }); + } else { + $this->getSubscribers(); + } + } public function mount() { if (!isCloud()) { @@ -17,7 +41,15 @@ class Index extends Component if (auth()->user()->id !== 0) { return redirect()->route('dashboard'); } - $this->users = User::whereHas('teams', function ($query) { + $this->getSubscribers(); + } + public function getSubscribers() { + $this->inactive_subscribers = User::whereDoesntHave('teams', function ($query) { + $query->whereRelation('subscription', 'stripe_subscription_id', '!=', null); + })->get()->filter(function ($user) { + return $user->id !== 0; + }); + $this->active_subscribers = User::whereHas('teams', function ($query) { $query->whereRelation('subscription', 'stripe_subscription_id', '!=', null); })->get()->filter(function ($user) { return $user->id !== 0; diff --git a/resources/views/livewire/admin/index.blade.php b/resources/views/livewire/admin/index.blade.php index 5964097c6..99abdf0e5 100644 --- a/resources/views/livewire/admin/index.blade.php +++ b/resources/views/livewire/admin/index.blade.php @@ -1,17 +1,31 @@

Admin Dashboard

Who am I now?

- {{ auth()->user()->name }} -

Users

+
{{ auth()->user()->name }}
+ + + Search + +

Active Subscribers

-
- Root -
- @foreach ($users as $user) -
+ @forelse ($active_subscribers as $user) +

{{ $user->name }}

{{ $user->email }}

- @endforeach + @empty +

No active subscribers

+ @endforelse +
+

Inactive Subscribers

+
+ @forelse ($inactive_subscribers as $user) +
+

{{ $user->name }}

+

{{ $user->email }}

+
+ @empty +

No inactive subscribers

+ @endforelse
From 0f4eab3cf2ec7a2b22b9992f4307126cd623e0dd Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Tue, 2 Apr 2024 15:01:50 +0200 Subject: [PATCH 12/20] Fix error handling in loadUnmanagedContainers method --- app/Livewire/Server/Resources.php | 6 +++++- app/Models/Server.php | 5 ----- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/app/Livewire/Server/Resources.php b/app/Livewire/Server/Resources.php index f781418d9..1c8a8267e 100644 --- a/app/Livewire/Server/Resources.php +++ b/app/Livewire/Server/Resources.php @@ -42,7 +42,11 @@ class Resources extends Component $this->dispatch('success', 'Resource statuses refreshed.'); } public function loadUnmanagedContainers() { - $this->unmanagedContainers = $this->server->loadUnmanagedContainers(); + try { + $this->unmanagedContainers = $this->server->loadUnmanagedContainers(); + } catch (\Throwable $e) { + return handleError($e, $this); + } } public function mount() { $this->unmanagedContainers = collect(); diff --git a/app/Models/Server.php b/app/Models/Server.php index 10af2915d..cbe895936 100644 --- a/app/Models/Server.php +++ b/app/Models/Server.php @@ -550,7 +550,6 @@ $schema://$host { } public function loadUnmanagedContainers() { - try { if ($this->isFunctional()) { $containers = instant_remote_process(["docker ps -a --format '{{json .}}' "], $this); $containers = format_docker_command_output_to_json($containers); @@ -566,10 +565,6 @@ $schema://$host { } else { return collect([]); } - } catch (\Throwable $e) { - return handleError($e); - } - } public function hasDefinedResources() { From db5d7857c8d4dd4340d43a74fdd08177df843663 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Tue, 2 Apr 2024 15:15:43 +0200 Subject: [PATCH 13/20] fix: warning if you use multiple domains for a service --- app/Livewire/Project/Service/ServiceApplicationView.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/app/Livewire/Project/Service/ServiceApplicationView.php b/app/Livewire/Project/Service/ServiceApplicationView.php index 0b3a4cef6..70a8662d5 100644 --- a/app/Livewire/Project/Service/ServiceApplicationView.php +++ b/app/Livewire/Project/Service/ServiceApplicationView.php @@ -59,7 +59,11 @@ class ServiceApplicationView extends Component $this->validate(); $this->application->save(); updateCompose($this->application); - $this->dispatch('success', 'Service saved.'); + if (str($this->application->fqdn)->contains(',')) { + $this->dispatch('warning', 'Some services do not support multiple domains, which can lead to problems and is NOT RECOMMENDED.'); + } else { + $this->dispatch('success', 'Service saved.'); + } } catch (\Throwable $e) { return handleError($e, $this); } finally { From fd9dae6e4b90692dbb97f13b6d8fedf20abf29cf Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Tue, 2 Apr 2024 15:40:19 +0200 Subject: [PATCH 14/20] Refactor EnvironmentVariable creation logic --- app/Models/EnvironmentVariable.php | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/app/Models/EnvironmentVariable.php b/app/Models/EnvironmentVariable.php index 611543b2d..32277769e 100644 --- a/app/Models/EnvironmentVariable.php +++ b/app/Models/EnvironmentVariable.php @@ -25,19 +25,18 @@ class EnvironmentVariable extends Model static::created(function (EnvironmentVariable $environment_variable) { if ($environment_variable->application_id && !$environment_variable->is_preview) { $found = ModelsEnvironmentVariable::where('key', $environment_variable->key)->where('application_id', $environment_variable->application_id)->where('is_preview', true)->first(); - $application = Application::find($environment_variable->application_id); - if ($application->build_pack === 'dockerfile') { - return; - } if (!$found) { - ModelsEnvironmentVariable::create([ - 'key' => $environment_variable->key, - 'value' => $environment_variable->value, - 'is_build_time' => $environment_variable->is_build_time, - 'is_multiline' => $environment_variable->is_multiline, - 'application_id' => $environment_variable->application_id, - 'is_preview' => true - ]); + $application = Application::find($environment_variable->application_id); + if ($application->build_pack !== 'dockerfile') { + ModelsEnvironmentVariable::create([ + 'key' => $environment_variable->key, + 'value' => $environment_variable->value, + 'is_build_time' => $environment_variable->is_build_time, + 'is_multiline' => $environment_variable->is_multiline, + 'application_id' => $environment_variable->application_id, + 'is_preview' => true + ]); + } } } $environment_variable->update([ From 6333d3fd13d999f19f36d8c2c7be9a62d9f557a2 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Tue, 2 Apr 2024 15:40:25 +0200 Subject: [PATCH 15/20] Fix image environment variable bug --- app/Jobs/ApplicationDeploymentJob.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/Jobs/ApplicationDeploymentJob.php b/app/Jobs/ApplicationDeploymentJob.php index 0c6b6eecb..b30a49585 100644 --- a/app/Jobs/ApplicationDeploymentJob.php +++ b/app/Jobs/ApplicationDeploymentJob.php @@ -325,6 +325,7 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted executeInDocker($this->deployment_uuid, "echo '$dockerfile_base64' | base64 -d > {$this->workdir}{$this->dockerfile_location}") ], ); + // TODO: If the image exists and envs are changed, they are not applied. $this->generate_image_names(); if (!$this->force_rebuild) { $this->check_image_locally_or_remotely(); @@ -1373,6 +1374,7 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted $environment_variables = collect(); if ($this->pull_request_id === 0) { foreach ($this->application->runtime_environment_variables as $env) { + ray($env); // This is necessary because we have to escape the value of the environment variable // but only if the environment variable is created after 4.0.0-beta.240 // when I implemented the escaping feature. From 7f4230d0261d33eae666548f7eaa2e0272acddb1 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Tue, 2 Apr 2024 15:40:52 +0200 Subject: [PATCH 16/20] Remove unnecessary code and comments --- app/Jobs/ApplicationDeploymentJob.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/Jobs/ApplicationDeploymentJob.php b/app/Jobs/ApplicationDeploymentJob.php index b30a49585..0c6b6eecb 100644 --- a/app/Jobs/ApplicationDeploymentJob.php +++ b/app/Jobs/ApplicationDeploymentJob.php @@ -325,7 +325,6 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted executeInDocker($this->deployment_uuid, "echo '$dockerfile_base64' | base64 -d > {$this->workdir}{$this->dockerfile_location}") ], ); - // TODO: If the image exists and envs are changed, they are not applied. $this->generate_image_names(); if (!$this->force_rebuild) { $this->check_image_locally_or_remotely(); @@ -1374,7 +1373,6 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted $environment_variables = collect(); if ($this->pull_request_id === 0) { foreach ($this->application->runtime_environment_variables as $env) { - ray($env); // This is necessary because we have to escape the value of the environment variable // but only if the environment variable is created after 4.0.0-beta.240 // when I implemented the escaping feature. From 31651aeaaba3a2e70a48bf86d1e06ef950cce63d Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Tue, 2 Apr 2024 20:35:44 +0200 Subject: [PATCH 17/20] ui: light buttons --- resources/css/app.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/css/app.css b/resources/css/app.css index 5976e2285..371efd8ed 100644 --- a/resources/css/app.css +++ b/resources/css/app.css @@ -41,7 +41,7 @@ option { } .button { - @apply flex items-center justify-center gap-2 px-3 py-1 text-sm text-white normal-case rounded cursor-pointer hover:bg-black/80 bg-coolgray-200 hover:bg-coolgray-500 hover:text-white disabled:bg-coolgray-100/10 disabled:cursor-not-allowed min-w-fit focus:outline-1 dark:disabled:text-neutral-600; + @apply flex items-center justify-center gap-2 px-2 py-1 text-sm text-black normal-case border rounded cursor-pointer bg-neutral-200/50 border-neutral-300 hover:bg-neutral-300 dark:bg-coolgray-200 dark:text-white dark:hover:text-white dark:hover:bg-coolgray-500 dark:border-black hover:text-black disabled:bg-coolgray-100/10 disabled:cursor-not-allowed min-w-fit focus:outline-1 dark:disabled:text-neutral-600; } button[isError]:not(:disabled) { From 735081af50ccd111af3db462f629643432ff5149 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Tue, 2 Apr 2024 20:50:12 +0200 Subject: [PATCH 18/20] fix: new github app creation --- app/Livewire/Project/New/GithubPrivateRepository.php | 2 -- .../project/new/github-private-repository.blade.php | 6 +++--- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/app/Livewire/Project/New/GithubPrivateRepository.php b/app/Livewire/Project/New/GithubPrivateRepository.php index 7d59cfb04..322fd4a4e 100644 --- a/app/Livewire/Project/New/GithubPrivateRepository.php +++ b/app/Livewire/Project/New/GithubPrivateRepository.php @@ -7,14 +7,12 @@ use App\Models\GithubApp; use App\Models\Project; use App\Models\StandaloneDocker; use App\Models\SwarmDocker; -use App\Traits\SaveFromRedirect; use Illuminate\Support\Facades\Http; use Illuminate\Support\Facades\Route; use Livewire\Component; class GithubPrivateRepository extends Component { - use SaveFromRedirect; public $current_step = 'github_apps'; public $github_apps; public GithubApp $github_app; diff --git a/resources/views/livewire/project/new/github-private-repository.blade.php b/resources/views/livewire/project/new/github-private-repository.blade.php index 29438988e..4fc2a0bbc 100644 --- a/resources/views/livewire/project/new/github-private-repository.blade.php +++ b/resources/views/livewire/project/new/github-private-repository.blade.php @@ -1,9 +1,9 @@

Create a new Application

- - + Add New GitHub App - + + + @if ($repositories->count() > 0) From 132807b55d4a762dd117a201c66e58e6c3f092c4 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Tue, 2 Apr 2024 20:50:35 +0200 Subject: [PATCH 19/20] fix: always rebuild Dockerfile / dockerimage buildpacks --- app/Jobs/ApplicationDeploymentJob.php | 48 ++++++++++--------- .../application/deployment/show.blade.php | 2 +- 2 files changed, 26 insertions(+), 24 deletions(-) diff --git a/app/Jobs/ApplicationDeploymentJob.php b/app/Jobs/ApplicationDeploymentJob.php index 0c6b6eecb..356006983 100644 --- a/app/Jobs/ApplicationDeploymentJob.php +++ b/app/Jobs/ApplicationDeploymentJob.php @@ -234,7 +234,7 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted $this->build_server = $this->server; $this->original_server = $this->server; } - if ($this->restart_only && $this->application->build_pack !== 'dockerimage') { + if ($this->restart_only && $this->application->build_pack !== 'dockerimage' && $this->application->build_pack !== 'dockerfile') { $this->just_restart(); if ($this->server->isProxyShouldRun()) { dispatch(new ContainerStatusJob($this->server)); @@ -326,17 +326,19 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted ], ); $this->generate_image_names(); - if (!$this->force_rebuild) { - $this->check_image_locally_or_remotely(); - if (str($this->saved_outputs->get('local_image_found'))->isNotEmpty() && !$this->application->isConfigurationChanged()) { - $this->create_workdir(); - $this->application_deployment_queue->addLogEntry("No configuration changed & image found ({$this->production_image_name}) with the same Git Commit SHA. Build step skipped."); - $this->generate_compose_file(); - $this->push_to_docker_registry(); - $this->rolling_update(); - return; - } - } + + // Always rebuild dockerfile based container. + // if (!$this->force_rebuild) { + // $this->check_image_locally_or_remotely(); + // if (str($this->saved_outputs->get('local_image_found'))->isNotEmpty() && !$this->application->isConfigurationChanged()) { + // $this->create_workdir(); + // $this->application_deployment_queue->addLogEntry("No configuration changed & image found ({$this->production_image_name}) with the same Git Commit SHA. Build step skipped."); + // $this->generate_compose_file(); + // $this->push_to_docker_registry(); + // $this->rolling_update(); + // return; + // } + // } $this->generate_compose_file(); $this->generate_build_env_variables(); $this->add_build_env_variables_to_dockerfile(); @@ -467,17 +469,17 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted $this->set_base_dir(); $this->generate_image_names(); $this->clone_repository(); - if (!$this->force_rebuild) { - $this->check_image_locally_or_remotely(); - if (str($this->saved_outputs->get('local_image_found'))->isNotEmpty() && !$this->application->isConfigurationChanged()) { - $this->create_workdir(); - $this->application_deployment_queue->addLogEntry("No configuration changed & image found ({$this->production_image_name}) with the same Git Commit SHA. Build step skipped."); - $this->generate_compose_file(); - $this->push_to_docker_registry(); - $this->rolling_update(); - return; - } - } + // if (!$this->force_rebuild) { + // $this->check_image_locally_or_remotely(); + // if (str($this->saved_outputs->get('local_image_found'))->isNotEmpty() && !$this->application->isConfigurationChanged()) { + // $this->create_workdir(); + // $this->application_deployment_queue->addLogEntry("No configuration changed & image found ({$this->production_image_name}) with the same Git Commit SHA. Build step skipped."); + // $this->generate_compose_file(); + // $this->push_to_docker_registry(); + // $this->rolling_update(); + // return; + // } + // } $this->cleanup_git(); $this->generate_compose_file(); $this->generate_build_env_variables(); diff --git a/resources/views/livewire/project/application/deployment/show.blade.php b/resources/views/livewire/project/application/deployment/show.blade.php index 1426ef583..1d3455605 100644 --- a/resources/views/livewire/project/application/deployment/show.blade.php +++ b/resources/views/livewire/project/application/deployment/show.blade.php @@ -87,7 +87,7 @@
$line['hidden'], - 'text-red-500 whitespace-pre-line' => $line['type'] == 'stderr', + 'text-red-500 font-bold whitespace-pre-line' => $line['type'] == 'stderr', ])>[{{ $line['timestamp'] }}] @if ($line['hidden'])
COMMAND:
{{ $line['command'] }}

OUTPUT: @endif @if (str($line['output'])->contains('http://') || str($line['output'])->contains('https://')) From a198bfc5c015ae3f7436f531f3162321bc11509a Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Tue, 2 Apr 2024 21:25:09 +0200 Subject: [PATCH 20/20] Refactor deployment logic in Github webhook controller --- app/Http/Controllers/Webhook/Github.php | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/app/Http/Controllers/Webhook/Github.php b/app/Http/Controllers/Webhook/Github.php index 433d29c58..373d89918 100644 --- a/app/Http/Controllers/Webhook/Github.php +++ b/app/Http/Controllers/Webhook/Github.php @@ -204,7 +204,6 @@ class Github extends Controller } public function normal(Request $request) { - ray('asdf'); try { $return_payloads = collect([]); $id = null; @@ -303,9 +302,10 @@ class Github extends Controller $isFunctional = $application->destination->server->isFunctional(); if (!$isFunctional) { $return_payloads->push([ - 'application' => $application->name, 'status' => 'failed', 'message' => 'Server is not functional.', + 'application_uuid' => $application->uuid, + 'application_name' => $application->name, ]); continue; } @@ -313,13 +313,15 @@ class Github extends Controller if ($application->isDeployable()) { $watch_files_trigger = $application->watchPathCheck($changed_files); if (!$watch_files_trigger) { + $paths = str($application->watch_paths)->explode("\n"); $return_payloads->push([ - 'application' => $application->name, 'status' => 'failed', - 'message' => 'Watch paths does not have the changed files. Deployment ignored.', + 'message' => 'Changed files do not match watch paths. Ignoring deployment.', + 'application_uuid' => $application->uuid, + 'application_name' => $application->name, 'details' => [ 'changed_files' => $changed_files, - 'watch_paths' => $application->watch_paths, + 'watch_paths' => $paths, ], ]); } else { @@ -332,16 +334,18 @@ class Github extends Controller is_webhook: true, ); $return_payloads->push([ - 'application' => $application->name, 'status' => 'success', 'message' => 'Deployment queued.', + 'application_uuid' => $application->uuid, + 'application_name' => $application->name, ]); } } else { $return_payloads->push([ - 'application' => $application->name, 'status' => 'failed', 'message' => 'Deployments disabled.', + 'application_uuid' => $application->uuid, + 'application_name' => $application->name, ]); } }