fix(domains): preserve removed compose service domains

This commit is contained in:
Andras Bacsai
2026-09-04 16:47:12 +02:00
parent a04c2ecb44
commit 851a902346
3 changed files with 49 additions and 5 deletions
+20
View File
@@ -443,6 +443,26 @@ function getComposeServiceDomainString(array|Collection $domains, string $servic
return $matches[0]['domain'];
}
/**
* Determine whether a compose service already has a domain-map entry, including
* an explicitly empty entry left when a user removes its generated domain.
*
* @param array<string, mixed>|Collection<string, mixed> $domains
*/
function hasComposeServiceDomainEntry(array|Collection $domains, string $serviceName): bool
{
$normalized = normalizeComposeServiceName($serviceName);
foreach (collect($domains)->keys() as $key) {
$key = (string) $key;
if ($key === $serviceName || normalizeComposeServiceName($key) === $normalized) {
return true;
}
}
return false;
}
function composeDomainEntryString(mixed $entry): ?string
{
if (is_object($entry)) {
+2 -5
View File
@@ -525,8 +525,7 @@ function applicationParser(Application $resource, int $pull_request_id = 0, ?int
$originalServiceName = findComposeServiceName($normalizedServiceName, array_keys($services));
if ($originalServiceName !== null) {
$domains = json_decode(data_get($resource, 'docker_compose_domains') ?: '[]', true) ?: [];
$domainExists = getComposeServiceDomainString($domains, $originalServiceName);
if (is_null($domainExists)) {
if (! hasComposeServiceDomainEntry($domains, $originalServiceName)) {
$serviceNameForDomain = str($parsed['service_name'])->replace('_', '-')->value();
$domainValue = generateUrl(server: $server, random: "$serviceNameForDomain-$uuid");
if ($value && get_class($value) === Stringable::class && $value->startsWith('/')) {
@@ -648,12 +647,10 @@ function applicationParser(Application $resource, int $pull_request_id = 0, ?int
// Only add domain if the service exists
if ($composeServiceName !== null) {
$domains = json_decode(data_get($resource, 'docker_compose_domains') ?: '[]', true) ?: [];
$domainExists = getComposeServiceDomainString($domains, $composeServiceName);
// Update domain using URL with port if applicable
$domainValue = $port ? $urlWithPort : $url;
if (is_null($domainExists)) {
if (! hasComposeServiceDomainEntry($domains, $composeServiceName)) {
$resource->docker_compose_domains = json_encode(putComposeServiceDomain(
$domains,
$composeServiceName,
+27
View File
@@ -111,6 +111,33 @@ it('does not add a single-label hostname as an application domain', function ()
expect($this->application->fresh()->fqdn)->toBeNull();
});
it('keeps a compose domain removed when the service declares a magic URL variable', function () {
$this->application->update([
'build_pack' => 'dockercompose',
'docker_compose_raw' => <<<'YAML'
services:
web:
image: nginx:alpine
environment:
SERVICE_URL_WEB: /api
YAML,
'docker_compose_domains' => json_encode([
'web' => ['domain' => 'https://web.example.com/api'],
]),
]);
$component = Livewire::test(Domains::class, ['application' => $this->application->fresh()]);
$domainKey = hash('sha256', 'https://web.example.com/api|web');
$component
->call('removeDomainByKey', $domainKey)
->assertDispatched('success')
->assertSet('domainRows', []);
expect(json_decode($this->application->fresh()->docker_compose_domains, true))
->toMatchArray(['web' => ['domain' => null]]);
});
it('generates a preview domain when the application has no domain', function () {
$preview = ApplicationPreview::create([
'application_id' => $this->application->id,