From 27e4882d571c0a364d281f10f3f83d1182a28c3f Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Thu, 27 Feb 2025 11:29:04 +0100 Subject: [PATCH] feat(core): You can validate compose files with docker compose config fix(core): labels are now accepted with both compose styles refactor: remove lots of ray's --- app/Actions/Docker/GetContainersStatus.php | 1 - .../Api/ApplicationsController.php | 5 - app/Http/Controllers/Webhook/Bitbucket.php | 2 +- app/Http/Controllers/Webhook/Gitea.php | 1 - app/Http/Controllers/Webhook/Github.php | 1 - app/Http/Controllers/Webhook/Gitlab.php | 1 - app/Jobs/ApplicationDeploymentJob.php | 2 - app/Livewire/MonacoEditor.php | 2 +- app/Livewire/Project/New/DockerCompose.php | 6 - app/Livewire/Project/Service/EditCompose.php | 10 ++ app/Livewire/Project/Service/StackForm.php | 6 +- app/Livewire/Project/Shared/Webhooks.php | 2 - app/Livewire/Server/Proxy/Deploy.php | 1 - app/Livewire/Source/Github/Change.php | 1 - app/Models/Server.php | 6 - app/Notifications/Dto/PushoverMessage.php | 2 +- app/Traits/HasNotificationSettings.php | 2 +- bootstrap/helpers/applications.php | 2 - bootstrap/helpers/docker.php | 57 ++++---- bootstrap/helpers/shared.php | 135 +++++++++--------- config/chunk-upload.php | 1 + config/debugbar.php | 2 +- .../project/service/edit-compose.blade.php | 34 ++--- tests/Browser/LoginTest.php | 2 +- tests/Browser/Project/ProjectAddNewTest.php | 2 +- tests/Browser/Project/ProjectSearchTest.php | 2 +- tests/Browser/Project/ProjectTest.php | 2 +- tests/Feature/DockerComposeParseTest.php | 8 +- tests/Pest.php | 1 + 29 files changed, 137 insertions(+), 162 deletions(-) diff --git a/app/Actions/Docker/GetContainersStatus.php b/app/Actions/Docker/GetContainersStatus.php index c0e088203..091268043 100644 --- a/app/Actions/Docker/GetContainersStatus.php +++ b/app/Actions/Docker/GetContainersStatus.php @@ -208,7 +208,6 @@ class GetContainersStatus $foundServices[] = "$service->id-$service->name"; $statusFromDb = $service->status; if ($statusFromDb !== $containerStatus) { - // ray('Updating status: ' . $containerStatus); $service->update(['status' => $containerStatus]); } else { $service->update(['last_online_at' => now()]); diff --git a/app/Http/Controllers/Api/ApplicationsController.php b/app/Http/Controllers/Api/ApplicationsController.php index ff926bf70..4762a04b9 100644 --- a/app/Http/Controllers/Api/ApplicationsController.php +++ b/app/Http/Controllers/Api/ApplicationsController.php @@ -1291,11 +1291,6 @@ class ApplicationsController extends Controller $dockerCompose = base64_decode($request->docker_compose_raw); $dockerComposeRaw = Yaml::dump(Yaml::parse($dockerCompose), 10, 2, Yaml::DUMP_MULTI_LINE_LITERAL_BLOCK); - // $isValid = validateComposeFile($dockerComposeRaw, $server_id); - // if ($isValid !== 'OK') { - // return $this->dispatch('error', "Invalid docker-compose file.\n$isValid"); - // } - $service = new Service; removeUnnecessaryFieldsFromRequest($request); $service->fill($request->all()); diff --git a/app/Http/Controllers/Webhook/Bitbucket.php b/app/Http/Controllers/Webhook/Bitbucket.php index b629daf54..33d8f8532 100644 --- a/app/Http/Controllers/Webhook/Bitbucket.php +++ b/app/Http/Controllers/Webhook/Bitbucket.php @@ -49,7 +49,7 @@ class Bitbucket extends Controller $full_name = data_get($payload, 'repository.full_name'); $commit = data_get($payload, 'push.changes.0.new.target.hash'); - if (!$branch) { + if (! $branch) { return response([ 'status' => 'failed', 'message' => 'Nothing to do. No branch found in the request.', diff --git a/app/Http/Controllers/Webhook/Gitea.php b/app/Http/Controllers/Webhook/Gitea.php index cc53f2034..dbdd0b27d 100644 --- a/app/Http/Controllers/Webhook/Gitea.php +++ b/app/Http/Controllers/Webhook/Gitea.php @@ -202,7 +202,6 @@ class Gitea extends Controller if ($found) { $found->delete(); $container_name = generateApplicationContainerName($application, $pull_request_id); - // ray('Stopping container: ' . $container_name); instant_remote_process(["docker rm -f $container_name"], $application->destination->server); $return_payloads->push([ 'application' => $application->name, diff --git a/app/Http/Controllers/Webhook/Github.php b/app/Http/Controllers/Webhook/Github.php index ac1d4ded2..882f2be8b 100644 --- a/app/Http/Controllers/Webhook/Github.php +++ b/app/Http/Controllers/Webhook/Github.php @@ -208,7 +208,6 @@ class Github extends Controller if ($found) { $found->delete(); $container_name = generateApplicationContainerName($application, $pull_request_id); - // ray('Stopping container: ' . $container_name); instant_remote_process(["docker rm -f $container_name"], $application->destination->server); $return_payloads->push([ 'application' => $application->name, diff --git a/app/Http/Controllers/Webhook/Gitlab.php b/app/Http/Controllers/Webhook/Gitlab.php index d8dcc0c3b..cf6874b8c 100644 --- a/app/Http/Controllers/Webhook/Gitlab.php +++ b/app/Http/Controllers/Webhook/Gitlab.php @@ -227,7 +227,6 @@ class Gitlab extends Controller if ($found) { $found->delete(); $container_name = generateApplicationContainerName($application, $pull_request_id); - // ray('Stopping container: ' . $container_name); instant_remote_process(["docker rm -f $container_name"], $application->destination->server); $return_payloads->push([ 'application' => $application->name, diff --git a/app/Jobs/ApplicationDeploymentJob.php b/app/Jobs/ApplicationDeploymentJob.php index c28f22742..d0e88df44 100644 --- a/app/Jobs/ApplicationDeploymentJob.php +++ b/app/Jobs/ApplicationDeploymentJob.php @@ -1207,7 +1207,6 @@ class ApplicationDeploymentJob implements ShouldBeEncrypted, ShouldQueue if ($this->application->custom_healthcheck_found) { $this->application_deployment_queue->addLogEntry('Custom healthcheck found, skipping default healthcheck.'); } - // ray('New container name: ', $this->container_name); if ($this->container_name) { $counter = 1; $this->application_deployment_queue->addLogEntry('Waiting for healthcheck to pass on the new container.'); @@ -1410,7 +1409,6 @@ class ApplicationDeploymentJob implements ShouldBeEncrypted, ShouldQueue continue; } - // ray('Deploying to additional destination: ', $server->name); $deployment_uuid = new Cuid2; queue_application_deployment( deployment_uuid: $deployment_uuid, diff --git a/app/Livewire/MonacoEditor.php b/app/Livewire/MonacoEditor.php index 42d276e64..53ca1d386 100644 --- a/app/Livewire/MonacoEditor.php +++ b/app/Livewire/MonacoEditor.php @@ -2,7 +2,7 @@ namespace App\Livewire; -//use Livewire\Component; +// use Livewire\Component; use Illuminate\View\Component; use Visus\Cuid2\Cuid2; diff --git a/app/Livewire/Project/New/DockerCompose.php b/app/Livewire/Project/New/DockerCompose.php index 27975eaa2..2f51094d1 100644 --- a/app/Livewire/Project/New/DockerCompose.php +++ b/app/Livewire/Project/New/DockerCompose.php @@ -52,12 +52,6 @@ class DockerCompose extends Component 'dockerComposeRaw' => 'required', ]); $this->dockerComposeRaw = Yaml::dump(Yaml::parse($this->dockerComposeRaw), 10, 2, Yaml::DUMP_MULTI_LINE_LITERAL_BLOCK); - - $isValid = validateComposeFile($this->dockerComposeRaw, $server_id); - if ($isValid !== 'OK') { - return $this->dispatch('error', "Invalid docker-compose file.\n$isValid"); - } - $project = Project::where('uuid', $this->parameters['project_uuid'])->first(); $environment = $project->load(['environments'])->environments->where('uuid', $this->parameters['environment_uuid'])->first(); diff --git a/app/Livewire/Project/Service/EditCompose.php b/app/Livewire/Project/Service/EditCompose.php index dc043e65a..8ece12790 100644 --- a/app/Livewire/Project/Service/EditCompose.php +++ b/app/Livewire/Project/Service/EditCompose.php @@ -39,6 +39,16 @@ class EditCompose extends Component $this->service = Service::find($this->serviceId); } + public function validateCompose() + { + $isValid = validateComposeFile($this->service->docker_compose_raw, $this->service->server_id); + if ($isValid !== 'OK') { + $this->dispatch('error', "Invalid docker-compose file.\n$isValid"); + } else { + $this->dispatch('success', 'Docker compose is valid.'); + } + } + public function saveEditedCompose() { $this->dispatch('info', 'Saving new docker compose...'); diff --git a/app/Livewire/Project/Service/StackForm.php b/app/Livewire/Project/Service/StackForm.php index 2c751aa92..368598466 100644 --- a/app/Livewire/Project/Service/StackForm.php +++ b/app/Livewire/Project/Service/StackForm.php @@ -63,7 +63,7 @@ class StackForm extends Component public function saveCompose($raw) { $this->service->docker_compose_raw = $raw; - $this->submit(notify: false); + $this->submit(notify: true); } public function instantSave() @@ -76,10 +76,6 @@ class StackForm extends Component { try { $this->validate(); - $isValid = validateComposeFile($this->service->docker_compose_raw, $this->service->server->id); - if ($isValid !== 'OK') { - throw new \Exception("Invalid docker-compose file.\n$isValid"); - } $this->service->save(); $this->service->saveExtraFields($this->fields); $this->service->parse(); diff --git a/app/Livewire/Project/Shared/Webhooks.php b/app/Livewire/Project/Shared/Webhooks.php index aab1fdc47..57c65c4dd 100644 --- a/app/Livewire/Project/Shared/Webhooks.php +++ b/app/Livewire/Project/Shared/Webhooks.php @@ -29,8 +29,6 @@ class Webhooks extends Component public function mount() { - // ray()->clearAll(); - // ray()->showQueries(); $this->deploywebhook = generateDeployWebhook($this->resource); $this->githubManualWebhookSecret = data_get($this->resource, 'manual_webhook_secret_github'); diff --git a/app/Livewire/Server/Proxy/Deploy.php b/app/Livewire/Server/Proxy/Deploy.php index 4f9d41092..f823ff3d4 100644 --- a/app/Livewire/Server/Proxy/Deploy.php +++ b/app/Livewire/Server/Proxy/Deploy.php @@ -105,7 +105,6 @@ class Deploy extends Component $startTime = Carbon::now()->getTimestamp(); while ($process->running()) { - ray('running'); if (Carbon::now()->getTimestamp() - $startTime >= $timeout) { $this->forceStopContainer($containerName); break; diff --git a/app/Livewire/Source/Github/Change.php b/app/Livewire/Source/Github/Change.php index fc597748e..20f52c322 100644 --- a/app/Livewire/Source/Github/Change.php +++ b/app/Livewire/Source/Github/Change.php @@ -101,7 +101,6 @@ class Change extends Component // ]); // } - // ray($runners_by_repository); // } public function mount() diff --git a/app/Models/Server.php b/app/Models/Server.php index 187685d66..f5cf84604 100644 --- a/app/Models/Server.php +++ b/app/Models/Server.php @@ -437,10 +437,6 @@ class Server extends BaseModel "mkdir -p $dynamic_config_path", "echo '$base64' | base64 -d | tee $file > /dev/null", ], $this); - - if (config('app.env') === 'local') { - // ray($yaml); - } } } elseif ($this->proxyType() === 'CADDY') { $file = "$dynamic_config_path/coolify.caddy"; @@ -970,10 +966,8 @@ $schema://$host { } }); if ($supported->count() === 1) { - // ray('supported'); return str($supported->first()); } else { - // ray('not supported'); return false; } } diff --git a/app/Notifications/Dto/PushoverMessage.php b/app/Notifications/Dto/PushoverMessage.php index 0efd1d526..abf6f1b7a 100644 --- a/app/Notifications/Dto/PushoverMessage.php +++ b/app/Notifications/Dto/PushoverMessage.php @@ -40,7 +40,7 @@ class PushoverMessage if ($buttonUrl && str_contains($buttonUrl, 'http://localhost')) { $buttonUrl = str_replace('http://localhost', config('app.url'), $buttonUrl); } - $payload['message'] .= " " . $text . ''; + $payload['message'] .= " ".$text.''; } Log::info('Pushover message', $payload); diff --git a/app/Traits/HasNotificationSettings.php b/app/Traits/HasNotificationSettings.php index ef858d0b6..bb088896a 100644 --- a/app/Traits/HasNotificationSettings.php +++ b/app/Traits/HasNotificationSettings.php @@ -4,9 +4,9 @@ namespace App\Traits; use App\Notifications\Channels\DiscordChannel; use App\Notifications\Channels\EmailChannel; +use App\Notifications\Channels\PushoverChannel; use App\Notifications\Channels\SlackChannel; use App\Notifications\Channels\TelegramChannel; -use App\Notifications\Channels\PushoverChannel; use Illuminate\Database\Eloquent\Model; trait HasNotificationSettings diff --git a/bootstrap/helpers/applications.php b/bootstrap/helpers/applications.php index 73d5389ae..d5283898e 100644 --- a/bootstrap/helpers/applications.php +++ b/bootstrap/helpers/applications.php @@ -91,8 +91,6 @@ function next_queuable(string $server_id, string $application_id): bool $server = Server::find($server_id); $concurrent_builds = $server->settings->concurrent_builds; - // ray("serverId:{$server->id}", "concurrentBuilds:{$concurrent_builds}", "deployments:{$deployments->count()}", "sameApplicationDeployments:{$same_application_deployments->count()}")->green(); - if ($deployments->count() > $concurrent_builds) { return false; } diff --git a/bootstrap/helpers/docker.php b/bootstrap/helpers/docker.php index 696f6a8c4..59318eec5 100644 --- a/bootstrap/helpers/docker.php +++ b/bootstrap/helpers/docker.php @@ -569,7 +569,7 @@ function generateLabelsApplication(Application $application, ?ApplicationPreview if ($shouldGenerateLabelsExactly) { switch ($application->destination->server->proxyType()) { case ProxyTypes::TRAEFIK->value: - $labels = $labels->merge(fqdnLabelsForTraefik( + $proxyLabels = fqdnLabelsForTraefik( uuid: $appUuid, domains: $domains, onlyPort: $onlyPort, @@ -577,10 +577,11 @@ function generateLabelsApplication(Application $application, ?ApplicationPreview is_gzip_enabled: $application->isGzipEnabled(), is_stripprefix_enabled: $application->isStripprefixEnabled(), redirect_direction: $application->redirect - )); + ); + $labels = $labels->merge(convertToKeyValueCollection($proxyLabels)); break; case ProxyTypes::CADDY->value: - $labels = $labels->merge(fqdnLabelsForCaddy( + $proxyLabels = fqdnLabelsForCaddy( network: $application->destination->network, uuid: $appUuid, domains: $domains, @@ -589,11 +590,12 @@ function generateLabelsApplication(Application $application, ?ApplicationPreview is_gzip_enabled: $application->isGzipEnabled(), is_stripprefix_enabled: $application->isStripprefixEnabled(), redirect_direction: $application->redirect - )); + ); + $labels = $labels->merge(convertToKeyValueCollection($proxyLabels)); break; } } else { - $labels = $labels->merge(fqdnLabelsForTraefik( + $proxyLabels = fqdnLabelsForTraefik( uuid: $appUuid, domains: $domains, onlyPort: $onlyPort, @@ -601,8 +603,8 @@ function generateLabelsApplication(Application $application, ?ApplicationPreview is_gzip_enabled: $application->isGzipEnabled(), is_stripprefix_enabled: $application->isStripprefixEnabled(), redirect_direction: $application->redirect - )); - $labels = $labels->merge(fqdnLabelsForCaddy( + ); + $proxyLabels = fqdnLabelsForCaddy( network: $application->destination->network, uuid: $appUuid, domains: $domains, @@ -611,7 +613,8 @@ function generateLabelsApplication(Application $application, ?ApplicationPreview is_gzip_enabled: $application->isGzipEnabled(), is_stripprefix_enabled: $application->isStripprefixEnabled(), redirect_direction: $application->redirect - )); + ); + $labels = $labels->merge(convertToKeyValueCollection($proxyLabels)); } } } else { @@ -624,17 +627,18 @@ function generateLabelsApplication(Application $application, ?ApplicationPreview if ($shouldGenerateLabelsExactly) { switch ($application->destination->server->proxyType()) { case ProxyTypes::TRAEFIK->value: - $labels = $labels->merge(fqdnLabelsForTraefik( + $proxyLabels = fqdnLabelsForTraefik( uuid: $appUuid, domains: $domains, onlyPort: $onlyPort, is_force_https_enabled: $application->isForceHttpsEnabled(), is_gzip_enabled: $application->isGzipEnabled(), is_stripprefix_enabled: $application->isStripprefixEnabled() - )); + ); + $labels = $labels->merge(convertToKeyValueCollection($proxyLabels)); break; case ProxyTypes::CADDY->value: - $labels = $labels->merge(fqdnLabelsForCaddy( + $proxyLabels = fqdnLabelsForCaddy( network: $application->destination->network, uuid: $appUuid, domains: $domains, @@ -642,19 +646,20 @@ function generateLabelsApplication(Application $application, ?ApplicationPreview is_force_https_enabled: $application->isForceHttpsEnabled(), is_gzip_enabled: $application->isGzipEnabled(), is_stripprefix_enabled: $application->isStripprefixEnabled() - )); + ); + $labels = $labels->merge(convertToKeyValueCollection($proxyLabels)); break; } } else { - $labels = $labels->merge(fqdnLabelsForTraefik( + $proxyLabels = fqdnLabelsForTraefik( uuid: $appUuid, domains: $domains, onlyPort: $onlyPort, is_force_https_enabled: $application->isForceHttpsEnabled(), is_gzip_enabled: $application->isGzipEnabled(), is_stripprefix_enabled: $application->isStripprefixEnabled() - )); - $labels = $labels->merge(fqdnLabelsForCaddy( + ); + $proxyLabels = fqdnLabelsForCaddy( network: $application->destination->network, uuid: $appUuid, domains: $domains, @@ -662,7 +667,8 @@ function generateLabelsApplication(Application $application, ?ApplicationPreview is_force_https_enabled: $application->isForceHttpsEnabled(), is_gzip_enabled: $application->isGzipEnabled(), is_stripprefix_enabled: $application->isStripprefixEnabled() - )); + ); + $labels = $labels->merge(convertToKeyValueCollection($proxyLabels)); } } @@ -778,7 +784,6 @@ function convertDockerRunToCompose(?string $custom_docker_run_options = null) } } } - ray($payload); $compose_options->put('deploy', [ 'resources' => [ 'reservations' => [ @@ -829,26 +834,20 @@ function generateCustomDockerRunOptionsForDatabases($docker_run_options, $docker function validateComposeFile(string $compose, int $server_id): string|Throwable { - return 'OK'; + $uuid = Str::random(10); try { - $uuid = Str::random(10); - $server = Server::findOrFail($server_id); + $server = Server::ownedByCurrentTeam()->findOrFail($server_id); $base64_compose = base64_encode($compose); - $output = instant_remote_process([ + instant_remote_process([ "echo {$base64_compose} | base64 -d | tee /tmp/{$uuid}.yml > /dev/null", - "docker compose -f /tmp/{$uuid}.yml config", + "chmod 600 /tmp/{$uuid}.yml", + "docker compose -f /tmp/{$uuid}.yml config --no-interpolate --no-path-resolution -q", + "rm /tmp/{$uuid}.yml", ], $server); - ray($output); return 'OK'; } catch (\Throwable $e) { - ray($e); - return $e->getMessage(); - } finally { - instant_remote_process([ - "rm /tmp/{$uuid}.yml", - ], $server); } } diff --git a/bootstrap/helpers/shared.php b/bootstrap/helpers/shared.php index 3fba7edb7..c3d7d0bfc 100644 --- a/bootstrap/helpers/shared.php +++ b/bootstrap/helpers/shared.php @@ -800,7 +800,6 @@ function parseEnvVariable(Str|string $value) } else { // SERVICE_BASE64_64_UMAMI $command = $value->after('SERVICE_')->beforeLast('_'); - ray($command); } } } @@ -952,7 +951,6 @@ function validate_dns_entry(string $fqdn, Server $server) $type = \PurplePixie\PhpDns\DNSTypes::NAME_A; foreach ($dns_servers as $dns_server) { try { - ray("Checking $host on $dns_server"); $query = new DNSQuery($dns_server); $results = $query->query($host, $type); if ($results === false || $query->hasError()) { @@ -961,13 +959,10 @@ function validate_dns_entry(string $fqdn, Server $server) foreach ($results as $result) { if ($result->getType() == $type) { if (ip_match($result->getData(), $cloudflare_ips->toArray(), $match)) { - ray("Found match in Cloudflare IPs: $match"); $found_matching_ip = true; break; } if ($result->getData() === $ip) { - ray($host.' has IP address '.$result->getData()); - ray($result->getString()); $found_matching_ip = true; break; } @@ -977,7 +972,6 @@ function validate_dns_entry(string $fqdn, Server $server) } catch (\Exception) { } } - ray("Found match: $found_matching_ip"); return $found_matching_ip; } @@ -1331,7 +1325,6 @@ function parseServiceVolumes($serviceVolumes, $resource, $topLevelVolumes, $pull $isDirectory = (bool) data_get($volume, 'isDirectory', null) || (bool) data_get($volume, 'is_directory', null); if ((is_null($isDirectory) || ! $isDirectory) && is_null($content)) { // if isDirectory is not set (or false) & content is also not set, we assume it is a directory - ray('setting isDirectory to true'); $isDirectory = true; } } @@ -1483,6 +1476,7 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal $serviceNetworks = collect(data_get($service, 'networks', [])); $serviceVariables = collect(data_get($service, 'environment', [])); $serviceLabels = collect(data_get($service, 'labels', [])); + $serviceLabels = convertToKeyValueCollection($serviceLabels); $hasHostNetworkMode = data_get($service, 'network_mode') === 'host' ? true : false; if ($serviceLabels->count() > 0) { $removedLabels = collect([]); @@ -1499,7 +1493,6 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal $serviceLabels->push("$removedLabelName=$removedLabel"); } } - $containerName = "$serviceName-{$resource->uuid}"; // Decide if the service is a database @@ -1662,7 +1655,6 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal } if (is_null($isDirectory) && is_null($content)) { // if isDirectory is not set & content is also not set, we assume it is a directory - ray('setting isDirectory to true'); $isDirectory = true; } } @@ -2013,7 +2005,7 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal if ($shouldGenerateLabelsExactly) { switch ($resource->server->proxyType()) { case ProxyTypes::TRAEFIK->value: - $serviceLabels = $serviceLabels->merge(fqdnLabelsForTraefik( + $proxyLabels = fqdnLabelsForTraefik( uuid: $resource->uuid, domains: $fqdns, is_force_https_enabled: true, @@ -2022,10 +2014,12 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal is_stripprefix_enabled: $savedService->isStripprefixEnabled(), service_name: $serviceName, image: data_get($service, 'image') - )); + ); + $serviceLabels = $serviceLabels->merge(convertToKeyValueCollection($proxyLabels)); + break; case ProxyTypes::CADDY->value: - $serviceLabels = $serviceLabels->merge(fqdnLabelsForCaddy( + $proxyLabels = fqdnLabelsForCaddy( network: $resource->destination->network, uuid: $resource->uuid, domains: $fqdns, @@ -2035,11 +2029,13 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal is_stripprefix_enabled: $savedService->isStripprefixEnabled(), service_name: $serviceName, image: data_get($service, 'image') - )); + ); + $serviceLabels = $serviceLabels->merge(convertToKeyValueCollection($proxyLabels)); + break; } } else { - $serviceLabels = $serviceLabels->merge(fqdnLabelsForTraefik( + $proxyLabels = fqdnLabelsForTraefik( uuid: $resource->uuid, domains: $fqdns, is_force_https_enabled: true, @@ -2048,8 +2044,8 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal is_stripprefix_enabled: $savedService->isStripprefixEnabled(), service_name: $serviceName, image: data_get($service, 'image') - )); - $serviceLabels = $serviceLabels->merge(fqdnLabelsForCaddy( + ); + $proxyLabels = fqdnLabelsForCaddy( network: $resource->destination->network, uuid: $resource->uuid, domains: $fqdns, @@ -2059,7 +2055,8 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal is_stripprefix_enabled: $savedService->isStripprefixEnabled(), service_name: $serviceName, image: data_get($service, 'image') - )); + ); + $serviceLabels = $serviceLabels->merge(convertToKeyValueCollection($proxyLabels)); } } } @@ -2208,6 +2205,7 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal $serviceVariables = collect(data_get($service, 'environment', [])); $serviceDependencies = collect(data_get($service, 'depends_on', [])); $serviceLabels = collect(data_get($service, 'labels', [])); + $serviceLabels = convertToKeyValueCollection($serviceLabels); $serviceBuildVariables = collect(data_get($service, 'build.args', [])); $serviceVariables = $serviceVariables->merge($serviceBuildVariables); if ($serviceLabels->count() > 0) { @@ -2529,9 +2527,6 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal } } } - if ($collectedPorts->count() > 0) { - ray($collectedPorts->implode(',')); - } $definedNetworkExists = $topLevelNetworks->contains(function ($value, $_) use ($definedNetwork) { return $value == $definedNetwork; }); @@ -2784,48 +2779,46 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal if ($shouldGenerateLabelsExactly) { switch ($server->proxyType()) { case ProxyTypes::TRAEFIK->value: - $serviceLabels = $serviceLabels->merge( - fqdnLabelsForTraefik( - uuid: $resource->uuid, - domains: $fqdns, - serviceLabels: $serviceLabels, - generate_unique_uuid: $resource->build_pack === 'dockercompose', - image: data_get($service, 'image'), - is_force_https_enabled: $resource->isForceHttpsEnabled(), - is_gzip_enabled: $resource->isGzipEnabled(), - is_stripprefix_enabled: $resource->isStripprefixEnabled(), - ) + $proxyLabels = fqdnLabelsForTraefik( + uuid: $resource->uuid, + domains: $fqdns, + serviceLabels: $serviceLabels, + generate_unique_uuid: $resource->build_pack === 'dockercompose', + image: data_get($service, 'image'), + is_force_https_enabled: $resource->isForceHttpsEnabled(), + is_gzip_enabled: $resource->isGzipEnabled(), + is_stripprefix_enabled: $resource->isStripprefixEnabled(), ); + $serviceLabels = $serviceLabels->merge(convertToKeyValueCollection($proxyLabels)); + break; case ProxyTypes::CADDY->value: - $serviceLabels = $serviceLabels->merge( - fqdnLabelsForCaddy( - network: $resource->destination->network, - uuid: $resource->uuid, - domains: $fqdns, - serviceLabels: $serviceLabels, - image: data_get($service, 'image'), - is_force_https_enabled: $resource->isForceHttpsEnabled(), - is_gzip_enabled: $resource->isGzipEnabled(), - is_stripprefix_enabled: $resource->isStripprefixEnabled(), - ) + $proxyLabels = fqdnLabelsForCaddy( + network: $resource->destination->network, + uuid: $resource->uuid, + domains: $fqdns, + serviceLabels: $serviceLabels, + image: data_get($service, 'image'), + is_force_https_enabled: $resource->isForceHttpsEnabled(), + is_gzip_enabled: $resource->isGzipEnabled(), + is_stripprefix_enabled: $resource->isStripprefixEnabled(), ); + $serviceLabels = $serviceLabels->merge(convertToKeyValueCollection($proxyLabels)); + break; } } else { - $serviceLabels = $serviceLabels->merge( - fqdnLabelsForTraefik( - uuid: $resource->uuid, - domains: $fqdns, - serviceLabels: $serviceLabels, - generate_unique_uuid: $resource->build_pack === 'dockercompose', - image: data_get($service, 'image'), - is_force_https_enabled: $resource->isForceHttpsEnabled(), - is_gzip_enabled: $resource->isGzipEnabled(), - is_stripprefix_enabled: $resource->isStripprefixEnabled(), - ) + $proxyLabels = fqdnLabelsForTraefik( + uuid: $resource->uuid, + domains: $fqdns, + serviceLabels: $serviceLabels, + generate_unique_uuid: $resource->build_pack === 'dockercompose', + image: data_get($service, 'image'), + is_force_https_enabled: $resource->isForceHttpsEnabled(), + is_gzip_enabled: $resource->isGzipEnabled(), + is_stripprefix_enabled: $resource->isStripprefixEnabled(), ); - $serviceLabels = $serviceLabels->merge( + $proxyLabels = fqdnLabelsForCaddy( network: $resource->destination->network, uuid: $resource->uuid, @@ -2835,8 +2828,8 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal is_force_https_enabled: $resource->isForceHttpsEnabled(), is_gzip_enabled: $resource->isGzipEnabled(), is_stripprefix_enabled: $resource->isStripprefixEnabled(), - ) - ); + ); + $serviceLabels = $serviceLabels->merge(convertToKeyValueCollection($proxyLabels)); } } } @@ -2851,7 +2844,7 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal pull_request_id: $pull_request_id, type: 'application' ); - $serviceLabels = $serviceLabels->merge($defaultLabels); + $serviceLabels = $serviceLabels->merge(convertToKeyValueCollection($defaultLabels)); if ($server->isLogDrainEnabled()) { if ($resource instanceof Application && $resource->isLogDrainEnabled()) { @@ -2956,7 +2949,6 @@ function newParser(Application|Service $resource, int $pull_request_id = 0, ?int } $parsedServices = collect([]); - // ray()->clearAll(); $allMagicEnvironments = collect([]); foreach ($services as $serviceName => $service) { @@ -3016,7 +3008,7 @@ function newParser(Application|Service $resource, int $pull_request_id = 0, ?int $environment = $environment->merge($buildArgs); // convert environment variables to one format - $environment = convertComposeEnvironmentToArray($environment); + $environment = convertToKeyValueCollection($environment); // Add Coolify defined environments $allEnvironments = $resource->environment_variables()->get(['key', 'value']); @@ -3192,12 +3184,13 @@ function newParser(Application|Service $resource, int $pull_request_id = 0, ?int $use_network_mode = data_get($service, 'network_mode') !== null; $depends_on = collect(data_get($service, 'depends_on', [])); $labels = collect(data_get($service, 'labels', [])); + $labels = convertToKeyValueCollection($labels); $environment = collect(data_get($service, 'environment', [])); $ports = collect(data_get($service, 'ports', [])); $buildArgs = collect(data_get($service, 'build.args', [])); $environment = $environment->merge($buildArgs); - $environment = convertComposeEnvironmentToArray($environment); + $environment = convertToKeyValueCollection($environment); $coolifyEnvironments = collect([]); $isDatabase = isDatabaseImage(data_get_str($service, 'image')); @@ -3704,7 +3697,7 @@ function newParser(Application|Service $resource, int $pull_request_id = 0, ?int return $value; }); } - $serviceLabels = $labels->merge($defaultLabels); + $serviceLabels = $labels->merge(convertToKeyValueCollection($defaultLabels)); if ($serviceLabels->count() > 0) { if ($isApplication) { $isContainerLabelEscapeEnabled = data_get($resource, 'settings.is_container_label_escape_enabled'); @@ -3736,7 +3729,7 @@ function newParser(Application|Service $resource, int $pull_request_id = 0, ?int if ($shouldGenerateLabelsExactly) { switch ($server->proxyType()) { case ProxyTypes::TRAEFIK->value: - $serviceLabels = $serviceLabels->merge(fqdnLabelsForTraefik( + $proxyLabels = fqdnLabelsForTraefik( uuid: $uuid, domains: $fqdns, is_force_https_enabled: true, @@ -3745,10 +3738,11 @@ function newParser(Application|Service $resource, int $pull_request_id = 0, ?int is_stripprefix_enabled: $originalResource->isStripprefixEnabled(), service_name: $serviceName, image: $image - )); + ); + $serviceLabels = $serviceLabels->merge(convertToKeyValueCollection($proxyLabels)); break; case ProxyTypes::CADDY->value: - $serviceLabels = $serviceLabels->merge(fqdnLabelsForCaddy( + $proxyLabels = fqdnLabelsForCaddy( network: $network, uuid: $uuid, domains: $fqdns, @@ -3759,11 +3753,13 @@ function newParser(Application|Service $resource, int $pull_request_id = 0, ?int service_name: $serviceName, image: $image, predefinedPort: $predefinedPort - )); + ); + $serviceLabels = $serviceLabels->merge(convertToKeyValueCollection($proxyLabels)); + break; } } else { - $serviceLabels = $serviceLabels->merge(fqdnLabelsForTraefik( + $proxyLabels = fqdnLabelsForTraefik( uuid: $uuid, domains: $fqdns, is_force_https_enabled: true, @@ -3772,8 +3768,8 @@ function newParser(Application|Service $resource, int $pull_request_id = 0, ?int is_stripprefix_enabled: $originalResource->isStripprefixEnabled(), service_name: $serviceName, image: $image - )); - $serviceLabels = $serviceLabels->merge(fqdnLabelsForCaddy( + ); + $proxyLabels = $proxyLabels->merge(fqdnLabelsForCaddy( network: $network, uuid: $uuid, domains: $fqdns, @@ -3785,6 +3781,7 @@ function newParser(Application|Service $resource, int $pull_request_id = 0, ?int image: $image, predefinedPort: $predefinedPort )); + $serviceLabels = $serviceLabels->merge(convertToKeyValueCollection($proxyLabels)); } } if ($isService) { @@ -3934,7 +3931,7 @@ function add_coolify_default_environment_variables(StandaloneRedis|StandalonePos } } -function convertComposeEnvironmentToArray($environment) +function convertToKeyValueCollection($environment) { $convertedServiceVariables = collect([]); if (isAssociativeArray($environment)) { diff --git a/config/chunk-upload.php b/config/chunk-upload.php index a0baf8139..e577eb858 100644 --- a/config/chunk-upload.php +++ b/config/chunk-upload.php @@ -1,4 +1,5 @@ [ 'timeline' => false, // Add the views to the timeline (Experimental) - 'data' => false, //true for all data, 'keys' for only names, false for no parameters. + 'data' => false, // true for all data, 'keys' for only names, false for no parameters. 'group' => 50, // Group duplicate views. Pass value to auto-group, or true/false to force 'exclude_paths' => [ // Add the paths which you don't want to appear in the views 'vendor/filament', // Exclude Filament components by default diff --git a/resources/views/livewire/project/service/edit-compose.blade.php b/resources/views/livewire/project/service/edit-compose.blade.php index beaccac91..513bd8a90 100644 --- a/resources/views/livewire/project/service/edit-compose.blade.php +++ b/resources/views/livewire/project/service/edit-compose.blade.php @@ -20,27 +20,27 @@
- -
-
- Switch - Textarea +
+ +
+
-
-
-
- Show Deployable Compose -
-
- Show Source - Compose -
+
+
+ Show Deployable Compose +
+
+ Show Source + Compose
- + + Validate + + Save
diff --git a/tests/Browser/LoginTest.php b/tests/Browser/LoginTest.php index 5e8d5c53e..d20e65294 100644 --- a/tests/Browser/LoginTest.php +++ b/tests/Browser/LoginTest.php @@ -16,7 +16,7 @@ class LoginTest extends DuskTestCase * * @throws Throwable */ - public function testLogin() + public function test_login() { $this->browse(callback: function (Browser $browser) { $browser->loginWithRootUser() diff --git a/tests/Browser/Project/ProjectAddNewTest.php b/tests/Browser/Project/ProjectAddNewTest.php index 0dae7603e..b03313e4b 100644 --- a/tests/Browser/Project/ProjectAddNewTest.php +++ b/tests/Browser/Project/ProjectAddNewTest.php @@ -16,7 +16,7 @@ class ProjectAddNewTest extends DuskTestCase * * @throws Throwable */ - public function testLogin() + public function test_login() { $this->browse(function (Browser $browser) { $browser->loginWithRootUser() diff --git a/tests/Browser/Project/ProjectSearchTest.php b/tests/Browser/Project/ProjectSearchTest.php index aedf17183..7bc6796d1 100644 --- a/tests/Browser/Project/ProjectSearchTest.php +++ b/tests/Browser/Project/ProjectSearchTest.php @@ -16,7 +16,7 @@ class ProjectSearchTest extends DuskTestCase * * @throws Throwable */ - public function testLogin() + public function test_login() { $this->browse(function (Browser $browser) { $browser->loginWithRootUser() diff --git a/tests/Browser/Project/ProjectTest.php b/tests/Browser/Project/ProjectTest.php index e4707da8a..0d360e460 100644 --- a/tests/Browser/Project/ProjectTest.php +++ b/tests/Browser/Project/ProjectTest.php @@ -16,7 +16,7 @@ class ProjectTest extends DuskTestCase * * @throws Throwable */ - public function testLogin() + public function test_login() { $this->browse(function (Browser $browser) { $browser->loginWithRootUser() diff --git a/tests/Feature/DockerComposeParseTest.php b/tests/Feature/DockerComposeParseTest.php index d21adac8e..9407d2470 100644 --- a/tests/Feature/DockerComposeParseTest.php +++ b/tests/Feature/DockerComposeParseTest.php @@ -358,7 +358,7 @@ use Symfony\Component\Yaml\Yaml; // expect($output)->toContain('Docker version'); // }); -// test('ConvertComposeEnvironmentToArray', function () { +// test('convertToKeyValueCollection', function () { // ray()->clearAll(); // $yaml = ' // services: @@ -374,9 +374,9 @@ use Symfony\Component\Yaml\Yaml; // - POSTGRES_DB: activepieces // '; // $parsedYaml = Yaml::parse($yaml); -// $output = convertComposeEnvironmentToArray($parsedYaml['services']['activepieces']['environment']); -// $output2 = convertComposeEnvironmentToArray($parsedYaml['services']['activepieces2']['environment']); -// $dboutput = convertComposeEnvironmentToArray($parsedYaml['services']['postgres']['environment']); +// $output = convertToKeyValueCollection($parsedYaml['services']['activepieces']['environment']); +// $output2 = convertToKeyValueCollection($parsedYaml['services']['activepieces2']['environment']); +// $dboutput = convertToKeyValueCollection($parsedYaml['services']['postgres']['environment']); // ray($output); // ray($output2); // ray($dboutput); diff --git a/tests/Pest.php b/tests/Pest.php index 0178e9648..236ac497e 100644 --- a/tests/Pest.php +++ b/tests/Pest.php @@ -1,4 +1,5 @@