diff --git a/CHANGELOG.md b/CHANGELOG.md
index 177012001..04b99c646 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,33 @@ # Changelog
## [unreleased]
+### 🐛 Bug Fixes
+
+- *(docker)* Adjust openssh-client installation in Dockerfile to avoid version bug
+- *(docker)* Streamline openssh-client installation in Dockerfile
+
+### 📚 Documentation
+
+- Update changelog
+
+### ⚙️ Miscellaneous Tasks
+
+- *(versions)* Increment coolify version numbers to 4.0.0-beta.431 and 4.0.0-beta.432 in configuration files
+
+## [4.0.0-beta.430] - 2025-09-24
+
+### 🐛 Bug Fixes
+
+- *(PreviewCompose)* Adds port to preview urls
+- *(deployment-job)* Enhance build time variable analysis
+
+### 📚 Documentation
+
+- Update changelog
+- Update changelog
+
+## [4.0.0-beta.429] - 2025-09-23
+
### 🚀 Features
- *(environment)* Replace is_buildtime_only with is_runtime and is_buildtime flags for environment variables, updating related logic and views
@@ -23,6 +50,8 @@ ### 🚀 Features
- *(cloud-check)* Enhance CloudCheckSubscription command with fix options
- *(stripe)* Enhance subscription handling and verification process
- *(private-key-refresh)* Add refresh dispatch on private key update and connection check
+- *(comments)* Add automated comments for labeled pull requests to guide documentation updates
+- *(comments)* Ping PR author
### 🐛 Bug Fixes
@@ -42,6 +71,8 @@ ### 🐛 Bug Fixes
- *(environment-variables)* Correct method call syntax in analyzeBuildVariable function
- *(clears-global-search-cache)* Refine team retrieval logic in getTeamIdForCache method
- *(subscription-job)* Enhance retry logic for VerifyStripeSubscriptionStatusJob
+- *(environment-variable)* Update checkbox visibility and helper text for build and runtime options
+- *(deployment-job)* Escape single quotes in build arguments for Docker Compose command
### 🚜 Refactor
@@ -75,6 +106,8 @@ ### 🎨 Styling
### ⚙️ Miscellaneous Tasks
- Change order of runtime and buildtime
+- *(docker-compose)* Update soketi image version to 1.0.10 in production and Windows configurations
+- *(versions)* Update coolify version numbers to 4.0.0-beta.430 and 4.0.0-beta.431 in configuration files
## [4.0.0-beta.428] - 2025-09-15
diff --git a/resources/views/livewire/project/application/general.blade.php b/resources/views/livewire/project/application/general.blade.php
index f2468c6b7..3b9609ac4 100644
--- a/resources/views/livewire/project/application/general.blade.php
+++ b/resources/views/livewire/project/application/general.blade.php
@@ -268,6 +268,14 @@ class="underline" href="https://coolify.io/docs/knowledge-base/docker/registry"
helper="If you use this, you need to specify paths relatively and should use the same compose file in the custom command, otherwise the automatically configured labels / etc won't work.
So in your case, use: docker compose -f .{{ Str::start($application->base_directory . $application->docker_compose_location, '/') }} up -d"
label="Custom Start Command" />
+ @if ($this->application->is_github_based())
+
+
+
+ @endif
@else
@@ -299,7 +307,7 @@ class="underline" href="https://coolify.io/docs/knowledge-base/docker/registry"
@endif
- @if ($this->application->is_github_based() && !$this->application->is_public_repository())
+ @if ($this->application->is_github_based())
watch_paths = null;
+
+ $modified_files = collect(['docker-compose.yml', 'README.md']);
+
+ $this->assertFalse($application->isWatchPathsTriggered($modified_files));
+ }
+
+ public function test_is_watch_paths_triggered_with_exact_match()
+ {
+ $application = new Application();
+ $application->watch_paths = "docker-compose.yml\nDockerfile";
+
+ // Exact match should return true
+ $this->assertTrue($application->isWatchPathsTriggered(collect(['docker-compose.yml'])));
+ $this->assertTrue($application->isWatchPathsTriggered(collect(['Dockerfile'])));
+
+ // Non-matching file should return false
+ $this->assertFalse($application->isWatchPathsTriggered(collect(['README.md'])));
+ }
+
+ public function test_is_watch_paths_triggered_with_wildcard_patterns()
+ {
+ $application = new Application();
+ $application->watch_paths = "*.yml\nsrc/**/*.php\nconfig/*";
+
+ // Wildcard matches
+ $this->assertTrue($application->isWatchPathsTriggered(collect(['docker-compose.yml'])));
+ $this->assertTrue($application->isWatchPathsTriggered(collect(['production.yml'])));
+ $this->assertTrue($application->isWatchPathsTriggered(collect(['src/Controllers/UserController.php'])));
+ $this->assertTrue($application->isWatchPathsTriggered(collect(['src/Models/User.php'])));
+ $this->assertTrue($application->isWatchPathsTriggered(collect(['config/app.php'])));
+
+ // Non-matching files
+ $this->assertFalse($application->isWatchPathsTriggered(collect(['README.md'])));
+ $this->assertFalse($application->isWatchPathsTriggered(collect(['src/index.js'])));
+ $this->assertFalse($application->isWatchPathsTriggered(collect(['configurations/deep/file.php'])));
+ }
+
+ public function test_is_watch_paths_triggered_with_multiple_files()
+ {
+ $application = new Application();
+ $application->watch_paths = "docker-compose.yml\n*.env";
+
+ // At least one file matches
+ $modified_files = collect(['README.md', 'docker-compose.yml', 'package.json']);
+ $this->assertTrue($application->isWatchPathsTriggered($modified_files));
+
+ // No files match
+ $modified_files = collect(['README.md', 'package.json', 'src/index.js']);
+ $this->assertFalse($application->isWatchPathsTriggered($modified_files));
+ }
+
+ public function test_is_watch_paths_triggered_with_complex_patterns()
+ {
+ $application = new Application();
+ // fnmatch doesn't support {a,b} syntax, so we need to use separate patterns
+ $application->watch_paths = "**/*.js\n**/*.jsx\n**/*.ts\n**/*.tsx";
+
+ // JavaScript/TypeScript files should match
+ $this->assertTrue($application->isWatchPathsTriggered(collect(['src/index.js'])));
+ $this->assertTrue($application->isWatchPathsTriggered(collect(['components/Button.jsx'])));
+ $this->assertTrue($application->isWatchPathsTriggered(collect(['types/user.ts'])));
+ $this->assertTrue($application->isWatchPathsTriggered(collect(['pages/Home.tsx'])));
+
+ // Deeply nested files should match
+ $this->assertTrue($application->isWatchPathsTriggered(collect(['src/components/ui/Button.tsx'])));
+
+ // Non-matching files
+ $this->assertFalse($application->isWatchPathsTriggered(collect(['README.md'])));
+ $this->assertFalse($application->isWatchPathsTriggered(collect(['package.json'])));
+ }
+
+ public function test_is_watch_paths_triggered_with_question_mark_pattern()
+ {
+ $application = new Application();
+ $application->watch_paths = "test?.txt\nfile-?.yml";
+
+ // Single character wildcard matches
+ $this->assertTrue($application->isWatchPathsTriggered(collect(['test1.txt'])));
+ $this->assertTrue($application->isWatchPathsTriggered(collect(['testA.txt'])));
+ $this->assertTrue($application->isWatchPathsTriggered(collect(['file-1.yml'])));
+ $this->assertTrue($application->isWatchPathsTriggered(collect(['file-B.yml'])));
+
+ // Non-matching files
+ $this->assertFalse($application->isWatchPathsTriggered(collect(['test.txt'])));
+ $this->assertFalse($application->isWatchPathsTriggered(collect(['test12.txt'])));
+ $this->assertFalse($application->isWatchPathsTriggered(collect(['file.yml'])));
+ }
+
+ public function test_is_watch_paths_triggered_with_character_set_pattern()
+ {
+ $application = new Application();
+ $application->watch_paths = "[abc]test.txt\nfile[0-9].yml";
+
+ // Character set matches
+ $this->assertTrue($application->isWatchPathsTriggered(collect(['atest.txt'])));
+ $this->assertTrue($application->isWatchPathsTriggered(collect(['btest.txt'])));
+ $this->assertTrue($application->isWatchPathsTriggered(collect(['ctest.txt'])));
+ $this->assertTrue($application->isWatchPathsTriggered(collect(['file1.yml'])));
+ $this->assertTrue($application->isWatchPathsTriggered(collect(['file9.yml'])));
+
+ // Non-matching files
+ $this->assertFalse($application->isWatchPathsTriggered(collect(['dtest.txt'])));
+ $this->assertFalse($application->isWatchPathsTriggered(collect(['test.txt'])));
+ $this->assertFalse($application->isWatchPathsTriggered(collect(['fileA.yml'])));
+ }
+
+ public function test_is_watch_paths_triggered_with_empty_watch_paths()
+ {
+ $application = new Application();
+ $application->watch_paths = '';
+
+ $this->assertFalse($application->isWatchPathsTriggered(collect(['any-file.txt'])));
+ }
+
+ public function test_is_watch_paths_triggered_with_whitespace_only_patterns()
+ {
+ $application = new Application();
+ $application->watch_paths = "\n \n\t\n";
+
+ $this->assertFalse($application->isWatchPathsTriggered(collect(['any-file.txt'])));
+ }
+
+ public function test_is_watch_paths_triggered_for_dockercompose_typical_patterns()
+ {
+ $application = new Application();
+ $application->watch_paths = "docker-compose*.yml\n.env*\nDockerfile*\nservices/**";
+
+ // Docker Compose related files
+ $this->assertTrue($application->isWatchPathsTriggered(collect(['docker-compose.yml'])));
+ $this->assertTrue($application->isWatchPathsTriggered(collect(['docker-compose.prod.yml'])));
+ $this->assertTrue($application->isWatchPathsTriggered(collect(['docker-compose-dev.yml'])));
+
+ // Environment files
+ $this->assertTrue($application->isWatchPathsTriggered(collect(['.env'])));
+ $this->assertTrue($application->isWatchPathsTriggered(collect(['.env.local'])));
+ $this->assertTrue($application->isWatchPathsTriggered(collect(['.env.production'])));
+
+ // Dockerfile variations
+ $this->assertTrue($application->isWatchPathsTriggered(collect(['Dockerfile'])));
+ $this->assertTrue($application->isWatchPathsTriggered(collect(['Dockerfile.prod'])));
+
+ // Service files
+ $this->assertTrue($application->isWatchPathsTriggered(collect(['services/api/app.js'])));
+ $this->assertTrue($application->isWatchPathsTriggered(collect(['services/web/index.html'])));
+
+ // Non-matching files (e.g., documentation, configs outside services)
+ $this->assertFalse($application->isWatchPathsTriggered(collect(['README.md'])));
+ $this->assertFalse($application->isWatchPathsTriggered(collect(['package.json'])));
+ $this->assertFalse($application->isWatchPathsTriggered(collect(['config/nginx.conf'])));
+ }
+}
\ No newline at end of file