fix(compose): normalize service-name keys for domains and env vars (#11040)

This commit is contained in:
Andras Bacsai
2026-08-03 23:08:56 +02:00
committed by GitHub
parent 7b18777f06
commit 0b843bb07c
18 changed files with 1443 additions and 220 deletions
+62 -25
View File
@@ -301,12 +301,7 @@ class General extends Component
}
$this->parsedServiceDomains = $this->application->docker_compose_domains ? json_decode($this->application->docker_compose_domains, true) : [];
// Convert service names with dots and dashes to use underscores for HTML form binding
$sanitizedDomains = [];
foreach ($this->parsedServiceDomains as $serviceName => $domain) {
$sanitizedKey = str($serviceName)->replace('-', '_')->replace('.', '_')->toString();
$sanitizedDomains[$sanitizedKey] = $domain;
}
$this->parsedServiceDomains = $sanitizedDomains;
$this->parsedServiceDomains = $this->sanitizeParsedServiceDomainsForForm($this->parsedServiceDomains);
$this->customLabels = $this->application->parseContainerLabels();
if (! $this->customLabels && $this->application->destination->server->proxyType() !== 'NONE' && $this->application->settings->is_container_label_readonly_enabled === true) {
@@ -520,12 +515,7 @@ class General extends Component
$this->parsedServiceDomains = $this->application->docker_compose_domains ? json_decode($this->application->docker_compose_domains, true) : [];
// Convert service names with dots and dashes to use underscores for HTML form binding
$sanitizedDomains = [];
foreach ($this->parsedServiceDomains as $serviceName => $domain) {
$sanitizedKey = str($serviceName)->replace('-', '_')->replace('.', '_')->toString();
$sanitizedDomains[$sanitizedKey] = $domain;
}
$this->parsedServiceDomains = $sanitizedDomains;
$this->parsedServiceDomains = $this->sanitizeParsedServiceDomainsForForm($this->parsedServiceDomains);
$showToast && $this->dispatch('success', 'Docker compose file loaded.');
$this->dispatch('compose_loaded');
@@ -551,22 +541,14 @@ class General extends Component
$uuid = new_public_id();
$domain = generateUrl(server: $this->application->destination->server, random: $uuid);
$sanitizedKey = str($serviceName)->replace('-', '_')->replace('.', '_')->toString();
$sanitizedKey = normalizeComposeServiceName($serviceName);
$this->parsedServiceDomains[$sanitizedKey]['domain'] = $domain;
// Convert back to original service names for storage
$originalDomains = [];
$composeServiceNames = collect(data_get($this->parsedServices, 'services', []))->keys()->map(fn ($name) => (string) $name)->values()->all();
foreach ($this->parsedServiceDomains as $key => $value) {
// Find the original service name by checking parsed services
$originalServiceName = $key;
if (isset($this->parsedServices['services'])) {
foreach ($this->parsedServices['services'] as $originalName => $service) {
if (str($originalName)->replace('-', '_')->replace('.', '_')->toString() === $key) {
$originalServiceName = $originalName;
break;
}
}
}
$originalServiceName = findComposeServiceName((string) $key, $composeServiceNames) ?? (string) $key;
$originalDomains[$originalServiceName] = $value;
}
@@ -858,9 +840,10 @@ class General extends Component
foreach ($this->parsedServiceDomains as $serviceName => $service) {
$this->parsedServiceDomains[$serviceName]['domain'] = ValidationPatterns::normalizeApplicationDomains(data_get($service, 'domain'));
}
$this->application->docker_compose_domains = json_encode($this->parsedServiceDomains);
$originalDomains = $this->composeDomainsForStorage();
$this->application->docker_compose_domains = json_encode($originalDomains);
if ($this->application->isDirty('docker_compose_domains')) {
foreach ($this->parsedServiceDomains as $service) {
foreach ($originalDomains as $service) {
$domain = data_get($service, 'domain');
if ($domain) {
if (! validateDNSEntry($domain, $this->application->destination->server)) {
@@ -985,4 +968,58 @@ class General extends Component
'{workdir}/.env'
);
}
private function composeDomainsForStorage(): array
{
return rekeyComposeDomainsToServiceNames(
$this->parsedServiceDomains,
collect(data_get($this->parsedServices, 'services', []))->keys(),
);
}
/**
* Collapse domain map keys to underscore form keys for Livewire/HTML binding.
* When twin keys exist, prefer a filled domain over a blank one.
*
* @param array<string, mixed> $domains
* @return array<string, mixed>
*/
private function sanitizeParsedServiceDomainsForForm(array $domains): array
{
$sanitizedDomains = [];
foreach ($domains as $serviceName => $domain) {
$sanitizedKey = normalizeComposeServiceName((string) $serviceName);
if (! array_key_exists($sanitizedKey, $sanitizedDomains)) {
$sanitizedDomains[$sanitizedKey] = $domain;
continue;
}
$existing = $sanitizedDomains[$sanitizedKey];
if (is_object($existing)) {
$existing = (array) $existing;
}
if (is_object($domain)) {
$domain = (array) $domain;
}
if (! is_array($existing)) {
$existing = ['domain' => $existing];
}
if (! is_array($domain)) {
$domain = ['domain' => $domain];
}
$merged = array_merge($existing, $domain);
$merged['domain'] = preferComposeDomainValue(
$existing['domain'] ?? null,
false,
$domain['domain'] ?? null,
false,
);
$sanitizedDomains[$sanitizedKey] = $merged;
}
return $sanitizedDomains;
}
}