Merge branch 'next' into hotfix

This commit is contained in:
Andras Bacsai
2025-01-10 20:23:29 +01:00
committed by GitHub
302 changed files with 57260 additions and 2156 deletions

View File

@@ -166,6 +166,7 @@ function removeUnnecessaryFieldsFromRequest(Request $request)
{
$request->offsetUnset('project_uuid');
$request->offsetUnset('environment_name');
$request->offsetUnset('environment_uuid');
$request->offsetUnset('destination_uuid');
$request->offsetUnset('server_uuid');
$request->offsetUnset('type');

View File

@@ -188,7 +188,22 @@ function get_port_from_dockerfile($dockerfile): ?int
return null;
}
function defaultLabels($id, $name, $pull_request_id = 0, string $type = 'application', $subType = null, $subId = null)
function defaultDatabaseLabels($database)
{
$labels = collect([]);
$labels->push('coolify.managed=true');
$labels->push('coolify.type=database');
$labels->push('coolify.databaseId='.$database->id);
$labels->push('coolify.resourceName='.Str::slug($database->name));
$labels->push('coolify.serviceName='.Str::slug($database->name));
$labels->push('coolify.projectName='.Str::slug($database->project()->name));
$labels->push('coolify.environmentName='.Str::slug($database->environment->name));
$labels->push('coolify.database.subType='.$database->type());
return $labels;
}
function defaultLabels($id, $name, string $projectName, string $resourceName, string $environment, $pull_request_id = 0, string $type = 'application', $subType = null, $subId = null, $subName = null)
{
$labels = collect([]);
$labels->push('coolify.managed=true');
@@ -196,14 +211,21 @@ function defaultLabels($id, $name, $pull_request_id = 0, string $type = 'applica
$labels->push('coolify.'.$type.'Id='.$id);
$labels->push("coolify.type=$type");
$labels->push('coolify.name='.$name);
$labels->push('coolify.resourceName='.Str::slug($resourceName));
$labels->push('coolify.projectName='.Str::slug($projectName));
$labels->push('coolify.serviceName='.Str::slug($subName ?? $resourceName));
$labels->push('coolify.environmentName='.Str::slug($environment));
$labels->push('coolify.pullRequestId='.$pull_request_id);
if ($type === 'service') {
$subId && $labels->push('coolify.service.subId='.$subId);
$subType && $labels->push('coolify.service.subType='.$subType);
$subName && $labels->push('coolify.service.subName='.Str::slug($subName));
}
return $labels;
}
function generateServiceSpecificFqdns(ServiceApplication|Application $resource)
{
if ($resource->getMorphClass() === \App\Models\ServiceApplication::class) {

View File

@@ -2,6 +2,7 @@
use App\Models\Application;
use App\Models\EnvironmentVariable;
use App\Models\Service;
use App\Models\ServiceApplication;
use App\Models\ServiceDatabase;
use Illuminate\Support\Stringable;
@@ -119,7 +120,10 @@ function updateCompose(ServiceApplication|ServiceDatabase $resource)
if ($resourceFqdns->count() === 1) {
$resourceFqdns = $resourceFqdns->first();
$variableName = 'SERVICE_FQDN_'.str($resource->name)->upper()->replace('-', '');
$generatedEnv = EnvironmentVariable::where('service_id', $resource->service_id)->where('key', $variableName)->first();
$generatedEnv = EnvironmentVariable::where('resourceable_type', Service::class)
->where('resourceable_id', $resource->service_id)
->where('key', $variableName)
->first();
$fqdn = Url::fromString($resourceFqdns);
$port = $fqdn->getPort();
$path = $fqdn->getPath();
@@ -134,7 +138,10 @@ function updateCompose(ServiceApplication|ServiceDatabase $resource)
}
if ($port) {
$variableName = $variableName."_$port";
$generatedEnv = EnvironmentVariable::where('service_id', $resource->service_id)->where('key', $variableName)->first();
$generatedEnv = EnvironmentVariable::where('resourceable_type', Service::class)
->where('resourceable_id', $resource->service_id)
->where('key', $variableName)
->first();
if ($generatedEnv) {
if ($path === '/') {
$generatedEnv->value = $fqdn;
@@ -145,7 +152,10 @@ function updateCompose(ServiceApplication|ServiceDatabase $resource)
}
}
$variableName = 'SERVICE_URL_'.str($resource->name)->upper()->replace('-', '');
$generatedEnv = EnvironmentVariable::where('service_id', $resource->service_id)->where('key', $variableName)->first();
$generatedEnv = EnvironmentVariable::where('resourceable_type', Service::class)
->where('resourceable_id', $resource->service_id)
->where('key', $variableName)
->first();
$url = Url::fromString($fqdn);
$port = $url->getPort();
$path = $url->getPath();
@@ -161,7 +171,10 @@ function updateCompose(ServiceApplication|ServiceDatabase $resource)
}
if ($port) {
$variableName = $variableName."_$port";
$generatedEnv = EnvironmentVariable::where('service_id', $resource->service_id)->where('key', $variableName)->first();
$generatedEnv = EnvironmentVariable::where('resourceable_type', Service::class)
->where('resourceable_id', $resource->service_id)
->where('key', $variableName)
->first();
if ($generatedEnv) {
if ($path === '/') {
$generatedEnv->value = $url;
@@ -179,10 +192,16 @@ function updateCompose(ServiceApplication|ServiceDatabase $resource)
$path = $host->getPath();
$host = $host->getScheme().'://'.$host->getHost();
if ($port) {
$port_envs = EnvironmentVariable::where('service_id', $resource->service_id)->where('key', 'like', "SERVICE_FQDN_%_$port")->get();
$port_envs = EnvironmentVariable::where('resourceable_type', Service::class)
->where('resourceable_id', $resource->service_id)
->where('key', 'like', "SERVICE_FQDN_%_$port")
->get();
foreach ($port_envs as $port_env) {
$service_fqdn = str($port_env->key)->beforeLast('_')->after('SERVICE_FQDN_');
$env = EnvironmentVariable::where('service_id', $resource->service_id)->where('key', 'SERVICE_FQDN_'.$service_fqdn)->first();
$env = EnvironmentVariable::where('resourceable_type', Service::class)
->where('resourceable_id', $resource->service_id)
->where('key', 'SERVICE_FQDN_'.$service_fqdn)
->first();
if ($env) {
if ($path === '/') {
$env->value = $host;
@@ -198,10 +217,16 @@ function updateCompose(ServiceApplication|ServiceDatabase $resource)
}
$port_env->save();
}
$port_envs_url = EnvironmentVariable::where('service_id', $resource->service_id)->where('key', 'like', "SERVICE_URL_%_$port")->get();
$port_envs_url = EnvironmentVariable::where('resourceable_type', Service::class)
->where('resourceable_id', $resource->service_id)
->where('key', 'like', "SERVICE_URL_%_$port")
->get();
foreach ($port_envs_url as $port_env_url) {
$service_url = str($port_env_url->key)->beforeLast('_')->after('SERVICE_URL_');
$env = EnvironmentVariable::where('service_id', $resource->service_id)->where('key', 'SERVICE_URL_'.$service_url)->first();
$env = EnvironmentVariable::where('resourceable_type', Service::class)
->where('resourceable_id', $resource->service_id)
->where('key', 'SERVICE_URL_'.$service_url)
->first();
if ($env) {
if ($path === '/') {
$env->value = $url;
@@ -219,7 +244,10 @@ function updateCompose(ServiceApplication|ServiceDatabase $resource)
}
} else {
$variableName = 'SERVICE_FQDN_'.str($resource->name)->upper()->replace('-', '');
$generatedEnv = EnvironmentVariable::where('service_id', $resource->service_id)->where('key', $variableName)->first();
$generatedEnv = EnvironmentVariable::where('resourceable_type', Service::class)
->where('resourceable_id', $resource->service_id)
->where('key', $variableName)
->first();
$fqdn = Url::fromString($fqdn);
$fqdn = $fqdn->getScheme().'://'.$fqdn->getHost().$fqdn->getPath();
if ($generatedEnv) {
@@ -227,7 +255,10 @@ function updateCompose(ServiceApplication|ServiceDatabase $resource)
$generatedEnv->save();
}
$variableName = 'SERVICE_URL_'.str($resource->name)->upper()->replace('-', '');
$generatedEnv = EnvironmentVariable::where('service_id', $resource->service_id)->where('key', $variableName)->first();
$generatedEnv = EnvironmentVariable::where('resourceable_type', Service::class)
->where('resourceable_id', $resource->service_id)
->where('key', $variableName)
->first();
$url = Url::fromString($fqdn);
$url = $url->getHost().$url->getPath();
if ($generatedEnv) {

View File

@@ -1828,7 +1828,8 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
'key' => $key,
'value' => $fqdn,
'is_build_time' => false,
'service_id' => $resource->id,
'resourceable_type' => get_class($resource),
'resourceable_id' => $resource->id,
'is_preview' => false,
]);
}
@@ -1840,7 +1841,8 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
}
$env = EnvironmentVariable::where([
'key' => $key,
'service_id' => $resource->id,
'resourceable_type' => get_class($resource),
'resourceable_id' => $resource->id,
])->first();
if ($env) {
$env_url = Url::fromString($savedService->fqdn);
@@ -1863,14 +1865,16 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
if ($value?->startsWith('$')) {
$foundEnv = EnvironmentVariable::where([
'key' => $key,
'service_id' => $resource->id,
'resourceable_type' => get_class($resource),
'resourceable_id' => $resource->id,
])->first();
$value = replaceVariables($value);
$key = $value;
if ($value->startsWith('SERVICE_')) {
$foundEnv = EnvironmentVariable::where([
'key' => $key,
'service_id' => $resource->id,
'resourceable_type' => get_class($resource),
'resourceable_id' => $resource->id,
])->first();
['command' => $command, 'forService' => $forService, 'generatedValue' => $generatedValue, 'port' => $port] = parseEnvVariable($value);
if (! is_null($command)) {
@@ -1904,7 +1908,8 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
'key' => $key,
'value' => $fqdn,
'is_build_time' => false,
'service_id' => $resource->id,
'resourceable_type' => get_class($resource),
'resourceable_id' => $resource->id,
'is_preview' => false,
]);
}
@@ -1921,7 +1926,8 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
}
$env = EnvironmentVariable::where([
'key' => $key,
'service_id' => $resource->id,
'resourceable_type' => get_class($resource),
'resourceable_id' => $resource->id,
])->first();
if ($env) {
$env_url = Url::fromString($env->value);
@@ -1941,7 +1947,8 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
'key' => $key,
'value' => $generatedValue,
'is_build_time' => false,
'service_id' => $resource->id,
'resourceable_type' => get_class($resource),
'resourceable_id' => $resource->id,
'is_preview' => false,
]);
}
@@ -1966,18 +1973,21 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
}
$foundEnv = EnvironmentVariable::where([
'key' => $key,
'service_id' => $resource->id,
'resourceable_type' => get_class($resource),
'resourceable_id' => $resource->id,
])->first();
if ($foundEnv) {
$defaultValue = data_get($foundEnv, 'value');
}
EnvironmentVariable::updateOrCreate([
'key' => $key,
'service_id' => $resource->id,
'resourceable_type' => get_class($resource),
'resourceable_id' => $resource->id,
], [
'value' => $defaultValue,
'is_build_time' => false,
'service_id' => $resource->id,
'resourceable_type' => get_class($resource),
'resourceable_id' => $resource->id,
'is_preview' => false,
]);
}
@@ -1989,7 +1999,17 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
} else {
$fqdns = collect(data_get($savedService, 'fqdns'))->filter();
}
$defaultLabels = defaultLabels($resource->id, $containerName, type: 'service', subType: $isDatabase ? 'database' : 'application', subId: $savedService->id);
$defaultLabels = defaultLabels(
id: $resource->id,
name: $containerName,
projectName: $resource->project()->name,
resourceName: $resource->name,
type: 'service',
subType: $isDatabase ? 'database' : 'application',
subId: $savedService->id,
subName: $savedService->name,
environment: $resource->environment->name,
);
$serviceLabels = $serviceLabels->merge($defaultLabels);
if (! $isDatabase && $fqdns->count() > 0) {
if ($fqdns) {
@@ -2817,7 +2837,16 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
}
}
}
$defaultLabels = defaultLabels($resource->id, $containerName, $pull_request_id, type: 'application');
$defaultLabels = defaultLabels(
id: $resource->id,
name: $containerName,
projectName: $resource->project()->name,
resourceName: $resource->name,
environment: $resource->environment->name,
pull_request_id: $pull_request_id,
type: 'application'
);
$serviceLabels = $serviceLabels->merge($defaultLabels);
if ($server->isLogDrainEnabled()) {
@@ -2840,6 +2869,10 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
data_set($service, 'container_name', $containerName);
data_forget($service, 'volumes.*.content');
data_forget($service, 'volumes.*.isDirectory');
data_forget($service, 'volumes.*.is_directory');
data_forget($service, 'exclude_from_hc');
data_set($service, 'environment', $serviceVariables->toArray());
updateCompose($savedService);
return $service;
});
@@ -2878,13 +2911,11 @@ function newParser(Application|Service $resource, int $pull_request_id = 0, ?int
}
if ($isApplication) {
$nameOfId = 'application_id';
$pullRequestId = $pull_request_id;
$isPullRequest = $pullRequestId == 0 ? false : true;
$server = data_get($resource, 'destination.server');
$fileStorages = $resource->fileStorages();
} elseif ($isService) {
$nameOfId = 'service_id';
$server = data_get($resource, 'server');
$allServices = get_service_templates();
} else {
@@ -3051,9 +3082,10 @@ function newParser(Application|Service $resource, int $pull_request_id = 0, ?int
}
if (substr_count(str($key)->value(), '_') === 2) {
$resource->environment_variables()->where('key', $key->value())->where($nameOfId, $resource->id)->firstOrCreate([
$resource->environment_variables()->firstOrCreate([
'key' => $key->value(),
$nameOfId => $resource->id,
'resourceable_type' => get_class($resource),
'resourceable_id' => $resource->id,
], [
'value' => $fqdn,
'is_build_time' => false,
@@ -3062,9 +3094,10 @@ function newParser(Application|Service $resource, int $pull_request_id = 0, ?int
}
if (substr_count(str($key)->value(), '_') === 3) {
$newKey = str($key)->beforeLast('_');
$resource->environment_variables()->where('key', $newKey->value())->where($nameOfId, $resource->id)->firstOrCreate([
$resource->environment_variables()->firstOrCreate([
'key' => $newKey->value(),
$nameOfId => $resource->id,
'resourceable_type' => get_class($resource),
'resourceable_id' => $resource->id,
], [
'value' => $fqdn,
'is_build_time' => false,
@@ -3080,7 +3113,7 @@ function newParser(Application|Service $resource, int $pull_request_id = 0, ?int
$key = str($key);
$value = replaceVariables($value);
$command = parseCommandFromMagicEnvVariable($key);
$found = $resource->environment_variables()->where('key', $key->value())->where($nameOfId, $resource->id)->first();
$found = $resource->environment_variables()->where('key', $key->value())->where('resourceable_type', get_class($resource))->where('resourceable_id', $resource->id)->first();
if ($found) {
continue;
}
@@ -3094,9 +3127,10 @@ function newParser(Application|Service $resource, int $pull_request_id = 0, ?int
} elseif ($isService) {
$fqdn = generateFqdn($server, "$fqdnFor-$uuid");
}
$resource->environment_variables()->where('key', $key->value())->where($nameOfId, $resource->id)->firstOrCreate([
$resource->environment_variables()->firstOrCreate([
'key' => $key->value(),
$nameOfId => $resource->id,
'resourceable_type' => get_class($resource),
'resourceable_id' => $resource->id,
], [
'value' => $fqdn,
'is_build_time' => false,
@@ -3113,9 +3147,10 @@ function newParser(Application|Service $resource, int $pull_request_id = 0, ?int
$fqdn = generateFqdn($server, "$fqdnFor-$uuid");
}
$fqdn = str($fqdn)->replace('http://', '')->replace('https://', '');
$resource->environment_variables()->where('key', $key->value())->where($nameOfId, $resource->id)->firstOrCreate([
$resource->environment_variables()->firstOrCreate([
'key' => $key->value(),
$nameOfId => $resource->id,
'resourceable_type' => get_class($resource),
'resourceable_id' => $resource->id,
], [
'value' => $fqdn,
'is_build_time' => false,
@@ -3123,9 +3158,10 @@ function newParser(Application|Service $resource, int $pull_request_id = 0, ?int
]);
} else {
$value = generateEnvValue($command, $resource);
$resource->environment_variables()->where('key', $key->value())->where($nameOfId, $resource->id)->firstOrCreate([
$resource->environment_variables()->firstOrCreate([
'key' => $key->value(),
$nameOfId => $resource->id,
'resourceable_type' => get_class($resource),
'resourceable_id' => $resource->id,
], [
'value' => $value,
'is_build_time' => false,
@@ -3473,9 +3509,10 @@ function newParser(Application|Service $resource, int $pull_request_id = 0, ?int
$originalValue = $value;
$parsedValue = replaceVariables($value);
if ($value->startsWith('$SERVICE_')) {
$resource->environment_variables()->where('key', $key)->where($nameOfId, $resource->id)->firstOrCreate([
$resource->environment_variables()->firstOrCreate([
'key' => $key,
$nameOfId => $resource->id,
'resourceable_type' => get_class($resource),
'resourceable_id' => $resource->id,
], [
'value' => $value,
'is_build_time' => false,
@@ -3489,9 +3526,10 @@ function newParser(Application|Service $resource, int $pull_request_id = 0, ?int
}
if ($key->value() === $parsedValue->value()) {
$value = null;
$resource->environment_variables()->where('key', $key)->where($nameOfId, $resource->id)->firstOrCreate([
$resource->environment_variables()->firstOrCreate([
'key' => $key,
$nameOfId => $resource->id,
'resourceable_type' => get_class($resource),
'resourceable_id' => $resource->id,
], [
'value' => $value,
'is_build_time' => false,
@@ -3525,22 +3563,24 @@ function newParser(Application|Service $resource, int $pull_request_id = 0, ?int
if ($originalValue->value() === $value->value()) {
// This means the variable does not have a default value, so it needs to be created in Coolify
$parsedKeyValue = replaceVariables($value);
$resource->environment_variables()->where('key', $parsedKeyValue)->where($nameOfId, $resource->id)->firstOrCreate([
$resource->environment_variables()->firstOrCreate([
'key' => $parsedKeyValue,
$nameOfId => $resource->id,
'resourceable_type' => get_class($resource),
'resourceable_id' => $resource->id,
], [
'is_build_time' => false,
'is_preview' => false,
'is_required' => $isRequired,
]);
// Add the variable to the environment so it will be shown in the deployable compose file
$environment[$parsedKeyValue->value()] = $resource->environment_variables()->where('key', $parsedKeyValue)->where($nameOfId, $resource->id)->first()->value;
$environment[$parsedKeyValue->value()] = $resource->environment_variables()->where('key', $parsedKeyValue)->where('resourceable_type', get_class($resource))->where('resourceable_id', $resource->id)->first()->value;
continue;
}
$resource->environment_variables()->where('key', $key)->where($nameOfId, $resource->id)->firstOrCreate([
$resource->environment_variables()->firstOrCreate([
'key' => $key,
$nameOfId => $resource->id,
'resourceable_type' => get_class($resource),
'resourceable_id' => $resource->id,
], [
'value' => $value,
'is_build_time' => false,
@@ -3600,11 +3640,15 @@ function newParser(Application|Service $resource, int $pull_request_id = 0, ?int
}
}
}
$defaultLabels = defaultLabels(
id: $resource->id,
name: $containerName,
projectName: $resource->project()->name,
resourceName: $resource->name,
pull_request_id: $pullRequestId,
type: 'application'
type: 'application',
environment: $resource->environment->name,
);
} elseif ($isService) {
if ($savedService->serviceType()) {
@@ -3612,7 +3656,18 @@ function newParser(Application|Service $resource, int $pull_request_id = 0, ?int
} else {
$fqdns = collect(data_get($savedService, 'fqdns'))->filter();
}
$defaultLabels = defaultLabels($resource->id, $containerName, type: 'service', subType: $isDatabase ? 'database' : 'application', subId: $savedService->id);
$defaultLabels = defaultLabels(
id: $resource->id,
name: $containerName,
projectName: $resource->project()->name,
resourceName: $resource->name,
type: 'service',
subType: $isDatabase ? 'database' : 'application',
subId: $savedService->id,
subName: $savedService->human_name ?? $savedService->name,
environment: $resource->environment->name,
);
}
// Add COOLIFY_FQDN & COOLIFY_URL to environment
if (! $isDatabase && $fqdns instanceof Collection && $fqdns->count() > 0) {

View File

@@ -40,6 +40,7 @@ function get_socialite_provider(string $provider)
'github' => \Laravel\Socialite\Two\GithubProvider::class,
'gitlab' => \Laravel\Socialite\Two\GitlabProvider::class,
'google' => \Laravel\Socialite\Two\GoogleProvider::class,
'infomaniak' => \SocialiteProviders\Infomaniak\Provider::class,
];
return Socialite::buildProvider(

View File

@@ -69,6 +69,7 @@ function allowedPathsForUnsubscribedAccounts()
'logout',
'force-password-reset',
'livewire/update',
'admin',
];
}
function allowedPathsForBoardingAccounts()