Merge branch 'main' into feat/scheduled-tasks-cron
This commit is contained in:
		@@ -19,10 +19,12 @@ Thank you so much!
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
Special thanks to our biggest sponsors, [CCCareers](https://cccareers.org/) and [Appwrite](https://appwrite.io)!
 | 
					Special thanks to our biggest sponsors, [CCCareers](https://cccareers.org/) and [Appwrite](https://appwrite.io)!
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<a href="https://cccareers.org/" target="_blank"><img src="./other/logos/ccc-logo.webp" alt="appwrite logo" width="200"/></a>
 | 
					<a href="https://cccareers.org/" target="_blank"><img src="./other/logos/ccc-logo.webp" alt="cccareers logo" width="200"/></a>
 | 
				
			||||||
<a href="https://appwrite.io" target="_blank"><img src="./other/logos/appwrite.svg" alt="appwrite logo" width="200"/></a>
 | 
					<a href="https://appwrite.io" target="_blank"><img src="./other/logos/appwrite.svg" alt="appwrite logo" width="200"/></a>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Github Sponsors ($15+)
 | 
					## Github Sponsors ($15+)
 | 
				
			||||||
 | 
					<a href="https://bc.direct"><img width="60px" alt="BC Direct" src="https://github.com/coollabsio/coolify/assets/5845193/a4063c41-95ed-4a32-8814-cd1475572e37"/></a>
 | 
				
			||||||
 | 
					<a href="https://github.com/automazeio"><img src="https://github.com/automazeio.png" width="60px" alt="Corentin Clichy" /></a>
 | 
				
			||||||
<a href="https://github.com/corentinclichy"><img src="https://github.com/corentinclichy.png" width="60px" alt="Corentin Clichy" /></a>
 | 
					<a href="https://github.com/corentinclichy"><img src="https://github.com/corentinclichy.png" width="60px" alt="Corentin Clichy" /></a>
 | 
				
			||||||
<a href="https://github.com/Niki2k1"><img src="https://github.com/Niki2k1.png" width="60px" alt="Niklas Lausch" /></a>
 | 
					<a href="https://github.com/Niki2k1"><img src="https://github.com/Niki2k1.png" width="60px" alt="Niklas Lausch" /></a>
 | 
				
			||||||
<a href="https://github.com/pixelinfinito"><img src="https://github.com/pixelinfinito.png" width="60px" alt="Pixel Infinito" /></a>
 | 
					<a href="https://github.com/pixelinfinito"><img src="https://github.com/pixelinfinito.png" width="60px" alt="Pixel Infinito" /></a>
 | 
				
			||||||
@@ -32,7 +34,6 @@ Special thanks to our biggest sponsors, [CCCareers](https://cccareers.org/) and
 | 
				
			|||||||
<a href="https://github.com/Illyism"><img src="https://github.com/Illyism.png" width="60px" alt="Ilias Ism" /></a>
 | 
					<a href="https://github.com/Illyism"><img src="https://github.com/Illyism.png" width="60px" alt="Ilias Ism" /></a>
 | 
				
			||||||
<a href="https://github.com/urtho"><img src="https://github.com/urtho.png" width="60px" alt="Paweł Pierścionek" /></a>
 | 
					<a href="https://github.com/urtho"><img src="https://github.com/urtho.png" width="60px" alt="Paweł Pierścionek" /></a>
 | 
				
			||||||
<a href="https://github.com/monocursive"><img src="https://github.com/monocursive.png" width="60px" alt="Michael Mazurczak" /></a>
 | 
					<a href="https://github.com/monocursive"><img src="https://github.com/monocursive.png" width="60px" alt="Michael Mazurczak" /></a>
 | 
				
			||||||
<a href="https://github.com/cccareers"><img src="https://github.com/cccareers.png" width="60px" alt="Creating Coding Careers" /></a>
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Organizations
 | 
					## Organizations
 | 
				
			||||||
<a href="https://opencollective.com/coollabsio/organization/0/website"><img src="https://opencollective.com/coollabsio/organization/0/avatar.svg"></a>
 | 
					<a href="https://opencollective.com/coollabsio/organization/0/website"><img src="https://opencollective.com/coollabsio/organization/0/avatar.svg"></a>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -21,14 +21,14 @@ class DeleteService
 | 
				
			|||||||
            foreach ($storages as $storage) {
 | 
					            foreach ($storages as $storage) {
 | 
				
			||||||
                $storagesToDelete->push($storage);
 | 
					                $storagesToDelete->push($storage);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            $application->delete();
 | 
					            $application->forceDelete();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        foreach ($service->databases()->get() as $database) {
 | 
					        foreach ($service->databases()->get() as $database) {
 | 
				
			||||||
            $storages = $database->persistentStorages()->get();
 | 
					            $storages = $database->persistentStorages()->get();
 | 
				
			||||||
            foreach ($storages as $storage) {
 | 
					            foreach ($storages as $storage) {
 | 
				
			||||||
                $storagesToDelete->push($storage);
 | 
					                $storagesToDelete->push($storage);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            $database->delete();
 | 
					            $database->forceDelete();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        foreach ($storagesToDelete as $storage) {
 | 
					        foreach ($storagesToDelete as $storage) {
 | 
				
			||||||
            $commands[] = "docker volume rm -f $storage->name";
 | 
					            $commands[] = "docker volume rm -f $storage->name";
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -55,7 +55,8 @@ class Init extends Command
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    private function restore_coolify_db_backup() {
 | 
					    private function restore_coolify_db_backup()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
            $database = StandalonePostgresql::withTrashed()->find(0);
 | 
					            $database = StandalonePostgresql::withTrashed()->find(0);
 | 
				
			||||||
            if ($database && $database->trashed()) {
 | 
					            if ($database && $database->trashed()) {
 | 
				
			||||||
@@ -73,9 +74,8 @@ class Init extends Command
 | 
				
			|||||||
                        'team_id' => 0,
 | 
					                        'team_id' => 0,
 | 
				
			||||||
                    ]);
 | 
					                    ]);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        } catch(\Throwable $e) {
 | 
					        } catch (\Throwable $e) {
 | 
				
			||||||
            echo "Error in restoring coolify db backup: {$e->getMessage()}\n";
 | 
					            echo "Error in restoring coolify db backup: {$e->getMessage()}\n";
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -138,6 +138,89 @@ class Init extends Command
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
    private function cleanup_stucked_resources()
 | 
					    private function cleanup_stucked_resources()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            $applications = Application::withTrashed()->whereNotNull('deleted_at')->get();
 | 
				
			||||||
 | 
					            foreach ($applications as $application) {
 | 
				
			||||||
 | 
					                echo "Deleting stucked application: {$application->name}\n";
 | 
				
			||||||
 | 
					                $application->forceDelete();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        } catch (\Throwable $e) {
 | 
				
			||||||
 | 
					            echo "Error in cleaning stucked application: {$e->getMessage()}\n";
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            $postgresqls = StandalonePostgresql::withTrashed()->whereNotNull('deleted_at')->get();
 | 
				
			||||||
 | 
					            foreach ($postgresqls as $postgresql) {
 | 
				
			||||||
 | 
					                echo "Deleting stucked postgresql: {$postgresql->name}\n";
 | 
				
			||||||
 | 
					                $postgresql->forceDelete();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        } catch (\Throwable $e) {
 | 
				
			||||||
 | 
					            echo "Error in cleaning stucked postgresql: {$e->getMessage()}\n";
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            $redis = StandaloneRedis::withTrashed()->whereNotNull('deleted_at')->get();
 | 
				
			||||||
 | 
					            foreach ($redis as $redis) {
 | 
				
			||||||
 | 
					                echo "Deleting stucked redis: {$redis->name}\n";
 | 
				
			||||||
 | 
					                $redis->forceDelete();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        } catch (\Throwable $e) {
 | 
				
			||||||
 | 
					            echo "Error in cleaning stucked redis: {$e->getMessage()}\n";
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            $mongodbs = StandaloneMongodb::withTrashed()->whereNotNull('deleted_at')->get();
 | 
				
			||||||
 | 
					            foreach ($mongodbs as $mongodb) {
 | 
				
			||||||
 | 
					                echo "Deleting stucked mongodb: {$mongodb->name}\n";
 | 
				
			||||||
 | 
					                $mongodb->forceDelete();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        } catch (\Throwable $e) {
 | 
				
			||||||
 | 
					            echo "Error in cleaning stucked mongodb: {$e->getMessage()}\n";
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            $mysqls = StandaloneMysql::withTrashed()->whereNotNull('deleted_at')->get();
 | 
				
			||||||
 | 
					            foreach ($mysqls as $mysql) {
 | 
				
			||||||
 | 
					                echo "Deleting stucked mysql: {$mysql->name}\n";
 | 
				
			||||||
 | 
					                $mysql->forceDelete();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        } catch (\Throwable $e) {
 | 
				
			||||||
 | 
					            echo "Error in cleaning stucked mysql: {$e->getMessage()}\n";
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            $mariadbs = StandaloneMariadb::withTrashed()->whereNotNull('deleted_at')->get();
 | 
				
			||||||
 | 
					            foreach ($mariadbs as $mariadb) {
 | 
				
			||||||
 | 
					                echo "Deleting stucked mariadb: {$mariadb->name}\n";
 | 
				
			||||||
 | 
					                $mariadb->forceDelete();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        } catch (\Throwable $e) {
 | 
				
			||||||
 | 
					            echo "Error in cleaning stucked mariadb: {$e->getMessage()}\n";
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            $services = Service::withTrashed()->whereNotNull('deleted_at')->get();
 | 
				
			||||||
 | 
					            foreach ($services as $service) {
 | 
				
			||||||
 | 
					                echo "Deleting stucked service: {$service->name}\n";
 | 
				
			||||||
 | 
					                $service->forceDelete();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        } catch (\Throwable $e) {
 | 
				
			||||||
 | 
					            echo "Error in cleaning stucked service: {$e->getMessage()}\n";
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            $serviceApps = ServiceApplication::withTrashed()->whereNotNull('deleted_at')->get();
 | 
				
			||||||
 | 
					            foreach ($serviceApps as $serviceApp) {
 | 
				
			||||||
 | 
					                echo "Deleting stucked serviceapp: {$serviceApp->name}\n";
 | 
				
			||||||
 | 
					                $serviceApp->forceDelete();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        } catch (\Throwable $e) {
 | 
				
			||||||
 | 
					            echo "Error in cleaning stucked serviceapp: {$e->getMessage()}\n";
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            $serviceDbs = ServiceDatabase::withTrashed()->whereNotNull('deleted_at')->get();
 | 
				
			||||||
 | 
					            foreach ($serviceDbs as $serviceDb) {
 | 
				
			||||||
 | 
					                echo "Deleting stucked serviceapp: {$serviceDb->name}\n";
 | 
				
			||||||
 | 
					                $serviceDb->forceDelete();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        } catch (\Throwable $e) {
 | 
				
			||||||
 | 
					            echo "Error in cleaning stucked serviceapp: {$e->getMessage()}\n";
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Cleanup any resources that are not attached to any environment or destination or server
 | 
					        // Cleanup any resources that are not attached to any environment or destination or server
 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
            $applications = Application::all();
 | 
					            $applications = Application::all();
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -164,11 +164,15 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
 | 
				
			|||||||
            $ips = collect([]);
 | 
					            $ips = collect([]);
 | 
				
			||||||
            if (count($allContainers) > 0) {
 | 
					            if (count($allContainers) > 0) {
 | 
				
			||||||
                $allContainers = $allContainers[0];
 | 
					                $allContainers = $allContainers[0];
 | 
				
			||||||
 | 
					                $allContainers = collect($allContainers)->sort()->values();
 | 
				
			||||||
                foreach ($allContainers as $container) {
 | 
					                foreach ($allContainers as $container) {
 | 
				
			||||||
                    $containerName = data_get($container, 'Name');
 | 
					                    $containerName = data_get($container, 'Name');
 | 
				
			||||||
                    if ($containerName === 'coolify-proxy') {
 | 
					                    if ($containerName === 'coolify-proxy') {
 | 
				
			||||||
                        continue;
 | 
					                        continue;
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
 | 
					                    if (preg_match('/-(\d{12})/',$containerName)) {
 | 
				
			||||||
 | 
					                        continue;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
                    $containerIp = data_get($container, 'IPv4Address');
 | 
					                    $containerIp = data_get($container, 'IPv4Address');
 | 
				
			||||||
                    if ($containerName && $containerIp) {
 | 
					                    if ($containerName && $containerIp) {
 | 
				
			||||||
                        $containerIp = str($containerIp)->before('/');
 | 
					                        $containerIp = str($containerIp)->before('/');
 | 
				
			||||||
@@ -446,8 +450,12 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
 | 
				
			|||||||
        $this->generate_image_names();
 | 
					        $this->generate_image_names();
 | 
				
			||||||
        $this->cleanup_git();
 | 
					        $this->cleanup_git();
 | 
				
			||||||
        $this->application->loadComposeFile(isInit: false);
 | 
					        $this->application->loadComposeFile(isInit: false);
 | 
				
			||||||
        $composeFile = $this->application->parseCompose(pull_request_id: $this->pull_request_id);
 | 
					        if ($this->application->settings->is_raw_compose_deployment_enabled) {
 | 
				
			||||||
        $yaml = Yaml::dump($composeFile->toArray(), 10);
 | 
					            $yaml = $composeFile = $this->application->docker_compose_raw;
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            $composeFile = $this->application->parseCompose(pull_request_id: $this->pull_request_id);
 | 
				
			||||||
 | 
					            $yaml = Yaml::dump($composeFile->toArray(), 10);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        $this->docker_compose_base64 = base64_encode($yaml);
 | 
					        $this->docker_compose_base64 = base64_encode($yaml);
 | 
				
			||||||
        $this->execute_remote_command([
 | 
					        $this->execute_remote_command([
 | 
				
			||||||
            executeInDocker($this->deployment_uuid, "echo '{$this->docker_compose_base64}' | base64 -d > {$this->workdir}{$this->docker_compose_location}"), "hidden" => true
 | 
					            executeInDocker($this->deployment_uuid, "echo '{$this->docker_compose_base64}' | base64 -d > {$this->workdir}{$this->docker_compose_location}"), "hidden" => true
 | 
				
			||||||
@@ -871,11 +879,11 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
 | 
				
			|||||||
    private function nixpacks_build_cmd()
 | 
					    private function nixpacks_build_cmd()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $this->generate_env_variables();
 | 
					        $this->generate_env_variables();
 | 
				
			||||||
        $cacheKey = $this->application->uuid;
 | 
					        // $cacheKey = $this->application->uuid;
 | 
				
			||||||
        if ($this->pull_request_id !== 0) {
 | 
					        // if ($this->pull_request_id !== 0) {
 | 
				
			||||||
            $cacheKey = "{$this->application->uuid}-pr-{$this->pull_request_id}";
 | 
					            // $cacheKey = "{$this->application->uuid}-pr-{$this->pull_request_id}";
 | 
				
			||||||
        }
 | 
					        // }
 | 
				
			||||||
        $nixpacks_command = "nixpacks build --cache-key '{$cacheKey}' -o {$this->workdir} {$this->env_args} --no-error-without-start";
 | 
					        $nixpacks_command = "nixpacks build {$this->env_args} --no-error-without-start";
 | 
				
			||||||
        if ($this->application->build_command) {
 | 
					        if ($this->application->build_command) {
 | 
				
			||||||
            $nixpacks_command .= " --build-cmd \"{$this->application->build_command}\"";
 | 
					            $nixpacks_command .= " --build-cmd \"{$this->application->build_command}\"";
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -885,7 +893,7 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
 | 
				
			|||||||
        if ($this->application->install_command) {
 | 
					        if ($this->application->install_command) {
 | 
				
			||||||
            $nixpacks_command .= " --install-cmd \"{$this->application->install_command}\"";
 | 
					            $nixpacks_command .= " --install-cmd \"{$this->application->install_command}\"";
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        $nixpacks_command .= " {$this->workdir}";
 | 
					        $nixpacks_command .= " -o {$this->workdir} {$this->workdir}";
 | 
				
			||||||
        return $nixpacks_command;
 | 
					        return $nixpacks_command;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1129,7 +1137,8 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
 | 
				
			|||||||
        // Add PORT if not exists, use the first port as default
 | 
					        // Add PORT if not exists, use the first port as default
 | 
				
			||||||
        if ($environment_variables->filter(fn ($env) => Str::of($env)->contains('PORT'))->isEmpty()) {
 | 
					        if ($environment_variables->filter(fn ($env) => Str::of($env)->contains('PORT'))->isEmpty()) {
 | 
				
			||||||
            $environment_variables->push("PORT={$ports[0]}");
 | 
					            $environment_variables->push("PORT={$ports[0]}");
 | 
				
			||||||
        }  if ($environment_variables->filter(fn ($env) => Str::of($env)->contains('SOURCE_COMMIT'))->isEmpty()) {
 | 
					        }
 | 
				
			||||||
 | 
					        if ($environment_variables->filter(fn ($env) => Str::of($env)->contains('SOURCE_COMMIT'))->isEmpty()) {
 | 
				
			||||||
            if (!is_null($this->commit)) {
 | 
					            if (!is_null($this->commit)) {
 | 
				
			||||||
                $environment_variables->push("SOURCE_COMMIT={$this->commit}");
 | 
					                $environment_variables->push("SOURCE_COMMIT={$this->commit}");
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@@ -1192,6 +1201,9 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
 | 
				
			|||||||
        if ($this->application->settings->is_static || $this->application->build_pack === 'static') {
 | 
					        if ($this->application->settings->is_static || $this->application->build_pack === 'static') {
 | 
				
			||||||
            if ($this->application->static_image) {
 | 
					            if ($this->application->static_image) {
 | 
				
			||||||
                $this->pull_latest_image($this->application->static_image);
 | 
					                $this->pull_latest_image($this->application->static_image);
 | 
				
			||||||
 | 
					                $this->execute_remote_command(
 | 
				
			||||||
 | 
					                    ["echo -n 'Continue with the building process.'"],
 | 
				
			||||||
 | 
					                );
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            if ($this->application->build_pack === 'static') {
 | 
					            if ($this->application->build_pack === 'static') {
 | 
				
			||||||
                $dockerfile = base64_encode("FROM {$this->application->static_image}
 | 
					                $dockerfile = base64_encode("FROM {$this->application->static_image}
 | 
				
			||||||
@@ -1218,9 +1230,23 @@ COPY ./nginx.conf /etc/nginx/conf.d/default.conf");
 | 
				
			|||||||
                }
 | 
					                }
 | 
				
			||||||
            }");
 | 
					            }");
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
                $this->execute_remote_command([
 | 
					                if ($this->application->build_pack === 'nixpacks') {
 | 
				
			||||||
                    executeInDocker($this->deployment_uuid, "docker build $this->buildTarget $this->addHosts --network host -f {$this->workdir}{$this->dockerfile_location} {$this->build_args} --progress plain -t $this->build_image_name {$this->workdir}"), "hidden" => true
 | 
					                    $this->execute_remote_command(
 | 
				
			||||||
                ]);
 | 
					                        [
 | 
				
			||||||
 | 
					                            executeInDocker($this->deployment_uuid, "cp {$this->workdir}/Dockerfile {$this->workdir}/.nixpacks/Dockerfile")
 | 
				
			||||||
 | 
					                        ],
 | 
				
			||||||
 | 
					                    );
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                if ($this->force_rebuild) {
 | 
				
			||||||
 | 
					                    $this->execute_remote_command([
 | 
				
			||||||
 | 
					                        executeInDocker($this->deployment_uuid, "docker build --no-cache $this->buildTarget $this->addHosts --network host -f {$this->workdir}{$this->dockerfile_location} {$this->build_args} --progress plain -t $this->build_image_name {$this->workdir}"), "hidden" => true
 | 
				
			||||||
 | 
					                    ]);
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    $this->execute_remote_command([
 | 
				
			||||||
 | 
					                        executeInDocker($this->deployment_uuid, "docker build $this->buildTarget $this->addHosts --network host -f {$this->workdir}{$this->dockerfile_location} {$this->build_args} --progress plain -t $this->build_image_name {$this->workdir}"), "hidden" => true
 | 
				
			||||||
 | 
					                    ]);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                // }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                $dockerfile = base64_encode("FROM {$this->application->static_image}
 | 
					                $dockerfile = base64_encode("FROM {$this->application->static_image}
 | 
				
			||||||
WORKDIR /usr/share/nginx/html/
 | 
					WORKDIR /usr/share/nginx/html/
 | 
				
			||||||
@@ -1263,9 +1289,23 @@ COPY ./nginx.conf /etc/nginx/conf.d/default.conf");
 | 
				
			|||||||
                    executeInDocker($this->deployment_uuid, "docker build --pull $this->buildTarget $this->addHosts --network host -f {$this->workdir}{$this->dockerfile_location} {$this->build_args} --progress plain -t $this->production_image_name {$this->workdir}"), "hidden" => true
 | 
					                    executeInDocker($this->deployment_uuid, "docker build --pull $this->buildTarget $this->addHosts --network host -f {$this->workdir}{$this->dockerfile_location} {$this->build_args} --progress plain -t $this->production_image_name {$this->workdir}"), "hidden" => true
 | 
				
			||||||
                ]);
 | 
					                ]);
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
                $this->execute_remote_command([
 | 
					                if ($this->application->build_pack === 'nixpacks') {
 | 
				
			||||||
                    executeInDocker($this->deployment_uuid, "docker build $this->buildTarget $this->addHosts --network host -f {$this->workdir}{$this->dockerfile_location} {$this->build_args} --progress plain -t $this->production_image_name {$this->workdir}"), "hidden" => true
 | 
					                    $this->execute_remote_command(
 | 
				
			||||||
                ]);
 | 
					                        [
 | 
				
			||||||
 | 
					                            executeInDocker($this->deployment_uuid, "cp {$this->workdir}/Dockerfile {$this->workdir}/.nixpacks/Dockerfile")
 | 
				
			||||||
 | 
					                        ],
 | 
				
			||||||
 | 
					                    );
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if ($this->force_rebuild) {
 | 
				
			||||||
 | 
					                    $this->execute_remote_command([
 | 
				
			||||||
 | 
					                        executeInDocker($this->deployment_uuid, "docker build --no-cache $this->buildTarget $this->addHosts --network host -f {$this->workdir}{$this->dockerfile_location} {$this->build_args} --progress plain -t $this->production_image_name {$this->workdir}"), "hidden" => true
 | 
				
			||||||
 | 
					                    ]);
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    $this->execute_remote_command([
 | 
				
			||||||
 | 
					                        executeInDocker($this->deployment_uuid, "docker build $this->buildTarget $this->addHosts --network host -f {$this->workdir}{$this->dockerfile_location} {$this->build_args} --progress plain -t $this->production_image_name {$this->workdir}"), "hidden" => true
 | 
				
			||||||
 | 
					                    ]);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        $this->execute_remote_command([
 | 
					        $this->execute_remote_command([
 | 
				
			||||||
@@ -1291,6 +1331,9 @@ COPY ./nginx.conf /etc/nginx/conf.d/default.conf");
 | 
				
			|||||||
            });
 | 
					            });
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            $this->application_deployment_queue->addLogEntry("New container is not healthy, rolling back to the old container.");
 | 
					            $this->application_deployment_queue->addLogEntry("New container is not healthy, rolling back to the old container.");
 | 
				
			||||||
 | 
					            $this->application_deployment_queue->update([
 | 
				
			||||||
 | 
					                'status' => ApplicationDeploymentStatus::FAILED->value,
 | 
				
			||||||
 | 
					            ]);
 | 
				
			||||||
            $this->execute_remote_command(
 | 
					            $this->execute_remote_command(
 | 
				
			||||||
                [executeInDocker($this->deployment_uuid, "docker rm -f $this->container_name >/dev/null 2>&1"), "hidden" => true, "ignore_errors" => true],
 | 
					                [executeInDocker($this->deployment_uuid, "docker rm -f $this->container_name >/dev/null 2>&1"), "hidden" => true, "ignore_errors" => true],
 | 
				
			||||||
            );
 | 
					            );
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -66,6 +66,7 @@ class General extends Component
 | 
				
			|||||||
        'application.settings.is_static' => 'boolean|required',
 | 
					        'application.settings.is_static' => 'boolean|required',
 | 
				
			||||||
        'application.docker_compose_custom_start_command' => 'nullable',
 | 
					        'application.docker_compose_custom_start_command' => 'nullable',
 | 
				
			||||||
        'application.docker_compose_custom_build_command' => 'nullable',
 | 
					        'application.docker_compose_custom_build_command' => 'nullable',
 | 
				
			||||||
 | 
					        'application.settings.is_raw_compose_deployment_enabled' => 'boolean|required',
 | 
				
			||||||
    ];
 | 
					    ];
 | 
				
			||||||
    protected $validationAttributes = [
 | 
					    protected $validationAttributes = [
 | 
				
			||||||
        'application.name' => 'name',
 | 
					        'application.name' => 'name',
 | 
				
			||||||
@@ -98,6 +99,7 @@ class General extends Component
 | 
				
			|||||||
        'application.settings.is_static' => 'Is static',
 | 
					        'application.settings.is_static' => 'Is static',
 | 
				
			||||||
        'application.docker_compose_custom_start_command' => 'Docker compose custom start command',
 | 
					        'application.docker_compose_custom_start_command' => 'Docker compose custom start command',
 | 
				
			||||||
        'application.docker_compose_custom_build_command' => 'Docker compose custom build command',
 | 
					        'application.docker_compose_custom_build_command' => 'Docker compose custom build command',
 | 
				
			||||||
 | 
					        'application.settings.is_raw_compose_deployment_enabled' => 'Is raw compose deployment enabled',
 | 
				
			||||||
    ];
 | 
					    ];
 | 
				
			||||||
    public function mount()
 | 
					    public function mount()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
@@ -114,6 +116,11 @@ class General extends Component
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
        $this->isConfigurationChanged = $this->application->isConfigurationChanged();
 | 
					        $this->isConfigurationChanged = $this->application->isConfigurationChanged();
 | 
				
			||||||
        $this->customLabels = $this->application->parseContainerLabels();
 | 
					        $this->customLabels = $this->application->parseContainerLabels();
 | 
				
			||||||
 | 
					        if (!$this->customLabels && $this->application->destination->server->proxyType() === 'TRAEFIK_V2') {
 | 
				
			||||||
 | 
					            $this->customLabels = str(implode(",", generateLabelsApplication($this->application)))->replace(',', "\n");
 | 
				
			||||||
 | 
					            $this->application->custom_labels = base64_encode($this->customLabels);
 | 
				
			||||||
 | 
					            $this->application->save();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        $this->initialDockerComposeLocation = $this->application->docker_compose_location;
 | 
					        $this->initialDockerComposeLocation = $this->application->docker_compose_location;
 | 
				
			||||||
        $this->checkLabelUpdates();
 | 
					        $this->checkLabelUpdates();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -199,7 +206,12 @@ class General extends Component
 | 
				
			|||||||
    public function submit($showToaster = true)
 | 
					    public function submit($showToaster = true)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
            ray($this->initialDockerComposeLocation, $this->application->docker_compose_location);
 | 
					            if (!$this->customLabels && $this->application->destination->server->proxyType() === 'TRAEFIK_V2') {
 | 
				
			||||||
 | 
					                $this->customLabels = str(implode(",", generateLabelsApplication($this->application)))->replace(',', "\n");
 | 
				
			||||||
 | 
					                $this->application->custom_labels = base64_encode($this->customLabels);
 | 
				
			||||||
 | 
					                $this->application->save();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if ($this->application->build_pack === 'dockercompose' && $this->initialDockerComposeLocation !== $this->application->docker_compose_location) {
 | 
					            if ($this->application->build_pack === 'dockercompose' && $this->initialDockerComposeLocation !== $this->application->docker_compose_location) {
 | 
				
			||||||
                $this->loadComposeFile();
 | 
					                $this->loadComposeFile();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@@ -207,6 +219,7 @@ class General extends Component
 | 
				
			|||||||
            if ($this->ports_exposes !== $this->application->ports_exposes) {
 | 
					            if ($this->ports_exposes !== $this->application->ports_exposes) {
 | 
				
			||||||
                $this->resetDefaultLabels(false);
 | 
					                $this->resetDefaultLabels(false);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (data_get($this->application, 'build_pack') === 'dockerimage') {
 | 
					            if (data_get($this->application, 'build_pack') === 'dockerimage') {
 | 
				
			||||||
                $this->validate([
 | 
					                $this->validate([
 | 
				
			||||||
                    'application.docker_registry_image_name' => 'required',
 | 
					                    'application.docker_registry_image_name' => 'required',
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -430,7 +430,7 @@ class Application extends BaseModel
 | 
				
			|||||||
    public function isConfigurationChanged($save = false)
 | 
					    public function isConfigurationChanged($save = false)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $newConfigHash = $this->fqdn . $this->git_repository . $this->git_branch . $this->git_commit_sha . $this->build_pack . $this->static_image . $this->install_command  . $this->build_command . $this->start_command . $this->port_exposes . $this->port_mappings . $this->base_directory . $this->publish_directory . $this->health_check_path  . $this->health_check_port . $this->health_check_host . $this->health_check_method . $this->health_check_return_code . $this->health_check_scheme . $this->health_check_response_text . $this->health_check_interval . $this->health_check_timeout . $this->health_check_retries . $this->health_check_start_period . $this->health_check_enabled . $this->limits_memory  . $this->limits_swap . $this->limits_swappiness . $this->limits_reservation . $this->limits_cpus . $this->limits_cpuset . $this->limits_cpu_shares . $this->dockerfile . $this->dockerfile_location . $this->custom_labels;
 | 
					        $newConfigHash = $this->fqdn . $this->git_repository . $this->git_branch . $this->git_commit_sha . $this->build_pack . $this->static_image . $this->install_command  . $this->build_command . $this->start_command . $this->port_exposes . $this->port_mappings . $this->base_directory . $this->publish_directory . $this->health_check_path  . $this->health_check_port . $this->health_check_host . $this->health_check_method . $this->health_check_return_code . $this->health_check_scheme . $this->health_check_response_text . $this->health_check_interval . $this->health_check_timeout . $this->health_check_retries . $this->health_check_start_period . $this->health_check_enabled . $this->limits_memory  . $this->limits_swap . $this->limits_swappiness . $this->limits_reservation . $this->limits_cpus . $this->limits_cpuset . $this->limits_cpu_shares . $this->dockerfile . $this->dockerfile_location . $this->custom_labels;
 | 
				
			||||||
        if ($this->pull_request_id === 0) {
 | 
					        if ($this->pull_request_id === 0 || $this->pull_request_id === null) {
 | 
				
			||||||
            $newConfigHash .= json_encode($this->environment_variables->all());
 | 
					            $newConfigHash .= json_encode($this->environment_variables->all());
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            $newConfigHash .= json_encode($this->environment_variables_preview->all());
 | 
					            $newConfigHash .= json_encode($this->environment_variables_preview->all());
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -41,11 +41,11 @@ function queue_application_deployment(int $application_id, string $deployment_uu
 | 
				
			|||||||
        dispatch(new ApplicationDeploymentNewJob(
 | 
					        dispatch(new ApplicationDeploymentNewJob(
 | 
				
			||||||
            deployment: $deployment,
 | 
					            deployment: $deployment,
 | 
				
			||||||
            application: Application::find($application_id)
 | 
					            application: Application::find($application_id)
 | 
				
			||||||
        ))->onConnection('long-running')->onQueue('long-running');
 | 
					        ));
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        dispatch(new ApplicationDeploymentJob(
 | 
					        dispatch(new ApplicationDeploymentJob(
 | 
				
			||||||
            application_deployment_queue_id: $deployment->id,
 | 
					            application_deployment_queue_id: $deployment->id,
 | 
				
			||||||
        ))->onConnection('long-running')->onQueue('long-running');
 | 
					        ));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -57,11 +57,11 @@ function queue_next_deployment(Application $application, bool $isNew = false)
 | 
				
			|||||||
            dispatch(new ApplicationDeploymentNewJob(
 | 
					            dispatch(new ApplicationDeploymentNewJob(
 | 
				
			||||||
                deployment: $next_found,
 | 
					                deployment: $next_found,
 | 
				
			||||||
                application: $application
 | 
					                application: $application
 | 
				
			||||||
            ))->onConnection('long-running')->onQueue('long-running');
 | 
					            ));
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            dispatch(new ApplicationDeploymentJob(
 | 
					            dispatch(new ApplicationDeploymentJob(
 | 
				
			||||||
                application_deployment_queue_id: $next_found->id,
 | 
					                application_deployment_queue_id: $next_found->id,
 | 
				
			||||||
            ))->onConnection('long-running')->onQueue('long-running');
 | 
					            ));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1035,7 +1035,9 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
 | 
				
			|||||||
                }
 | 
					                }
 | 
				
			||||||
                data_set($service, 'labels', $serviceLabels->toArray());
 | 
					                data_set($service, 'labels', $serviceLabels->toArray());
 | 
				
			||||||
                data_forget($service, 'is_database');
 | 
					                data_forget($service, 'is_database');
 | 
				
			||||||
                data_set($service, 'restart', RESTART_MODE);
 | 
					                if (!data_get($service, 'restart')) {
 | 
				
			||||||
 | 
					                    data_set($service, 'restart', RESTART_MODE);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
                data_set($service, 'container_name', $containerName);
 | 
					                data_set($service, 'container_name', $containerName);
 | 
				
			||||||
                data_forget($service, 'volumes.*.content');
 | 
					                data_forget($service, 'volumes.*.content');
 | 
				
			||||||
                data_forget($service, 'volumes.*.isDirectory');
 | 
					                data_forget($service, 'volumes.*.isDirectory');
 | 
				
			||||||
@@ -1399,6 +1401,11 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
 | 
				
			|||||||
                            $key = $value;
 | 
					                            $key = $value;
 | 
				
			||||||
                            $defaultValue = null;
 | 
					                            $defaultValue = null;
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
 | 
					                        $foundEnv = EnvironmentVariable::where([
 | 
				
			||||||
 | 
					                            'key' => $key,
 | 
				
			||||||
 | 
					                            'application_id' => $resource->id,
 | 
				
			||||||
 | 
					                            'is_preview' => false,
 | 
				
			||||||
 | 
					                        ])->first();
 | 
				
			||||||
                        if ($foundEnv) {
 | 
					                        if ($foundEnv) {
 | 
				
			||||||
                            $defaultValue = data_get($foundEnv, 'value');
 | 
					                            $defaultValue = data_get($foundEnv, 'value');
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
@@ -1468,7 +1475,9 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
            data_set($service, 'labels', $serviceLabels->toArray());
 | 
					            data_set($service, 'labels', $serviceLabels->toArray());
 | 
				
			||||||
            data_forget($service, 'is_database');
 | 
					            data_forget($service, 'is_database');
 | 
				
			||||||
            data_set($service, 'restart', RESTART_MODE);
 | 
					            if (!data_get($service, 'restart')) {
 | 
				
			||||||
 | 
					                data_set($service, 'restart', RESTART_MODE);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
            data_set($service, 'container_name', $containerName);
 | 
					            data_set($service, 'container_name', $containerName);
 | 
				
			||||||
            data_forget($service, 'volumes.*.content');
 | 
					            data_forget($service, 'volumes.*.content');
 | 
				
			||||||
            data_forget($service, 'volumes.*.isDirectory');
 | 
					            data_forget($service, 'volumes.*.isDirectory');
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -184,19 +184,8 @@ return [
 | 
				
			|||||||
            'connection' => 'redis',
 | 
					            'connection' => 'redis',
 | 
				
			||||||
            'queue' => ['default'],
 | 
					            'queue' => ['default'],
 | 
				
			||||||
            'balance' => 'auto',
 | 
					            'balance' => 'auto',
 | 
				
			||||||
            'autoScalingStrategy' => 'time',
 | 
					            // 'autoScalingStrategy' => 'time',
 | 
				
			||||||
            'maxProcesses' => 1,
 | 
					            // 'maxProcesses' => 1,
 | 
				
			||||||
            'maxTime' => 0,
 | 
					 | 
				
			||||||
            'maxJobs' => 0,
 | 
					 | 
				
			||||||
            'memory' => 128,
 | 
					 | 
				
			||||||
            'tries' => 1,
 | 
					 | 
				
			||||||
            'timeout' => 300,
 | 
					 | 
				
			||||||
            'nice' => 0,
 | 
					 | 
				
			||||||
        ],
 | 
					 | 
				
			||||||
        'long-running' => [
 | 
					 | 
				
			||||||
            'connection' => 'redis',
 | 
					 | 
				
			||||||
            'queue' => ['long-running'],
 | 
					 | 
				
			||||||
            'balance' => 'auto',
 | 
					 | 
				
			||||||
            'maxTime' => 0,
 | 
					            'maxTime' => 0,
 | 
				
			||||||
            'maxJobs' => 0,
 | 
					            'maxJobs' => 0,
 | 
				
			||||||
            'memory' => 128,
 | 
					            'memory' => 128,
 | 
				
			||||||
@@ -209,27 +198,15 @@ return [
 | 
				
			|||||||
    'environments' => [
 | 
					    'environments' => [
 | 
				
			||||||
        'production' => [
 | 
					        'production' => [
 | 
				
			||||||
            's6' => [
 | 
					            's6' => [
 | 
				
			||||||
                'autoScalingStrategy' => 'size',
 | 
					 | 
				
			||||||
                'maxProcesses' => env('HORIZON_MAX_PROCESSES', 2),
 | 
					 | 
				
			||||||
                'balanceMaxShift' => env('HORIZON_BALANCE_MAX_SHIFT', 1),
 | 
					 | 
				
			||||||
                'balanceCooldown' => env('HORIZON_BALANCE_COOLDOWN', 1),
 | 
					 | 
				
			||||||
            ],
 | 
					 | 
				
			||||||
            'long-running' => [
 | 
					 | 
				
			||||||
                'autoScalingStrategy' => 'size',
 | 
					                'autoScalingStrategy' => 'size',
 | 
				
			||||||
                'maxProcesses' => env('HORIZON_MAX_PROCESSES', 6),
 | 
					                'maxProcesses' => env('HORIZON_MAX_PROCESSES', 6),
 | 
				
			||||||
                'balanceMaxShift' => env('HORIZON_BALANCE_MAX_SHIFT', 1),
 | 
					                'balanceMaxShift' => env('HORIZON_BALANCE_MAX_SHIFT', 1),
 | 
				
			||||||
                'balanceCooldown' => env('HORIZON_BALANCE_COOLDOWN', 1),
 | 
					                'balanceCooldown' => env('HORIZON_BALANCE_COOLDOWN', 1),
 | 
				
			||||||
            ],
 | 
					            ],
 | 
				
			||||||
        ],
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
        'local' => [
 | 
					        'local' => [
 | 
				
			||||||
            's6' => [
 | 
					            's6' => [
 | 
				
			||||||
                'autoScalingStrategy' => 'size',
 | 
					 | 
				
			||||||
                'maxProcesses' => env('HORIZON_MAX_PROCESSES', 2),
 | 
					 | 
				
			||||||
                'balanceMaxShift' => env('HORIZON_BALANCE_MAX_SHIFT', 1),
 | 
					 | 
				
			||||||
                'balanceCooldown' => env('HORIZON_BALANCE_COOLDOWN', 1),
 | 
					 | 
				
			||||||
            ],
 | 
					 | 
				
			||||||
            'long-running' => [
 | 
					 | 
				
			||||||
                'autoScalingStrategy' => 'size',
 | 
					                'autoScalingStrategy' => 'size',
 | 
				
			||||||
                'maxProcesses' => env('HORIZON_MAX_PROCESSES', 6),
 | 
					                'maxProcesses' => env('HORIZON_MAX_PROCESSES', 6),
 | 
				
			||||||
                'balanceMaxShift' => env('HORIZON_BALANCE_MAX_SHIFT', 1),
 | 
					                'balanceMaxShift' => env('HORIZON_BALANCE_MAX_SHIFT', 1),
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -33,14 +33,6 @@ return [
 | 
				
			|||||||
        'sync' => [
 | 
					        'sync' => [
 | 
				
			||||||
            'driver' => 'sync',
 | 
					            'driver' => 'sync',
 | 
				
			||||||
        ],
 | 
					        ],
 | 
				
			||||||
        'long-running' => [
 | 
					 | 
				
			||||||
            'driver' => 'redis',
 | 
					 | 
				
			||||||
            'connection' => 'default',
 | 
					 | 
				
			||||||
            'queue' => 'long-running',
 | 
					 | 
				
			||||||
            'retry_after' => 3600,
 | 
					 | 
				
			||||||
            'block_for' => null,
 | 
					 | 
				
			||||||
            'after_commit' => true,
 | 
					 | 
				
			||||||
        ],
 | 
					 | 
				
			||||||
        'database' => [
 | 
					        'database' => [
 | 
				
			||||||
            'driver' => 'database',
 | 
					            'driver' => 'database',
 | 
				
			||||||
            'table' => 'jobs',
 | 
					            'table' => 'jobs',
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,7 +7,7 @@ return [
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    // The release version of your application
 | 
					    // The release version of your application
 | 
				
			||||||
    // Example with dynamic git hash: trim(exec('git --git-dir ' . base_path('.git') . ' log --pretty="%h" -n1 HEAD'))
 | 
					    // Example with dynamic git hash: trim(exec('git --git-dir ' . base_path('.git') . ' log --pretty="%h" -n1 HEAD'))
 | 
				
			||||||
    'release' => '4.0.0-beta.175',
 | 
					    'release' => '4.0.0-beta.182',
 | 
				
			||||||
    // When left empty or `null` the Laravel environment will be used
 | 
					    // When left empty or `null` the Laravel environment will be used
 | 
				
			||||||
    'environment' => config('app.env'),
 | 
					    'environment' => config('app.env'),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,3 +1,3 @@
 | 
				
			|||||||
<?php
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
return '4.0.0-beta.175';
 | 
					return '4.0.0-beta.182';
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -0,0 +1,28 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use Illuminate\Database\Migrations\Migration;
 | 
				
			||||||
 | 
					use Illuminate\Database\Schema\Blueprint;
 | 
				
			||||||
 | 
					use Illuminate\Support\Facades\Schema;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					return new class extends Migration
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Run the migrations.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function up(): void
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        Schema::table('application_settings', function (Blueprint $table) {
 | 
				
			||||||
 | 
					            $table->boolean('is_raw_compose_deployment_enabled')->default(false);
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Reverse the migrations.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function down(): void
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        Schema::table('application_settings', function (Blueprint $table) {
 | 
				
			||||||
 | 
					            $table->dropColumn('is_raw_compose_deployment_enabled');
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
@@ -8,9 +8,9 @@ ARG DOCKER_COMPOSE_VERSION=2.21.0
 | 
				
			|||||||
# https://github.com/docker/buildx/releases
 | 
					# https://github.com/docker/buildx/releases
 | 
				
			||||||
ARG DOCKER_BUILDX_VERSION=0.11.2
 | 
					ARG DOCKER_BUILDX_VERSION=0.11.2
 | 
				
			||||||
# https://github.com/buildpacks/pack/releases
 | 
					# https://github.com/buildpacks/pack/releases
 | 
				
			||||||
ARG PACK_VERSION=0.31.0
 | 
					ARG PACK_VERSION=0.32.1
 | 
				
			||||||
# https://github.com/railwayapp/nixpacks/releases
 | 
					# https://github.com/railwayapp/nixpacks/releases
 | 
				
			||||||
ARG NIXPACKS_VERSION=1.18.0
 | 
					ARG NIXPACKS_VERSION=1.20.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
USER root
 | 
					USER root
 | 
				
			||||||
WORKDIR /artifacts
 | 
					WORKDIR /artifacts
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,12 +0,0 @@
 | 
				
			|||||||
@isset($title, $action)
 | 
					 | 
				
			||||||
    <div tabindex="0" x-data="{ open: false }"
 | 
					 | 
				
			||||||
        class="transition border rounded cursor-pointer collapse collapse-arrow border-coolgray-200"
 | 
					 | 
				
			||||||
        :class="open ? 'collapse-open' : 'collapse-close'">
 | 
					 | 
				
			||||||
        <div class="flex flex-col justify-center text-sm select-text collapse-title" x-on:click="open = !open">
 | 
					 | 
				
			||||||
            {{ $title }}
 | 
					 | 
				
			||||||
        </div>
 | 
					 | 
				
			||||||
        <div class="collapse-content">
 | 
					 | 
				
			||||||
            {{ $action }}
 | 
					 | 
				
			||||||
        </div>
 | 
					 | 
				
			||||||
    </div>
 | 
					 | 
				
			||||||
@endisset
 | 
					 | 
				
			||||||
@@ -5,9 +5,10 @@
 | 
				
			|||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
        <div>Advanced configuration for your application.</div>
 | 
					        <div>Advanced configuration for your application.</div>
 | 
				
			||||||
        <div class="flex flex-col w-full pt-4">
 | 
					        <div class="flex flex-col w-full pt-4">
 | 
				
			||||||
 | 
					            @if (!$application->settings->is_raw_compose_deployment_enabled)
 | 
				
			||||||
            <x-forms.checkbox helper="Drain logs to your configured log drain endpoint in your Server settings."
 | 
					                <x-forms.checkbox helper="Drain logs to your configured log drain endpoint in your Server settings."
 | 
				
			||||||
                instantSave id="application.settings.is_log_drain_enabled" label="Drain Logs" />
 | 
					                    instantSave id="application.settings.is_log_drain_enabled" label="Drain Logs" />
 | 
				
			||||||
 | 
					            @endif
 | 
				
			||||||
            <x-forms.checkbox
 | 
					            <x-forms.checkbox
 | 
				
			||||||
                helper="Your application will be available only on https if your domain starts with https://..."
 | 
					                helper="Your application will be available only on https if your domain starts with https://..."
 | 
				
			||||||
                instantSave id="application.settings.is_force_https_enabled" label="Force Https" />
 | 
					                instantSave id="application.settings.is_force_https_enabled" label="Force Https" />
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -48,7 +48,10 @@
 | 
				
			|||||||
                        </div>
 | 
					                        </div>
 | 
				
			||||||
                    @endif
 | 
					                    @endif
 | 
				
			||||||
                    @if ($application->build_pack === 'dockercompose')
 | 
					                    @if ($application->build_pack === 'dockercompose')
 | 
				
			||||||
                        @if (count($parsedServices) > 0)
 | 
					                        <x-forms.checkbox instantSave id="application.settings.is_raw_compose_deployment_enabled"
 | 
				
			||||||
 | 
					                            label="Raw Compose Deployment"
 | 
				
			||||||
 | 
					                            helper="WARNING: Advanced use cases only. Your docker compose file will be deployed as-is. Nothing is modified by Coolify. You need to configure the proxy parts. More info in the <a href='https://coolify.io/docs/docker-compose'>documentation.</a>" />
 | 
				
			||||||
 | 
					                        @if (count($parsedServices) > 0 && !$application->settings->is_raw_compose_deployment_enabled)
 | 
				
			||||||
                            @foreach (data_get($parsedServices, 'services') as $serviceName => $service)
 | 
					                            @foreach (data_get($parsedServices, 'services') as $serviceName => $service)
 | 
				
			||||||
                                @if (!isDatabaseImage(data_get($service, 'image')))
 | 
					                                @if (!isDatabaseImage(data_get($service, 'image')))
 | 
				
			||||||
                                    <div class="flex items-end gap-2">
 | 
					                                    <div class="flex items-end gap-2">
 | 
				
			||||||
@@ -184,8 +187,13 @@
 | 
				
			|||||||
            @endif
 | 
					            @endif
 | 
				
			||||||
            @if ($application->build_pack === 'dockercompose')
 | 
					            @if ($application->build_pack === 'dockercompose')
 | 
				
			||||||
                <x-forms.button wire:click="loadComposeFile">Reload Compose File</x-forms.button>
 | 
					                <x-forms.button wire:click="loadComposeFile">Reload Compose File</x-forms.button>
 | 
				
			||||||
                <x-forms.textarea rows="10" readonly id="application.docker_compose"
 | 
					                @if ($application->settings->is_raw_compose_deployment_enabled)
 | 
				
			||||||
                    label="Docker Compose Content" helper="You need to modify the docker compose file." />
 | 
					                    <x-forms.textarea rows="10" readonly id="application.docker_compose_raw"
 | 
				
			||||||
 | 
					                        label="Docker Compose Content (applicationId: {{$application->id}})" helper="You need to modify the docker compose file." />
 | 
				
			||||||
 | 
					                @else
 | 
				
			||||||
 | 
					                    <x-forms.textarea rows="10" readonly id="application.docker_compose"
 | 
				
			||||||
 | 
					                        label="Docker Compose Content" helper="You need to modify the docker compose file." />
 | 
				
			||||||
 | 
					                @endif
 | 
				
			||||||
                {{-- <x-forms.textarea rows="10" readonly id="application.docker_compose_pr"
 | 
					                {{-- <x-forms.textarea rows="10" readonly id="application.docker_compose_pr"
 | 
				
			||||||
                    label="Docker PR Compose Content" helper="You need to modify the docker compose file." /> --}}
 | 
					                    label="Docker PR Compose Content" helper="You need to modify the docker compose file." /> --}}
 | 
				
			||||||
            @endif
 | 
					            @endif
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,8 +1,10 @@
 | 
				
			|||||||
<x-collapsible>
 | 
					<div tabindex="0" x-data="{ open: false }"
 | 
				
			||||||
    <x-slot:title>
 | 
					    class="transition border rounded cursor-pointer collapse collapse-arrow border-coolgray-200"
 | 
				
			||||||
 | 
					    :class="open ? 'collapse-open' : 'collapse-close'">
 | 
				
			||||||
 | 
					    <div class="flex flex-col justify-center text-sm select-text collapse-title" x-on:click="open = !open">
 | 
				
			||||||
        <div>{{ $workdir }}{{ $fs_path }} -> {{ $fileStorage->mount_path }}</div>
 | 
					        <div>{{ $workdir }}{{ $fs_path }} -> {{ $fileStorage->mount_path }}</div>
 | 
				
			||||||
    </x-slot:title>
 | 
					    </div>
 | 
				
			||||||
    <x-slot:action>
 | 
					    <div class="collapse-content">
 | 
				
			||||||
        <form wire:submit='submit' class="flex flex-col gap-2">
 | 
					        <form wire:submit='submit' class="flex flex-col gap-2">
 | 
				
			||||||
            <div class="w-64">
 | 
					            <div class="w-64">
 | 
				
			||||||
                <x-forms.checkbox instantSave label="Is directory?" id="fileStorage.is_directory"></x-forms.checkbox>
 | 
					                <x-forms.checkbox instantSave label="Is directory?" id="fileStorage.is_directory"></x-forms.checkbox>
 | 
				
			||||||
@@ -21,5 +23,5 @@
 | 
				
			|||||||
            @endif
 | 
					            @endif
 | 
				
			||||||
            {{-- @endif --}}
 | 
					            {{-- @endif --}}
 | 
				
			||||||
        </form>
 | 
					        </form>
 | 
				
			||||||
    </x-slot:action>
 | 
					    </div>
 | 
				
			||||||
</x-collapsible>
 | 
					</div>
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										15
									
								
								templates/compose/stirling-pdf.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								templates/compose/stirling-pdf.yaml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,15 @@
 | 
				
			|||||||
 | 
					# documentation: https://github.com/Stirling-Tools/Stirling-PDF
 | 
				
			||||||
 | 
					# slogan: Stirling is a powerful web based PDF manipulation tool
 | 
				
			||||||
 | 
					# tags: pdf, manipulation, web, tool
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					services:
 | 
				
			||||||
 | 
					  stirling-pdf:
 | 
				
			||||||
 | 
					    image: frooodle/s-pdf:latest
 | 
				
			||||||
 | 
					    volumes:
 | 
				
			||||||
 | 
					      - stirling-training-data:/usr/share/tesseract-ocr/5/tessdata
 | 
				
			||||||
 | 
					      - stirling-configs:/configs
 | 
				
			||||||
 | 
					      - stirling-custom-files:/customFiles/
 | 
				
			||||||
 | 
					      - stirling-logs:/logs/
 | 
				
			||||||
 | 
					    environment:
 | 
				
			||||||
 | 
					      - SERVICE_FQDN_SPDF
 | 
				
			||||||
 | 
					      - DOCKER_ENABLE_SECURITY=false
 | 
				
			||||||
@@ -469,6 +469,17 @@
 | 
				
			|||||||
            "internet"
 | 
					            "internet"
 | 
				
			||||||
        ]
 | 
					        ]
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    "stirling-pdf": {
 | 
				
			||||||
 | 
					        "documentation": "https:\/\/github.com\/Stirling-Tools\/Stirling-PDF",
 | 
				
			||||||
 | 
					        "slogan": "Stirling is a powerful web based PDF manipulation tool",
 | 
				
			||||||
 | 
					        "compose": "c2VydmljZXM6CiAgc3RpcmxpbmctcGRmOgogICAgaW1hZ2U6ICdmcm9vb2RsZS9zLXBkZjpsYXRlc3QnCiAgICB2b2x1bWVzOgogICAgICAtICdzdGlybGluZy10cmFpbmluZy1kYXRhOi91c3Ivc2hhcmUvdGVzc2VyYWN0LW9jci81L3Rlc3NkYXRhJwogICAgICAtICdzdGlybGluZy1jb25maWdzOi9jb25maWdzJwogICAgICAtICdzdGlybGluZy1jdXN0b20tZmlsZXM6L2N1c3RvbUZpbGVzLycKICAgICAgLSAnc3RpcmxpbmctbG9nczovbG9ncy8nCiAgICBlbnZpcm9ubWVudDoKICAgICAgLSBTRVJWSUNFX0ZRRE5fU1BERgogICAgICAtIERPQ0tFUl9FTkFCTEVfU0VDVVJJVFk9ZmFsc2UK",
 | 
				
			||||||
 | 
					        "tags": [
 | 
				
			||||||
 | 
					            "pdf",
 | 
				
			||||||
 | 
					            "manipulation",
 | 
				
			||||||
 | 
					            "web",
 | 
				
			||||||
 | 
					            "tool"
 | 
				
			||||||
 | 
					        ]
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    "trigger-with-external-database": {
 | 
					    "trigger-with-external-database": {
 | 
				
			||||||
        "documentation": "https:\/\/trigger.dev\/docs\/documentation\/guides\/self-hosting",
 | 
					        "documentation": "https:\/\/trigger.dev\/docs\/documentation\/guides\/self-hosting",
 | 
				
			||||||
        "slogan": "The open source Background Jobs framework for TypeScript",
 | 
					        "slogan": "The open source Background Jobs framework for TypeScript",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,7 +4,7 @@
 | 
				
			|||||||
            "version": "3.12.36"
 | 
					            "version": "3.12.36"
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        "v4": {
 | 
					        "v4": {
 | 
				
			||||||
            "version": "4.0.0-beta.175"
 | 
					            "version": "4.0.0-beta.182"
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user