From ab30f95ad9d5cc118e656a31e5eea6560c53363f Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Tue, 15 Sep 2026 12:58:59 +0200 Subject: [PATCH] feat(restarts): make resource restart limits opt-in Default restart limits to zero for applications, previews, and services, and bump the Coolify version to 4.3.21. --- app/Livewire/Project/Application/Advanced.php | 4 +-- app/Livewire/Project/Service/Index.php | 4 +-- app/Models/Application.php | 4 +++ app/Models/ApplicationPreview.php | 4 +++ app/Models/ServiceApplication.php | 1 + config/constants.php | 2 +- ...9_15_105627_make_restart_limits_opt_in.php | 32 +++++++++++++++++++ other/nightly/versions.json | 2 +- .../Feature/AllResourceRestartLimitsTest.php | 28 ++++++++++++++++ tests/Unit/ProductionImageWorkflowTest.php | 4 +-- versions.json | 2 +- 11 files changed, 78 insertions(+), 9 deletions(-) create mode 100644 database/migrations/2026_09_15_105627_make_restart_limits_opt_in.php diff --git a/app/Livewire/Project/Application/Advanced.php b/app/Livewire/Project/Application/Advanced.php index a9e1c0be28..89d2011dcf 100644 --- a/app/Livewire/Project/Application/Advanced.php +++ b/app/Livewire/Project/Application/Advanced.php @@ -82,7 +82,7 @@ class Advanced extends Component public bool $isConnectToDockerNetworkEnabled = false; #[Validate(['integer', 'min:0'])] - public int $maxRestartCount = 10; + public int $maxRestartCount = 0; public function mount() { @@ -142,7 +142,7 @@ class Advanced extends Component $this->disableBuildCache = $this->application->settings->disable_build_cache; $this->injectBuildArgsToDockerfile = $this->application->settings->inject_build_args_to_dockerfile ?? true; $this->includeSourceCommitInBuild = $this->application->settings->include_source_commit_in_build ?? false; - $this->maxRestartCount = $this->application->max_restart_count ?? 10; + $this->maxRestartCount = $this->application->max_restart_count ?? 0; } // Load stop_grace_period separately since it has its own save handler diff --git a/app/Livewire/Project/Service/Index.php b/app/Livewire/Project/Service/Index.php index c73e8bb06e..f4b6bec2d4 100644 --- a/app/Livewire/Project/Service/Index.php +++ b/app/Livewire/Project/Service/Index.php @@ -84,7 +84,7 @@ class Index extends Component public bool $isStripprefixEnabled = false; - public mixed $maxRestartCount = 10; + public mixed $maxRestartCount = 0; protected $listeners = ['generateDockerCompose', 'refreshScheduledBackups' => '$refresh', 'refreshFileStorages']; @@ -432,7 +432,7 @@ class Index extends Component $this->isLogDrainEnabled = data_get($this->serviceApplication, 'is_log_drain_enabled', false); $this->isGzipEnabled = data_get($this->serviceApplication, 'is_gzip_enabled', true); $this->isStripprefixEnabled = data_get($this->serviceApplication, 'is_stripprefix_enabled', true); - $this->maxRestartCount = $this->serviceApplication->max_restart_count ?? 10; + $this->maxRestartCount = $this->serviceApplication->max_restart_count ?? 0; } } diff --git a/app/Models/Application.php b/app/Models/Application.php index 38b8c5b0e2..14adbcef38 100644 --- a/app/Models/Application.php +++ b/app/Models/Application.php @@ -135,6 +135,10 @@ class Application extends BaseModel private static $parserVersion = '5'; + protected $attributes = [ + 'max_restart_count' => 0, + ]; + protected $fillable = [ 'name', 'description', diff --git a/app/Models/ApplicationPreview.php b/app/Models/ApplicationPreview.php index bffbdab621..d15142b6ad 100644 --- a/app/Models/ApplicationPreview.php +++ b/app/Models/ApplicationPreview.php @@ -13,6 +13,10 @@ class ApplicationPreview extends BaseModel { use HasRestartLimit, SoftDeletes; + protected $attributes = [ + 'max_restart_count' => 0, + ]; + protected $fillable = [ 'uuid', 'application_id', diff --git a/app/Models/ServiceApplication.php b/app/Models/ServiceApplication.php index cba18c1f23..066a86fac8 100644 --- a/app/Models/ServiceApplication.php +++ b/app/Models/ServiceApplication.php @@ -54,6 +54,7 @@ class ServiceApplication extends BaseModel protected $attributes = [ 'is_force_https_enabled' => true, + 'max_restart_count' => 0, ]; protected function casts(): array diff --git a/config/constants.php b/config/constants.php index 3f8335134f..6a37550e4f 100644 --- a/config/constants.php +++ b/config/constants.php @@ -2,7 +2,7 @@ return [ 'coolify' => [ - 'version' => env('COOLIFY_VERSION') ?: '4.3.20', + 'version' => env('COOLIFY_VERSION') ?: '4.3.21', 'helper_version' => '1.0.17', 'realtime_version' => '1.0.19', 'railpack_version' => '0.23.0', diff --git a/database/migrations/2026_09_15_105627_make_restart_limits_opt_in.php b/database/migrations/2026_09_15_105627_make_restart_limits_opt_in.php new file mode 100644 index 0000000000..89d3efb333 --- /dev/null +++ b/database/migrations/2026_09_15_105627_make_restart_limits_opt_in.php @@ -0,0 +1,32 @@ +integer('max_restart_count')->default(0)->change(); + }); + } + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + foreach (['applications', 'application_previews', 'service_applications'] as $tableName) { + Schema::table($tableName, function (Blueprint $table) { + $table->integer('max_restart_count')->default(10)->change(); + }); + } + } +}; diff --git a/other/nightly/versions.json b/other/nightly/versions.json index 8ae9763c72..e010c30695 100644 --- a/other/nightly/versions.json +++ b/other/nightly/versions.json @@ -1,7 +1,7 @@ { "coolify": { "v4": { - "version": "4.3.20" + "version": "4.3.21" }, "nightly": { "version": "4.4-rc.1" diff --git a/tests/Feature/AllResourceRestartLimitsTest.php b/tests/Feature/AllResourceRestartLimitsTest.php index 7da82f7d65..62594fc8b6 100644 --- a/tests/Feature/AllResourceRestartLimitsTest.php +++ b/tests/Feature/AllResourceRestartLimitsTest.php @@ -3,6 +3,7 @@ use App\Actions\Docker\GetContainersStatus; use App\Actions\Service\StopServiceApplication; use App\Jobs\PushServerUpdateJob; +use App\Models\Application; use App\Models\ApplicationPreview; use App\Models\ServiceApplication; use App\Models\ServiceDatabase; @@ -209,6 +210,33 @@ it('limits restarts only for applications', function () { ->toContain('$resetRestartCount && $serviceApplication instanceof ServiceApplication'); }); +it('makes restart limits opt in for new application resources', function () { + $migrationPaths = glob(database_path('migrations/*_make_restart_limits_opt_in.php')); + + expect($migrationPaths)->toHaveCount(1); + + $migration = file_get_contents($migrationPaths[0]); + + expect($migration) + ->toContain("['applications', 'application_previews', 'service_applications']") + ->toContain("integer('max_restart_count')->default(0)->change()") + ->not->toContain('->update('); + + $applicationSettings = file_get_contents(app_path('Livewire/Project/Application/Advanced.php')); + $serviceSettings = file_get_contents(app_path('Livewire/Project/Service/Index.php')); + + expect($applicationSettings) + ->toContain('public int $maxRestartCount = 0;') + ->toContain('$this->application->max_restart_count ?? 0') + ->and($serviceSettings) + ->toContain('public mixed $maxRestartCount = 0;') + ->toContain('$this->serviceApplication->max_restart_count ?? 0'); + + foreach ([Application::class, ApplicationPreview::class, ServiceApplication::class] as $modelClass) { + expect((new $modelClass)->max_restart_count)->toBe(0); + } +}); + it('does not render restart limit warnings for service databases', function () { $html = Blade::render( '', diff --git a/tests/Unit/ProductionImageWorkflowTest.php b/tests/Unit/ProductionImageWorkflowTest.php index 8d64d5b12a..588b405310 100644 --- a/tests/Unit/ProductionImageWorkflowTest.php +++ b/tests/Unit/ProductionImageWorkflowTest.php @@ -23,8 +23,8 @@ it('publishes v4 branch builds under the commit sha with a traceable internal ve ->toContain('ARG COOLIFY_VERSION') ->toContain('ENV COOLIFY_VERSION=${COOLIFY_VERSION}') ->and($constants) - ->toContain("'version' => env('COOLIFY_VERSION') ?: '4.3.19'") - ->and($versions['coolify']['v4']['version'])->toBe('4.3.19') + ->toContain("'version' => env('COOLIFY_VERSION') ?: '4.3.21'") + ->and($versions['coolify']['v4']['version'])->toBe('4.3.21') ->and($versions['coolify']['nightly']['version'])->toBe('4.4-rc.1') ->and($nightlyVersions)->toBe($versions); }); diff --git a/versions.json b/versions.json index 8ae9763c72..e010c30695 100644 --- a/versions.json +++ b/versions.json @@ -1,7 +1,7 @@ { "coolify": { "v4": { - "version": "4.3.20" + "version": "4.3.21" }, "nightly": { "version": "4.4-rc.1"