From 47d37c6047c58b31a3fbca496f0516438320db4d Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Wed, 28 Jun 2023 13:27:05 +0200 Subject: [PATCH 01/17] fix: cancel deployment button --- config/version.php | 2 +- resources/views/livewire/destination/show.blade.php | 12 +++++------- .../project/application/deployment-navbar.blade.php | 2 -- versions.json | 2 +- 4 files changed, 7 insertions(+), 11 deletions(-) diff --git a/config/version.php b/config/version.php index b343fad81..6c54c29bf 100644 --- a/config/version.php +++ b/config/version.php @@ -1,3 +1,3 @@ Found Destinations @endif @foreach ($networks as $network) -
-
{{ data_get($network, 'Name') }}
- - Configure - -
+ + Add{{ data_get($network, 'Name') }} + + @endforeach diff --git a/resources/views/livewire/project/application/deployment-navbar.blade.php b/resources/views/livewire/project/application/deployment-navbar.blade.php index 5d91531ce..c5f09d175 100644 --- a/resources/views/livewire/project/application/deployment-navbar.blade.php +++ b/resources/views/livewire/project/application/deployment-navbar.blade.php @@ -2,7 +2,5 @@

Logs

@if (data_get($activity, 'properties.status') === 'in_progress') Cancel deployment - @else - Cancel deployment @endif diff --git a/versions.json b/versions.json index 8baf727d0..0145b0950 100644 --- a/versions.json +++ b/versions.json @@ -4,7 +4,7 @@ "version": "3.12.32" }, "v4": { - "version": "4.0.0-beta.14" + "version": "4.0.0-beta.15" } } } \ No newline at end of file From ba18c589f0749843cbf40dc8775c0e36846c2e0f Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Wed, 28 Jun 2023 13:37:00 +0200 Subject: [PATCH 02/17] fix: public repo limit shown + branch should be preselected. --- .../Project/New/PublicGitRepository.php | 14 +++++++++----- bootstrap/helpers/github.php | 1 + .../new/public-git-repository.blade.php | 18 +++++++++--------- 3 files changed, 19 insertions(+), 14 deletions(-) diff --git a/app/Http/Livewire/Project/New/PublicGitRepository.php b/app/Http/Livewire/Project/New/PublicGitRepository.php index 05793695e..9e24ed56d 100644 --- a/app/Http/Livewire/Project/New/PublicGitRepository.php +++ b/app/Http/Livewire/Project/New/PublicGitRepository.php @@ -8,6 +8,7 @@ use App\Models\Project; use App\Models\StandaloneDocker; use App\Models\SwarmDocker; +use Illuminate\Support\Facades\Log; use Livewire\Component; use Spatie\Url\Url; @@ -21,15 +22,17 @@ class PublicGitRepository extends Component public $parameters; public $query; - public $branches = []; + public bool $branch_found = false; public string $selected_branch = 'main'; public bool $is_static = false; public string|null $publish_directory = null; + public string $git_branch; + public int $rate_limit_remaining = 0; + public int $rate_limit_reset = 0; private GithubApp|GitlabApp $git_source; private string $git_host; private string $git_repository; - private string $git_branch; protected $rules = [ 'repository_url' => 'required|url', @@ -64,16 +67,17 @@ public function instantSave() } $this->emit('success', 'Application settings updated!'); } - public function load_branches() + public function load_branch() { + $this->branch_found = false; $this->validate([ 'repository_url' => 'required|url' ]); $this->get_git_source(); try { - ['data' => $data] = git_api(source: $this->git_source, endpoint: "/repos/{$this->git_repository}/branches"); - $this->branches = collect($data)->pluck('name')->toArray(); + ['data' => $data, 'rate_limit_remaining' => $this->rate_limit_remaining, 'rate_limit_reset' => $this->rate_limit_reset] = git_api(source: $this->git_source, endpoint: "/repos/{$this->git_repository}/branches/{$this->git_branch}"); + $this->branch_found = true; } catch (\Throwable $e) { return general_error_handler(err: $e, that: $this); } diff --git a/bootstrap/helpers/github.php b/bootstrap/helpers/github.php index f282ee6f1..53a0f52fb 100644 --- a/bootstrap/helpers/github.php +++ b/bootstrap/helpers/github.php @@ -68,6 +68,7 @@ function git_api(GithubApp|GitlabApp $source, string $endpoint, string $method = } return [ 'rate_limit_remaining' => $response->header('X-RateLimit-Remaining'), + 'rate_limit_reset' => $response->header('X-RateLimit-Reset'), 'data' => collect($json) ]; } diff --git a/resources/views/livewire/project/new/public-git-repository.blade.php b/resources/views/livewire/project/new/public-git-repository.blade.php index 53ef8bbd0..63cfc0f54 100644 --- a/resources/views/livewire/project/new/public-git-repository.blade.php +++ b/resources/views/livewire/project/new/public-git-repository.blade.php @@ -5,21 +5,21 @@
- - + Check repository
- @if (count($branches) > 0) + @if ($branch_found) +
+
Rate limit remaining: {{ $rate_limit_remaining }}
+
Rate limit reset at: {{ date('Y-m-d H:i:s', substr($rate_limit_reset, 0, 10)) }}
+
- - - @foreach ($branches as $branch) - - @endforeach - + @if ($is_static) From 80af200c9f910eb293f6738a2c4be9679b316b93 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Wed, 28 Jun 2023 18:20:01 +0200 Subject: [PATCH 03/17] feat: long running queue with 1 hour of timeout --- app/Jobs/ApplicationDeploymentJob.php | 24 ++++++++++++------ bootstrap/helpers/applications.php | 4 +-- bootstrap/helpers/github.php | 2 +- config/horizon.php | 25 ++++++++++++++++++- config/queue.php | 11 ++++++-- docker/coolify-builder/Dockerfile | 2 +- .../application/deployment-navbar.blade.php | 2 +- .../project/application/deployments.blade.php | 4 +-- resources/views/vendor/toaster/hub.blade.php | 2 +- 9 files changed, 57 insertions(+), 19 deletions(-) diff --git a/app/Jobs/ApplicationDeploymentJob.php b/app/Jobs/ApplicationDeploymentJob.php index 4f3911353..f38cf8463 100644 --- a/app/Jobs/ApplicationDeploymentJob.php +++ b/app/Jobs/ApplicationDeploymentJob.php @@ -17,12 +17,12 @@ use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\SerializesModels; use Illuminate\Support\Collection; -use Illuminate\Support\Facades\Notification; use Illuminate\Support\Facades\Storage; use Spatie\Activitylog\Models\Activity; use Symfony\Component\Yaml\Yaml; use Illuminate\Support\Str; use Spatie\Url\Url; +use Throwable; use Visus\Cuid2\Cuid2; class ApplicationDeploymentJob implements ShouldQueue @@ -46,7 +46,7 @@ class ApplicationDeploymentJob implements ShouldQueue private ApplicationPreview|null $preview = null; public static int $batch_counter = 0; - public $timeout = 10200; + public $failOnTimeout = true; public function __construct( public int $application_deployment_queue_id, @@ -128,7 +128,8 @@ public function handle(): void "echo '\nOops something is not okay, are you okay? 😢'", "echo '\n\n{$e->getMessage()}'", ]); - $this->fail(); + ray($e); + $this->fail($e->getMessage()); } finally { if (isset($this->docker_compose)) { Storage::disk('deployments')->put(Str::kebab($this->application->name) . '/docker-compose.yml', $this->docker_compose); @@ -142,9 +143,15 @@ private function start_builder_image() $this->execute_now([ "echo -n 'Pulling latest version of the builder image (ghcr.io/coollabsio/coolify-builder)... '", ]); - $this->execute_now([ - "docker run --pull=always -d --name {$this->deployment_uuid} --rm -v /var/run/docker.sock:/var/run/docker.sock ghcr.io/coollabsio/coolify-builder", - ], isDebuggable: true); + if (isDev()) { + $this->execute_now([ + "docker run -d --name {$this->deployment_uuid} --rm -v /var/run/docker.sock:/var/run/docker.sock coolify-builder", + ], isDebuggable: true); + } else { + $this->execute_now([ + "docker run --pull=always -d --name {$this->deployment_uuid} --rm -v /var/run/docker.sock:/var/run/docker.sock ghcr.io/coollabsio/coolify-builder", + ], isDebuggable: true); + } $this->execute_now([ "echo 'Done.'" ]); @@ -291,8 +298,9 @@ private function deploy() $this->next(ProcessStatus::FINISHED->value); } - public function failed(): void + public function failed(Throwable $exception): void { + ray($exception); $this->next(ProcessStatus::ERROR->value); } @@ -329,7 +337,7 @@ private function next(string $status) } private function execute_in_builder(string $command) { - return "docker exec {$this->deployment_uuid} bash -c '{$command}'"; + return "docker exec {$this->deployment_uuid} bash -c '{$command} |& tee -a /proc/1/fd/1'"; } private function generate_environment_variables($ports) { diff --git a/bootstrap/helpers/applications.php b/bootstrap/helpers/applications.php index bbf24ff00..0f69d42ca 100644 --- a/bootstrap/helpers/applications.php +++ b/bootstrap/helpers/applications.php @@ -34,7 +34,7 @@ function queue_application_deployment(int $application_id, string $deployment_uu force_rebuild: $force_rebuild, rollback_commit: $commit, pull_request_id: $pull_request_id, - )); + ))->onConnection('long-running')->onQueue('long-running'); } function queue_next_deployment(Application $application) @@ -47,6 +47,6 @@ function queue_next_deployment(Application $application) deployment_uuid: $next_found->deployment_uuid, force_rebuild: $next_found->force_rebuild, pull_request_id: $next_found->pull_request_id - )); + ))->onConnection('long-running')->onQueue('long-running'); } } diff --git a/bootstrap/helpers/github.php b/bootstrap/helpers/github.php index 53a0f52fb..4e4fdd7fc 100644 --- a/bootstrap/helpers/github.php +++ b/bootstrap/helpers/github.php @@ -64,7 +64,7 @@ function git_api(GithubApp|GitlabApp $source, string $endpoint, string $method = } $json = $response->json(); if ($response->failed() && $throwError) { - throw new \Exception("Failed to get data from {$source->name} with error: " . $json['message']); + throw new \Exception("Failed to get data from {$source->name} with error:

" . $json['message']); } return [ 'rate_limit_remaining' => $response->header('X-RateLimit-Remaining'), diff --git a/config/horizon.php b/config/horizon.php index d9f841aa6..f35cbd731 100644 --- a/config/horizon.php +++ b/config/horizon.php @@ -190,7 +190,18 @@ 'maxJobs' => 0, 'memory' => 128, 'tries' => 1, - 'timeout' => 3600, + 'timeout' => 300, + 'nice' => 0, + ], + 'long-running' => [ + 'connection' => 'redis', + 'queue' => ['long-running'], + 'balance' => 'auto', + 'maxTime' => 0, + 'maxJobs' => 0, + 'memory' => 128, + 'tries' => 1, + 'timeout' => 3560, 'nice' => 0, ], ], @@ -203,6 +214,12 @@ 'balanceMaxShift' => env('HORIZON_BALANCE_MAX_SHIFT', 1), 'balanceCooldown' => env('HORIZON_BALANCE_COOLDOWN', 1), ], + 'long-running' => [ + 'autoScalingStrategy' => 'size', + 'maxProcesses' => env('HORIZON_MAX_PROCESSES', 10), + 'balanceMaxShift' => env('HORIZON_BALANCE_MAX_SHIFT', 1), + 'balanceCooldown' => env('HORIZON_BALANCE_COOLDOWN', 1), + ], ], 'local' => [ @@ -212,6 +229,12 @@ 'balanceMaxShift' => env('HORIZON_BALANCE_MAX_SHIFT', 1), 'balanceCooldown' => env('HORIZON_BALANCE_COOLDOWN', 1), ], + 'long-running' => [ + 'autoScalingStrategy' => 'size', + 'maxProcesses' => env('HORIZON_MAX_PROCESSES', 10), + 'balanceMaxShift' => env('HORIZON_BALANCE_MAX_SHIFT', 1), + 'balanceCooldown' => env('HORIZON_BALANCE_COOLDOWN', 1), + ], ], ], ]; diff --git a/config/queue.php b/config/queue.php index a7a3d46f8..7bb782605 100644 --- a/config/queue.php +++ b/config/queue.php @@ -33,7 +33,14 @@ 'sync' => [ 'driver' => 'sync', ], - + 'long-running' => [ + 'driver' => 'redis', + 'connection' => 'default', + 'queue' => 'long-running', + 'retry_after' => 3600, + 'block_for' => null, + 'after_commit' => false, + ], 'database' => [ 'driver' => 'database', 'table' => 'jobs', @@ -66,7 +73,7 @@ 'driver' => 'redis', 'connection' => 'default', 'queue' => env('REDIS_QUEUE', 'default'), - 'retry_after' => 90, + 'retry_after' => 300, 'block_for' => null, 'after_commit' => false, ], diff --git a/docker/coolify-builder/Dockerfile b/docker/coolify-builder/Dockerfile index d03e0196c..390ea38f9 100644 --- a/docker/coolify-builder/Dockerfile +++ b/docker/coolify-builder/Dockerfile @@ -35,5 +35,5 @@ RUN if [[ ${TARGETPLATFORM} == 'linux/arm64' ]]; then \ ;fi ENTRYPOINT ["/sbin/tini", "--"] -CMD ["sh", "-c", "while true; do sleep 3600 && exit 0; done"] +CMD ["sh", "-c", "while true; do sleep 1; done"] diff --git a/resources/views/livewire/project/application/deployment-navbar.blade.php b/resources/views/livewire/project/application/deployment-navbar.blade.php index c5f09d175..87654251e 100644 --- a/resources/views/livewire/project/application/deployment-navbar.blade.php +++ b/resources/views/livewire/project/application/deployment-navbar.blade.php @@ -1,6 +1,6 @@

Logs

- @if (data_get($activity, 'properties.status') === 'in_progress') + @if (data_get($activity, 'properties.status') === 'in_progress' || data_get($activity, 'properties.status') === 'queued') Cancel deployment @endif
diff --git a/resources/views/livewire/project/application/deployments.blade.php b/resources/views/livewire/project/application/deployments.blade.php index ff1099028..1385025af 100644 --- a/resources/views/livewire/project/application/deployments.blade.php +++ b/resources/views/livewire/project/application/deployments.blade.php @@ -67,8 +67,8 @@ class="hover:no-underline"> dayjs.extend(window.dayjs_plugin_relativeTime); Alpine.data('elapsedTime', (uuid, status, created_at, updated_at) => ({ - finished_time: '0s', - started_time: '0s', + finished_time: 'calculating...', + started_time: 'calculating...', init() { if (timers[uuid]) { clearInterval(timers[uuid]); diff --git a/resources/views/vendor/toaster/hub.blade.php b/resources/views/vendor/toaster/hub.blade.php index 9bdcd47d6..5aff1b506 100644 --- a/resources/views/vendor/toaster/hub.blade.php +++ b/resources/views/vendor/toaster/hub.blade.php @@ -71,7 +71,7 @@ class="relative flex duration-300 transform transition ease-in-out max-w-md w-fu
- + @if ($closeable) From fed35d9c1370d4fd7516191b15ef377a7226e280 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Thu, 29 Jun 2023 17:16:50 +0200 Subject: [PATCH 04/17] fix: registration/login button fix: init user registrations --- app/Providers/FortifyServiceProvider.php | 5 +++++ resources/css/app.css | 2 +- resources/views/auth/login.blade.php | 5 ++--- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/app/Providers/FortifyServiceProvider.php b/app/Providers/FortifyServiceProvider.php index a1b116560..0a3d02ff7 100644 --- a/app/Providers/FortifyServiceProvider.php +++ b/app/Providers/FortifyServiceProvider.php @@ -52,6 +52,11 @@ public function boot(): void Fortify::loginView(function () { $settings = InstanceSettings::get(); + $users = User::count(); + if ($users == 0) { + // If there are no users, redirect to registration + return redirect()->route('register'); + } return view('auth.login', [ 'is_registration_enabled' => $settings->is_registration_enabled ]); diff --git a/resources/css/app.css b/resources/css/app.css index 8602c69a5..1ed610d1c 100644 --- a/resources/css/app.css +++ b/resources/css/app.css @@ -97,7 +97,7 @@ @keyframes lds-heart { } } .bg-coollabs-gradient { - @apply text-transparent bg-clip-text bg-gradient-to-r from-purple-500 via-pink-500 to-red-500; + @apply text-transparent text-white bg-gradient-to-r from-purple-500 via-pink-500 to-red-500; } .text-helper { @apply inline-block font-bold text-warning; diff --git a/resources/views/auth/login.blade.php b/resources/views/auth/login.blade.php index 1bb5c9b28..0a66be609 100644 --- a/resources/views/auth/login.blade.php +++ b/resources/views/auth/login.blade.php @@ -8,8 +8,7 @@

{{ __('auth.login') }}

@if ($is_registration_enabled) - + {{ __('auth.register_now') }} @endif @@ -41,7 +40,7 @@ class="text-xs text-center text-white normal-case bg-transparent border-none rou
@endif @if (session('status')) -
+
{{ session('status') }}
@endif From 4daa10d38b44e28e82417c67ca423f834a903cb3 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Fri, 30 Jun 2023 10:49:00 +0200 Subject: [PATCH 05/17] fix: better status on ui for apps --- app/Http/Livewire/Application/Heading.php | 71 ++++++++ app/Jobs/ApplicationDeploymentJob.php | 37 ++--- app/Models/ApplicationDeploymentQueue.php | 2 - docker-compose.prod.yml | 3 +- .../applications/actions.blade.php} | 11 +- .../applications/breadcrumbs.blade.php | 49 ++++++ .../components/applications/links.blade.php | 92 +++++++++++ .../components/applications/navbar.blade.php | 154 +----------------- .../components/status/restarting.blade.php | 2 +- .../livewire/application/heading.blade.php | 4 + .../application/configuration.blade.php | 2 +- .../project/application/deployment.blade.php | 2 +- .../project/application/deployments.blade.php | 2 +- 13 files changed, 250 insertions(+), 181 deletions(-) create mode 100644 app/Http/Livewire/Application/Heading.php rename resources/views/{livewire/project/application/deploy.blade.php => components/applications/actions.blade.php} (95%) create mode 100644 resources/views/components/applications/breadcrumbs.blade.php create mode 100644 resources/views/components/applications/links.blade.php create mode 100644 resources/views/livewire/application/heading.blade.php diff --git a/app/Http/Livewire/Application/Heading.php b/app/Http/Livewire/Application/Heading.php new file mode 100644 index 000000000..619d4b8ba --- /dev/null +++ b/app/Http/Livewire/Application/Heading.php @@ -0,0 +1,71 @@ +parameters = getRouteParameters(); + } + + public function check_status() + { + dispatch_sync(new ApplicationContainerStatusJob( + application: $this->application, + container_name: generate_container_name($this->application->uuid), + )); + $this->application->refresh(); + } + public function deploy(bool $force_rebuild = false) + { + $this->setDeploymentUuid(); + queue_application_deployment( + application_id: $this->application->id, + deployment_uuid: $this->deploymentUuid, + force_rebuild: $force_rebuild, + ); + return redirect()->route('project.application.deployment', [ + 'project_uuid' => $this->parameters['project_uuid'], + 'application_uuid' => $this->parameters['application_uuid'], + 'deployment_uuid' => $this->deploymentUuid, + 'environment_name' => $this->parameters['environment_name'], + ]); + } + public function force_deploy_with_debug() + { + if ($this->application->settings->is_debug_enabled == false) { + $this->application->settings->is_debug_enabled = true; + $this->application->settings->save(); + } + $this->deploy(); + } + public function force_deploy_without_cache() + { + $this->deploy(force_rebuild: true); + } + public function stop() + { + remote_process( + ["docker rm -f {$this->application->uuid}"], + $this->application->destination->server + ); + $this->application->status = 'stopped'; + $this->application->save(); + } + protected function setDeploymentUuid() + { + $this->deploymentUuid = new Cuid2(7); + $this->parameters['deployment_uuid'] = $this->deploymentUuid; + } +} diff --git a/app/Jobs/ApplicationDeploymentJob.php b/app/Jobs/ApplicationDeploymentJob.php index f38cf8463..416340565 100644 --- a/app/Jobs/ApplicationDeploymentJob.php +++ b/app/Jobs/ApplicationDeploymentJob.php @@ -143,15 +143,15 @@ private function start_builder_image() $this->execute_now([ "echo -n 'Pulling latest version of the builder image (ghcr.io/coollabsio/coolify-builder)... '", ]); - if (isDev()) { - $this->execute_now([ - "docker run -d --name {$this->deployment_uuid} --rm -v /var/run/docker.sock:/var/run/docker.sock coolify-builder", - ], isDebuggable: true); - } else { - $this->execute_now([ - "docker run --pull=always -d --name {$this->deployment_uuid} --rm -v /var/run/docker.sock:/var/run/docker.sock ghcr.io/coollabsio/coolify-builder", - ], isDebuggable: true); - } + // if (isDev()) { + // $this->execute_now([ + // "docker run -d --name {$this->deployment_uuid} --rm -v /var/run/docker.sock:/var/run/docker.sock coolify-builder", + // ], isDebuggable: true); + // } else { + $this->execute_now([ + "docker run --pull=always -d --name {$this->deployment_uuid} --rm -v /var/run/docker.sock:/var/run/docker.sock ghcr.io/coollabsio/coolify-builder", + ], isDebuggable: true); + // } $this->execute_now([ "echo 'Done.'" ]); @@ -300,22 +300,19 @@ private function deploy() public function failed(Throwable $exception): void { - ray($exception); $this->next(ProcessStatus::ERROR->value); } private function next(string $status) { - if (!Str::of($this->application_deployment_queue->status)->startsWith('cancelled')) { - ray('Next Status: ' . $status)->green(); - $this->application_deployment_queue->update([ - 'status' => $status, - ]); - $this->activity->properties = $this->activity->properties->merge([ - 'status' => $status, - ]); - $this->activity->save(); - } + ray('Next Status: ' . $status)->green(); + $this->application_deployment_queue->update([ + 'status' => $status, + ]); + $this->activity->properties = $this->activity->properties->merge([ + 'status' => $status, + ]); + $this->activity->save(); if ($this->pull_request_id) { dispatch(new ApplicationPullRequestUpdateJob( application_id: $this->application->id, diff --git a/app/Models/ApplicationDeploymentQueue.php b/app/Models/ApplicationDeploymentQueue.php index 474c38cc8..39642813a 100644 --- a/app/Models/ApplicationDeploymentQueue.php +++ b/app/Models/ApplicationDeploymentQueue.php @@ -2,9 +2,7 @@ namespace App\Models; -use Illuminate\Contracts\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Model; -use Spatie\SchemalessAttributes\Casts\SchemalessAttributes; class ApplicationDeploymentQueue extends Model { diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml index cc22fad99..872480a6e 100644 --- a/docker-compose.prod.yml +++ b/docker-compose.prod.yml @@ -26,7 +26,8 @@ services: - REDIS_PASSWORD - SSL_MODE=off - PHP_PM_CONTROL=dynamic - - PHP_PM_START_SERVERS=5 + - PHP_PM_START_SERVERS=1 + - PHP_PM_MIN_SPARE_SERVERS=1 - PHP_PM_MAX_SPARE_SERVERS=10 ports: - "${APP_PORT:-8000}:80" diff --git a/resources/views/livewire/project/application/deploy.blade.php b/resources/views/components/applications/actions.blade.php similarity index 95% rename from resources/views/livewire/project/application/deploy.blade.php rename to resources/views/components/applications/actions.blade.php index dda1e9a9a..d762a5360 100644 --- a/resources/views/livewire/project/application/deploy.blade.php +++ b/resources/views/components/applications/actions.blade.php @@ -1,4 +1,4 @@ -
+