Merge branch 'next' into feat/deployment-token

This commit is contained in:
Andras Bacsai
2024-12-09 09:16:59 +01:00
449 changed files with 21219 additions and 5891 deletions

View File

@@ -70,7 +70,8 @@ class ApplicationsController extends Controller
items: new OA\Items(ref: '#/components/schemas/Application')
)
),
]),
]
),
new OA\Response(
response: 401,
ref: '#/components/responses/401',
@@ -180,8 +181,10 @@ class ApplicationsController extends Controller
'watch_paths' => ['type' => 'string', 'description' => 'The watch paths.'],
'use_build_server' => ['type' => 'boolean', 'nullable' => true, 'description' => 'Use build server.'],
],
)),
]),
)
),
]
),
responses: [
new OA\Response(
response: 200,
@@ -284,8 +287,10 @@ class ApplicationsController extends Controller
'watch_paths' => ['type' => 'string', 'description' => 'The watch paths.'],
'use_build_server' => ['type' => 'boolean', 'nullable' => true, 'description' => 'Use build server.'],
],
)),
]),
)
),
]
),
responses: [
new OA\Response(
response: 200,
@@ -388,8 +393,10 @@ class ApplicationsController extends Controller
'watch_paths' => ['type' => 'string', 'description' => 'The watch paths.'],
'use_build_server' => ['type' => 'boolean', 'nullable' => true, 'description' => 'Use build server.'],
],
)),
]),
)
),
]
),
responses: [
new OA\Response(
response: 200,
@@ -476,8 +483,10 @@ class ApplicationsController extends Controller
'instant_deploy' => ['type' => 'boolean', 'description' => 'The flag to indicate if the application should be deployed instantly.'],
'use_build_server' => ['type' => 'boolean', 'nullable' => true, 'description' => 'Use build server.'],
],
)),
]),
)
),
]
),
responses: [
new OA\Response(
response: 200,
@@ -561,8 +570,10 @@ class ApplicationsController extends Controller
'instant_deploy' => ['type' => 'boolean', 'description' => 'The flag to indicate if the application should be deployed instantly.'],
'use_build_server' => ['type' => 'boolean', 'nullable' => true, 'description' => 'Use build server.'],
],
)),
]),
)
),
]
),
responses: [
new OA\Response(
response: 200,
@@ -612,8 +623,10 @@ class ApplicationsController extends Controller
'instant_deploy' => ['type' => 'boolean', 'description' => 'The flag to indicate if the application should be deployed instantly.'],
'use_build_server' => ['type' => 'boolean', 'nullable' => true, 'description' => 'Use build server.'],
],
)),
]),
)
),
]
),
responses: [
new OA\Response(
response: 200,
@@ -636,7 +649,7 @@ class ApplicationsController extends Controller
private function create_application(Request $request, $type)
{
$allowedFields = ['project_uuid', 'environment_name', 'server_uuid', 'destination_uuid', 'type', 'name', 'description', 'is_static', 'domains', 'git_repository', 'git_branch', 'git_commit_sha', 'private_key_uuid', 'docker_registry_image_name', 'docker_registry_image_tag', 'build_pack', 'install_command', 'build_command', 'start_command', 'ports_exposes', 'ports_mappings', 'base_directory', 'publish_directory', 'health_check_enabled', 'health_check_path', 'health_check_port', 'health_check_host', 'health_check_method', 'health_check_return_code', 'health_check_scheme', 'health_check_response_text', 'health_check_interval', 'health_check_timeout', 'health_check_retries', 'health_check_start_period', 'limits_memory', 'limits_memory_swap', 'limits_memory_swappiness', 'limits_memory_reservation', 'limits_cpus', 'limits_cpuset', 'limits_cpu_shares', 'custom_labels', 'custom_docker_run_options', 'post_deployment_command', 'post_deployment_command_container', 'pre_deployment_command', 'pre_deployment_command_container', 'manual_webhook_secret_github', 'manual_webhook_secret_gitlab', 'manual_webhook_secret_bitbucket', 'manual_webhook_secret_gitea', 'redirect', 'github_app_uuid', 'instant_deploy', 'dockerfile', 'docker_compose_location', 'docker_compose_raw', 'docker_compose_custom_start_command', 'docker_compose_custom_build_command', 'docker_compose_domains', 'watch_paths', 'use_build_server', 'static_image'];
$allowedFields = ['project_uuid', 'environment_name', 'server_uuid', 'destination_uuid', 'type', 'name', 'description', 'is_static', 'domains', 'git_repository', 'git_branch', 'git_commit_sha', 'private_key_uuid', 'docker_registry_image_name', 'docker_registry_image_tag', 'build_pack', 'install_command', 'build_command', 'start_command', 'ports_exposes', 'ports_mappings', 'base_directory', 'publish_directory', 'health_check_enabled', 'health_check_path', 'health_check_port', 'health_check_host', 'health_check_method', 'health_check_return_code', 'health_check_scheme', 'health_check_response_text', 'health_check_interval', 'health_check_timeout', 'health_check_retries', 'health_check_start_period', 'limits_memory', 'limits_memory_swap', 'limits_memory_swappiness', 'limits_memory_reservation', 'limits_cpus', 'limits_cpuset', 'limits_cpu_shares', 'custom_labels', 'custom_docker_run_options', 'post_deployment_command', 'post_deployment_command_container', 'pre_deployment_command', 'pre_deployment_command_container', 'manual_webhook_secret_github', 'manual_webhook_secret_gitlab', 'manual_webhook_secret_bitbucket', 'manual_webhook_secret_gitea', 'redirect', 'github_app_uuid', 'instant_deploy', 'dockerfile', 'docker_compose_location', 'docker_compose_raw', 'docker_compose_custom_start_command', 'docker_compose_custom_build_command', 'docker_compose_domains', 'watch_paths', 'use_build_server', 'static_image', 'custom_nginx_configuration'];
$teamId = getTeamIdFromToken();
if (is_null($teamId)) {
return invalidTokenResponse();
@@ -676,6 +689,27 @@ class ApplicationsController extends Controller
$githubAppUuid = $request->github_app_uuid;
$useBuildServer = $request->use_build_server;
$isStatic = $request->is_static;
$customNginxConfiguration = $request->custom_nginx_configuration;
if (! is_null($customNginxConfiguration)) {
if (! isBase64Encoded($customNginxConfiguration)) {
return response()->json([
'message' => 'Validation failed.',
'errors' => [
'custom_nginx_configuration' => 'The custom_nginx_configuration should be base64 encoded.',
],
], 422);
}
$customNginxConfiguration = base64_decode($customNginxConfiguration);
if (mb_detect_encoding($customNginxConfiguration, 'ASCII', true) === false) {
return response()->json([
'message' => 'Validation failed.',
'errors' => [
'custom_nginx_configuration' => 'The custom_nginx_configuration should be base64 encoded.',
],
], 422);
}
}
$project = Project::whereTeamId($teamId)->whereUuid($request->project_uuid)->first();
if (! $project) {
@@ -1247,7 +1281,8 @@ class ApplicationsController extends Controller
ref: '#/components/schemas/Application'
)
),
]),
]
),
new OA\Response(
response: 401,
ref: '#/components/responses/401',
@@ -1319,7 +1354,8 @@ class ApplicationsController extends Controller
]
)
),
]),
]
),
new OA\Response(
response: 401,
ref: '#/components/responses/401',
@@ -1445,8 +1481,10 @@ class ApplicationsController extends Controller
'watch_paths' => ['type' => 'string', 'description' => 'The watch paths.'],
'use_build_server' => ['type' => 'boolean', 'nullable' => true, 'description' => 'Use build server.'],
],
)),
]),
)
),
]
),
responses: [
new OA\Response(
response: 200,
@@ -1461,7 +1499,8 @@ class ApplicationsController extends Controller
]
)
),
]),
]
),
new OA\Response(
response: 401,
ref: '#/components/responses/401',
@@ -1500,7 +1539,7 @@ class ApplicationsController extends Controller
], 404);
}
$server = $application->destination->server;
$allowedFields = ['name', 'description', 'is_static', 'domains', 'git_repository', 'git_branch', 'git_commit_sha', 'docker_registry_image_name', 'docker_registry_image_tag', 'build_pack', 'static_image', 'install_command', 'build_command', 'start_command', 'ports_exposes', 'ports_mappings', 'base_directory', 'publish_directory', 'health_check_enabled', 'health_check_path', 'health_check_port', 'health_check_host', 'health_check_method', 'health_check_return_code', 'health_check_scheme', 'health_check_response_text', 'health_check_interval', 'health_check_timeout', 'health_check_retries', 'health_check_start_period', 'limits_memory', 'limits_memory_swap', 'limits_memory_swappiness', 'limits_memory_reservation', 'limits_cpus', 'limits_cpuset', 'limits_cpu_shares', 'custom_labels', 'custom_docker_run_options', 'post_deployment_command', 'post_deployment_command_container', 'pre_deployment_command', 'pre_deployment_command_container', 'watch_paths', 'manual_webhook_secret_github', 'manual_webhook_secret_gitlab', 'manual_webhook_secret_bitbucket', 'manual_webhook_secret_gitea', 'docker_compose_location', 'docker_compose_raw', 'docker_compose_custom_start_command', 'docker_compose_custom_build_command', 'docker_compose_domains', 'redirect', 'instant_deploy', 'use_build_server'];
$allowedFields = ['name', 'description', 'is_static', 'domains', 'git_repository', 'git_branch', 'git_commit_sha', 'docker_registry_image_name', 'docker_registry_image_tag', 'build_pack', 'static_image', 'install_command', 'build_command', 'start_command', 'ports_exposes', 'ports_mappings', 'base_directory', 'publish_directory', 'health_check_enabled', 'health_check_path', 'health_check_port', 'health_check_host', 'health_check_method', 'health_check_return_code', 'health_check_scheme', 'health_check_response_text', 'health_check_interval', 'health_check_timeout', 'health_check_retries', 'health_check_start_period', 'limits_memory', 'limits_memory_swap', 'limits_memory_swappiness', 'limits_memory_reservation', 'limits_cpus', 'limits_cpuset', 'limits_cpu_shares', 'custom_labels', 'custom_docker_run_options', 'post_deployment_command', 'post_deployment_command_container', 'pre_deployment_command', 'pre_deployment_command_container', 'watch_paths', 'manual_webhook_secret_github', 'manual_webhook_secret_gitlab', 'manual_webhook_secret_bitbucket', 'manual_webhook_secret_gitea', 'docker_compose_location', 'docker_compose_raw', 'docker_compose_custom_start_command', 'docker_compose_custom_build_command', 'docker_compose_domains', 'redirect', 'instant_deploy', 'use_build_server', 'custom_nginx_configuration'];
$validationRules = [
'name' => 'string|max:255',
@@ -1512,6 +1551,7 @@ class ApplicationsController extends Controller
'docker_compose_domains' => 'array|nullable',
'docker_compose_custom_start_command' => 'string|nullable',
'docker_compose_custom_build_command' => 'string|nullable',
'custom_nginx_configuration' => 'string|nullable',
];
$validationRules = array_merge($validationRules, sharedDataApplications());
$validator = customApiValidator($request->all(), $validationRules);
@@ -1530,6 +1570,25 @@ class ApplicationsController extends Controller
}
}
}
if ($request->has('custom_nginx_configuration')) {
if (! isBase64Encoded($request->custom_nginx_configuration)) {
return response()->json([
'message' => 'Validation failed.',
'errors' => [
'custom_nginx_configuration' => 'The custom_nginx_configuration should be base64 encoded.',
],
], 422);
}
$customNginxConfiguration = base64_decode($request->custom_nginx_configuration);
if (mb_detect_encoding($customNginxConfiguration, 'ASCII', true) === false) {
return response()->json([
'message' => 'Validation failed.',
'errors' => [
'custom_nginx_configuration' => 'The custom_nginx_configuration should be base64 encoded.',
],
], 422);
}
}
$return = $this->validateDataApplications($request, $server);
if ($return instanceof \Illuminate\Http\JsonResponse) {
return $return;
@@ -1550,16 +1609,33 @@ class ApplicationsController extends Controller
}
$domains = $request->domains;
if ($request->has('domains') && $server->isProxyShouldRun()) {
$errors = [];
$uuid = $request->uuid;
$fqdn = $request->domains;
$fqdn = str($fqdn)->replaceEnd(',', '')->trim();
$fqdn = str($fqdn)->replaceStart(',', '')->trim();
$application->fqdn = $fqdn;
if (! $application->settings->is_container_label_readonly_enabled) {
$customLabels = str(implode('|coolify|', generateLabelsApplication($application)))->replace('|coolify|', "\n");
$application->custom_labels = base64_encode($customLabels);
$errors = [];
$fqdn = str($fqdn)->trim()->explode(',')->map(function ($domain) use (&$errors) {
$domain = trim($domain);
if (filter_var($domain, FILTER_VALIDATE_URL) === false || ! preg_match('/^https?:\/\/[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,}/', $domain)) {
$errors[] = 'Invalid domain: '.$domain;
}
return $domain;
});
if (count($errors) > 0) {
return response()->json([
'message' => 'Validation failed.',
'errors' => $errors,
], 422);
}
if (checkIfDomainIsAlreadyUsed($fqdn, $teamId, $uuid)) {
return response()->json([
'message' => 'Validation failed.',
'errors' => [
'domains' => 'One of the domain is already used.',
],
], 422);
}
$request->offsetUnset('domains');
}
$dockerComposeDomainsJson = collect();
@@ -1649,7 +1725,8 @@ class ApplicationsController extends Controller
items: new OA\Items(ref: '#/components/schemas/EnvironmentVariable')
)
),
]),
]
),
new OA\Response(
response: 401,
ref: '#/components/responses/401',
@@ -1755,7 +1832,8 @@ class ApplicationsController extends Controller
]
)
),
]),
]
),
new OA\Response(
response: 401,
ref: '#/components/responses/401',
@@ -1943,7 +2021,8 @@ class ApplicationsController extends Controller
]
)
),
]),
]
),
new OA\Response(
response: 401,
ref: '#/components/responses/401',
@@ -2124,7 +2203,8 @@ class ApplicationsController extends Controller
]
)
),
]),
]
),
new OA\Response(
response: 401,
ref: '#/components/responses/401',
@@ -2273,7 +2353,8 @@ class ApplicationsController extends Controller
]
)
),
]),
]
),
new OA\Response(
response: 401,
ref: '#/components/responses/401',
@@ -2365,9 +2446,11 @@ class ApplicationsController extends Controller
properties: [
'message' => ['type' => 'string', 'example' => 'Deployment request queued.', 'description' => 'Message.'],
'deployment_uuid' => ['type' => 'string', 'example' => 'doogksw', 'description' => 'UUID of the deployment.'],
])
]
)
),
]),
]
),
new OA\Response(
response: 401,
ref: '#/components/responses/401',
@@ -2453,7 +2536,8 @@ class ApplicationsController extends Controller
]
)
),
]),
]
),
new OA\Response(
response: 401,
ref: '#/components/responses/401',
@@ -2527,7 +2611,8 @@ class ApplicationsController extends Controller
]
)
),
]),
]
),
new OA\Response(
response: 401,