diff --git a/app/Actions/Application/GenerateConfig.php b/app/Actions/Application/GenerateConfig.php new file mode 100644 index 000000000..69365f921 --- /dev/null +++ b/app/Actions/Application/GenerateConfig.php @@ -0,0 +1,17 @@ +clearAll(); + return $application->generateConfig(is_json: $is_json); + } +} diff --git a/app/Livewire/Project/Application/General.php b/app/Livewire/Project/Application/General.php index d2700f444..787bf879c 100644 --- a/app/Livewire/Project/Application/General.php +++ b/app/Livewire/Project/Application/General.php @@ -2,6 +2,7 @@ namespace App\Livewire\Project\Application; +use App\Actions\Application\GenerateConfig; use App\Models\Application; use Illuminate\Support\Collection; use Livewire\Component; @@ -413,4 +414,16 @@ class General extends Component $this->dispatch('configurationChanged'); } } + public function downloadConfig() + { + $config = GenerateConfig::run($this->application, true); + $fileName = str($this->application->name)->slug()->append('_config.json'); + + return response()->streamDownload(function () use ($config) { + echo $config; + }, $fileName, [ + 'Content-Type' => 'application/json', + 'Content-Disposition' => 'attachment; filename=' . $fileName, + ]); + } } diff --git a/app/Livewire/Project/New/PublicGitRepository.php b/app/Livewire/Project/New/PublicGitRepository.php index b5c5cb1db..971d4700b 100644 --- a/app/Livewire/Project/New/PublicGitRepository.php +++ b/app/Livewire/Project/New/PublicGitRepository.php @@ -31,10 +31,12 @@ class PublicGitRepository extends Component public bool $isStatic = false; + public bool $checkCoolifyConfig = true; + public ?string $publish_directory = null; // In case of docker compose - public ?string $base_directory = null; + public string $base_directory = '/'; public ?string $docker_compose_location = '/docker-compose.yaml'; // End of docker compose @@ -97,6 +99,7 @@ class PublicGitRepository extends Component $this->base_directory = '/'.$this->base_directory; } } + } public function updatedDockerComposeLocation() @@ -275,6 +278,7 @@ class PublicGitRepository extends Component 'destination_id' => $destination->id, 'destination_type' => $destination_class, 'build_pack' => $this->build_pack, + 'base_directory' => $this->base_directory, ]; } else { $application_init = [ @@ -289,6 +293,7 @@ class PublicGitRepository extends Component 'source_id' => $this->git_source->id, 'source_type' => $this->git_source->getMorphClass(), 'build_pack' => $this->build_pack, + 'base_directory' => $this->base_directory, ]; } @@ -303,11 +308,15 @@ class PublicGitRepository extends Component $application->settings->is_static = $this->isStatic; $application->settings->save(); - $fqdn = generateFqdn($destination->server, $application->uuid); $application->fqdn = $fqdn; $application->save(); - + if ($this->checkCoolifyConfig) { + // $config = loadConfigFromGit($this->repository_url, $this->git_branch, $this->base_directory, $this->query['server_id'], auth()->user()->currentTeam()->id); + // if ($config) { + // $application->setConfig($config); + // } + } return redirect()->route('project.application.configuration', [ 'application_uuid' => $application->uuid, 'environment_name' => $environment->name, diff --git a/app/Livewire/Project/Shared/UploadConfig.php b/app/Livewire/Project/Shared/UploadConfig.php new file mode 100644 index 000000000..dea842651 --- /dev/null +++ b/app/Livewire/Project/Shared/UploadConfig.php @@ -0,0 +1,41 @@ +config = '{ + "build_pack": "nixpacks", + "base_directory": "/nodejs", + "publish_directory": "/", + "ports_exposes": "3000", + "settings": { + "is_static": false + } +}'; + } + } + public function uploadConfig() + { + try { + $application = Application::findOrFail($this->applicationId); + $application->setConfig($this->config); + $this->dispatch('success', 'Application settings updated'); + } catch (\Exception $e) { + $this->dispatch('error', $e->getMessage()); + return; + } + + } + public function render() + { + return view('livewire.project.shared.upload-config'); + } +} diff --git a/app/Models/Application.php b/app/Models/Application.php index e4ab3918a..07aeb4c5b 100644 --- a/app/Models/Application.php +++ b/app/Models/Application.php @@ -9,6 +9,7 @@ use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Process\InvokedProcess; use Illuminate\Support\Collection; use Illuminate\Support\Facades\Process; +use Illuminate\Support\Facades\Validator; use Illuminate\Support\Str; use OpenApi\Attributes as OA; use RuntimeException; @@ -1427,4 +1428,67 @@ class Application extends BaseModel return $parsedCollection->toArray(); } } + + public function generateConfig($is_json = false) + { + $config = collect([]); + if ($this->build_pack = 'nixpacks') { + $config = collect([ + 'build_pack' => 'nixpacks', + 'docker_registry_image_name' => $this->docker_registry_image_name, + 'docker_registry_image_tag' => $this->docker_registry_image_tag, + 'install_command' => $this->install_command, + 'build_command' => $this->build_command, + 'start_command' => $this->start_command, + 'base_directory' => $this->base_directory, + 'publish_directory' => $this->publish_directory, + 'custom_docker_run_options' => $this->custom_docker_run_options, + 'ports_exposes' => $this->ports_exposes, + 'ports_mappings' => $this->ports_mapping, + 'settings' => collect([ + 'is_static' => $this->settings->is_static, + ]), + ]); + } + $config = $config->filter(function ($value) { + return str($value)->isNotEmpty(); + }); + if ($is_json) { + return json_encode($config, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES); + } + + return $config; + } + public function setConfig($config) { + + $config = $config; + $validator = Validator::make(['config' => $config], [ + 'config' => 'required|json', + ]); + if ($validator->fails()) { + throw new \Exception('Invalid JSON format'); + } + $config = json_decode($config, true); + + $deepValidator = Validator::make(['config' => $config], [ + 'config.build_pack' => 'required|string', + 'config.base_directory' => 'required|string', + 'config.publish_directory' => 'required|string', + 'config.ports_exposes' => 'required|string', + 'config.settings.is_static' => 'required|boolean', + ]); + if ($deepValidator->fails()) { + throw new \Exception('Invalid data'); + } + $config = $deepValidator->validated()['config']; + + try { + $settings = data_get($config, 'settings', []); + data_forget($config, 'settings'); + $this->update($config); + $this->settings()->update($settings); + } catch (\Exception $e) { + throw new \Exception('Failed to update application settings'); + } + } } diff --git a/bootstrap/helpers/shared.php b/bootstrap/helpers/shared.php index 65fe3322d..487a6f107 100644 --- a/bootstrap/helpers/shared.php +++ b/bootstrap/helpers/shared.php @@ -3981,3 +3981,31 @@ function instanceSettings() { return InstanceSettings::get(); } + +function loadConfigFromGit(string $repository, string $branch, string $base_directory, int $server_id, int $team_id) { + + $server = Server::find($server_id)->where('team_id', $team_id)->first(); + if (!$server) { + return; + } + $uuid = new Cuid2(); + $cloneCommand = "git clone --no-checkout -b $branch $repository ."; + $workdir = rtrim($base_directory, '/'); + $fileList = collect([".$workdir/coolify.json"]); + $commands = collect([ + "rm -rf /tmp/{$uuid}", + "mkdir -p /tmp/{$uuid}", + "cd /tmp/{$uuid}", + $cloneCommand, + 'git sparse-checkout init --cone', + "git sparse-checkout set {$fileList->implode(' ')}", + 'git read-tree -mu HEAD', + "cat .$workdir/coolify.json", + 'rm -rf /tmp/{$uuid}', + ]); + try { + return instant_remote_process($commands, $server); + } catch (\Exception $e) { + // continue + } +} diff --git a/resources/views/livewire/project/application/general.blade.php b/resources/views/livewire/project/application/general.blade.php index ce9fad1c4..e2cc92528 100644 --- a/resources/views/livewire/project/application/general.blade.php +++ b/resources/views/livewire/project/application/general.blade.php @@ -5,6 +5,13 @@ Save + {{-- + + Download Config + + + + --}}
General configuration for your application.
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 cef6cffaf..090f9ee4a 100644 --- a/resources/views/livewire/project/new/public-git-repository.blade.php +++ b/resources/views/livewire/project/new/public-git-repository.blade.php @@ -52,15 +52,21 @@ helper="It is calculated together with the Base Directory:
{{ Str::start($base_directory . $docker_compose_location, '/') }}" /> Compose file location in your repository:{{ Str::start($base_directory . $docker_compose_location, '/') }} + @else + @endif @if ($show_is_static) -
+
@endif + {{--
+ +
--}} {{-- @if ($build_pack === 'dockercompose' && isDev())
If you choose Docker Compose based deployments, you cannot change it afterwards.
diff --git a/resources/views/livewire/project/shared/upload-config.blade.php b/resources/views/livewire/project/shared/upload-config.blade.php new file mode 100644 index 000000000..6980d249e --- /dev/null +++ b/resources/views/livewire/project/shared/upload-config.blade.php @@ -0,0 +1,6 @@ +
+ + + Upload + +