fix(parser): populate compose domains from service env keys
This commit is contained in:
parent
e551f9c176
commit
eddcbe819b
2 changed files with 175 additions and 18 deletions
|
|
@ -502,25 +502,37 @@ function applicationParser(Application $resource, int $pull_request_id = 0, ?int
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Also populate docker_compose_domains for dockercompose apps (mirrors Path 1 at lines 601-627)
|
}
|
||||||
if ($resource->build_pack === 'dockercompose') {
|
|
||||||
$normalizedFqdnFor = str($fqdnFor)->replace('-', '_')->replace('.', '_')->value();
|
// Also populate docker_compose_domains for dockercompose apps from direct SERVICE_* declarations.
|
||||||
$serviceExists = false;
|
if ($resource->build_pack === 'dockercompose' && ($key->startsWith('SERVICE_FQDN_') || $key->startsWith('SERVICE_URL_'))) {
|
||||||
foreach (array_keys($services) as $serviceNameKey) {
|
$parsed = parseServiceEnvironmentVariable($key->value());
|
||||||
if (str($serviceNameKey)->replace('-', '_')->replace('.', '_')->value() === $normalizedFqdnFor) {
|
$normalizedServiceName = str($parsed['service_name'])->replace('-', '_')->replace('.', '_')->value();
|
||||||
$serviceExists = true;
|
$serviceExists = false;
|
||||||
break;
|
foreach (array_keys($services) as $serviceNameKey) {
|
||||||
}
|
if (str($serviceNameKey)->replace('-', '_')->replace('.', '_')->value() === $normalizedServiceName) {
|
||||||
|
$serviceExists = true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if ($serviceExists) {
|
}
|
||||||
$domains = collect(json_decode(data_get($resource, 'docker_compose_domains'))) ?? collect([]);
|
if ($serviceExists) {
|
||||||
$domainExists = data_get($domains->get($normalizedFqdnFor), 'domain');
|
$domains = collect(json_decode(data_get($resource, 'docker_compose_domains') ?: '[]'));
|
||||||
if (is_null($domainExists)) {
|
$domainExists = data_get($domains->get($normalizedServiceName), 'domain');
|
||||||
$domainValue = $fqdn;
|
if (is_null($domainExists)) {
|
||||||
$domains->put($normalizedFqdnFor, ['domain' => $domainValue]);
|
$serviceNameForDomain = str($parsed['service_name'])->replace('_', '-')->value();
|
||||||
$resource->docker_compose_domains = $domains->toJson();
|
$domainValue = generateUrl(server: $server, random: "$serviceNameForDomain-$uuid");
|
||||||
$resource->save();
|
if ($value && get_class($value) === Illuminate\Support\Stringable::class && $value->startsWith('/')) {
|
||||||
|
$path = $value->value();
|
||||||
|
if ($path !== '/') {
|
||||||
|
$domainValue = "$domainValue$path";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
if ($parsed['port'] && is_numeric($parsed['port'])) {
|
||||||
|
$domainValue = "$domainValue:{$parsed['port']}";
|
||||||
|
}
|
||||||
|
$domains->put($normalizedServiceName, ['domain' => $domainValue]);
|
||||||
|
$resource->docker_compose_domains = $domains->toJson();
|
||||||
|
$resource->save();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -630,7 +642,7 @@ function applicationParser(Application $resource, int $pull_request_id = 0, ?int
|
||||||
|
|
||||||
// Only add domain if the service exists
|
// Only add domain if the service exists
|
||||||
if ($serviceExists) {
|
if ($serviceExists) {
|
||||||
$domains = collect(json_decode(data_get($resource, 'docker_compose_domains'))) ?? collect([]);
|
$domains = collect(json_decode(data_get($resource, 'docker_compose_domains') ?: '[]'));
|
||||||
$domainExists = data_get($domains->get($serviceName), 'domain');
|
$domainExists = data_get($domains->get($serviceName), 'domain');
|
||||||
|
|
||||||
// Update domain using URL with port if applicable
|
// Update domain using URL with port if applicable
|
||||||
|
|
|
||||||
|
|
@ -82,6 +82,7 @@
|
||||||
->and($domains)->toBeArray()
|
->and($domains)->toBeArray()
|
||||||
->and($domains)->toHaveKey('backend')
|
->and($domains)->toHaveKey('backend')
|
||||||
->and($domains['backend'])->toHaveKey('domain')
|
->and($domains['backend'])->toHaveKey('domain')
|
||||||
|
->and($domains['backend']['domain'])->toStartWith('http://')
|
||||||
->and($domains['backend']['domain'])->not->toBeEmpty();
|
->and($domains['backend']['domain'])->not->toBeEmpty();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -142,3 +143,147 @@
|
||||||
$domains = json_decode($application->docker_compose_domains, true);
|
$domains = json_decode($application->docker_compose_domains, true);
|
||||||
expect($domains)->toBeNull();
|
expect($domains)->toBeNull();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('applicationParser populates docker_compose_domains for KEY-based SERVICE_URL variables', function () {
|
||||||
|
$dockerCompose = <<<'YAML'
|
||||||
|
services:
|
||||||
|
frontend:
|
||||||
|
image: myapp/frontend:latest
|
||||||
|
environment:
|
||||||
|
- SERVICE_URL_FRONTEND=/ui
|
||||||
|
YAML;
|
||||||
|
|
||||||
|
$application = Application::factory()->create([
|
||||||
|
'environment_id' => $this->environment->id,
|
||||||
|
'destination_id' => $this->destination->id,
|
||||||
|
'destination_type' => StandaloneDocker::class,
|
||||||
|
'build_pack' => 'dockercompose',
|
||||||
|
'docker_compose_raw' => $dockerCompose,
|
||||||
|
'fqdn' => null,
|
||||||
|
'docker_compose_domains' => null,
|
||||||
|
]);
|
||||||
|
|
||||||
|
applicationParser($application);
|
||||||
|
|
||||||
|
$application->refresh();
|
||||||
|
|
||||||
|
$domains = json_decode($application->docker_compose_domains, true);
|
||||||
|
|
||||||
|
expect($domains)->not->toBeNull()
|
||||||
|
->and($domains)->toHaveKey('frontend')
|
||||||
|
->and($domains['frontend']['domain'])->toStartWith('http://')
|
||||||
|
->and($domains['frontend']['domain'])->toEndWith('/ui');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('applicationParser preserves existing docker_compose_domains entries', function () {
|
||||||
|
$dockerCompose = <<<'YAML'
|
||||||
|
services:
|
||||||
|
backend:
|
||||||
|
image: myapp/backend:latest
|
||||||
|
environment:
|
||||||
|
- SERVICE_FQDN_BACKEND_8000=${BACKEND_URL}
|
||||||
|
frontend:
|
||||||
|
image: myapp/frontend:latest
|
||||||
|
environment:
|
||||||
|
- SERVICE_URL_FRONTEND=/ui
|
||||||
|
YAML;
|
||||||
|
|
||||||
|
$application = Application::factory()->create([
|
||||||
|
'environment_id' => $this->environment->id,
|
||||||
|
'destination_id' => $this->destination->id,
|
||||||
|
'destination_type' => StandaloneDocker::class,
|
||||||
|
'build_pack' => 'dockercompose',
|
||||||
|
'docker_compose_raw' => $dockerCompose,
|
||||||
|
'fqdn' => null,
|
||||||
|
'docker_compose_domains' => json_encode([
|
||||||
|
'frontend' => ['domain' => 'https://existing.example.com'],
|
||||||
|
]),
|
||||||
|
]);
|
||||||
|
|
||||||
|
applicationParser($application);
|
||||||
|
|
||||||
|
$application->refresh();
|
||||||
|
|
||||||
|
$domains = json_decode($application->docker_compose_domains, true);
|
||||||
|
|
||||||
|
expect($domains['frontend']['domain'])->toBe('https://existing.example.com')
|
||||||
|
->and($domains)->toHaveKey('backend')
|
||||||
|
->and($domains['backend']['domain'])->toStartWith('http://');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('applicationParser handles other docker compose domain shapes without regressions', function () {
|
||||||
|
$createApplication = function (string $dockerCompose, ?string $dockerComposeDomains = null): Application {
|
||||||
|
return Application::factory()->create([
|
||||||
|
'environment_id' => $this->environment->id,
|
||||||
|
'destination_id' => $this->destination->id,
|
||||||
|
'destination_type' => StandaloneDocker::class,
|
||||||
|
'build_pack' => 'dockercompose',
|
||||||
|
'docker_compose_raw' => $dockerCompose,
|
||||||
|
'fqdn' => null,
|
||||||
|
'docker_compose_domains' => $dockerComposeDomains,
|
||||||
|
]);
|
||||||
|
};
|
||||||
|
|
||||||
|
$valueBasedCompose = <<<'YAML'
|
||||||
|
services:
|
||||||
|
backend:
|
||||||
|
image: myapp/backend:latest
|
||||||
|
frontend:
|
||||||
|
image: myapp/frontend:latest
|
||||||
|
environment:
|
||||||
|
API_URL: ${SERVICE_URL_BACKEND}
|
||||||
|
YAML;
|
||||||
|
|
||||||
|
$valueBasedApplication = $createApplication($valueBasedCompose);
|
||||||
|
applicationParser($valueBasedApplication);
|
||||||
|
$valueBasedApplication->refresh();
|
||||||
|
$valueBasedDomains = json_decode($valueBasedApplication->docker_compose_domains, true);
|
||||||
|
|
||||||
|
expect($valueBasedDomains)->toHaveKey('backend')
|
||||||
|
->and($valueBasedDomains['backend']['domain'])->toStartWith('http://')
|
||||||
|
->and($valueBasedDomains)->not->toHaveKey('frontend');
|
||||||
|
|
||||||
|
$mapStyleCompose = <<<'YAML'
|
||||||
|
services:
|
||||||
|
frontend:
|
||||||
|
image: myapp/frontend:latest
|
||||||
|
environment:
|
||||||
|
SERVICE_URL_FRONTEND: /ui
|
||||||
|
YAML;
|
||||||
|
|
||||||
|
$mapStyleApplication = $createApplication($mapStyleCompose);
|
||||||
|
applicationParser($mapStyleApplication);
|
||||||
|
$mapStyleApplication->refresh();
|
||||||
|
$mapStyleDomains = json_decode($mapStyleApplication->docker_compose_domains, true);
|
||||||
|
|
||||||
|
expect($mapStyleDomains)->toHaveKey('frontend')
|
||||||
|
->and($mapStyleDomains['frontend']['domain'])->toEndWith('/ui');
|
||||||
|
|
||||||
|
$missingServiceCompose = <<<'YAML'
|
||||||
|
services:
|
||||||
|
worker:
|
||||||
|
image: myapp/worker:latest
|
||||||
|
environment:
|
||||||
|
SERVICE_URL_API: /api
|
||||||
|
YAML;
|
||||||
|
|
||||||
|
$missingServiceApplication = $createApplication($missingServiceCompose);
|
||||||
|
applicationParser($missingServiceApplication);
|
||||||
|
$missingServiceApplication->refresh();
|
||||||
|
|
||||||
|
expect(json_decode($missingServiceApplication->docker_compose_domains, true))->toBeNull();
|
||||||
|
|
||||||
|
$plainCompose = <<<'YAML'
|
||||||
|
services:
|
||||||
|
worker:
|
||||||
|
image: myapp/worker:latest
|
||||||
|
environment:
|
||||||
|
FOO: bar
|
||||||
|
YAML;
|
||||||
|
|
||||||
|
$plainApplication = $createApplication($plainCompose);
|
||||||
|
applicationParser($plainApplication);
|
||||||
|
$plainApplication->refresh();
|
||||||
|
|
||||||
|
expect(json_decode($plainApplication->docker_compose_domains, true))->toBeNull();
|
||||||
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue