Merge branch 'next' into set-default-message-queue-type-twenty
This commit is contained in:
2
.github/ISSUE_TEMPLATE/config.yml
vendored
2
.github/ISSUE_TEMPLATE/config.yml
vendored
@@ -4,5 +4,5 @@ contact_links:
|
|||||||
url: https://coollabs.io/discord
|
url: https://coollabs.io/discord
|
||||||
about: Reach out to us on Discord.
|
about: Reach out to us on Discord.
|
||||||
- name: 🙋♂️ Feature Requests
|
- name: 🙋♂️ Feature Requests
|
||||||
url: https://github.com/coollabsio/coolify/discussions/categories/feature-requests-ideas
|
url: https://github.com/coollabsio/coolify/discussions/categories/new-features
|
||||||
about: All feature requests will be discussed here.
|
about: All feature requests will be discussed here.
|
||||||
|
|||||||
@@ -18,7 +18,11 @@ class CleanupDatabase extends Command
|
|||||||
} else {
|
} else {
|
||||||
echo "Running database cleanup in dry-run mode...\n";
|
echo "Running database cleanup in dry-run mode...\n";
|
||||||
}
|
}
|
||||||
|
if (isCloud()) {
|
||||||
$keep_days = 60;
|
$keep_days = 60;
|
||||||
|
} else {
|
||||||
|
$keep_days = 60;
|
||||||
|
}
|
||||||
echo "Keep days: $keep_days\n";
|
echo "Keep days: $keep_days\n";
|
||||||
// Cleanup failed jobs table
|
// Cleanup failed jobs table
|
||||||
$failed_jobs = DB::table('failed_jobs')->where('failed_at', '<', now()->subDays(1));
|
$failed_jobs = DB::table('failed_jobs')->where('failed_at', '<', now()->subDays(1));
|
||||||
|
|||||||
@@ -739,7 +739,7 @@ class ApplicationsController extends Controller
|
|||||||
$application->isConfigurationChanged(true);
|
$application->isConfigurationChanged(true);
|
||||||
|
|
||||||
if ($instantDeploy) {
|
if ($instantDeploy) {
|
||||||
$deployment_uuid = new Cuid2(7);
|
$deployment_uuid = new Cuid2;
|
||||||
|
|
||||||
queue_application_deployment(
|
queue_application_deployment(
|
||||||
application: $application,
|
application: $application,
|
||||||
@@ -835,7 +835,7 @@ class ApplicationsController extends Controller
|
|||||||
$application->isConfigurationChanged(true);
|
$application->isConfigurationChanged(true);
|
||||||
|
|
||||||
if ($instantDeploy) {
|
if ($instantDeploy) {
|
||||||
$deployment_uuid = new Cuid2(7);
|
$deployment_uuid = new Cuid2;
|
||||||
|
|
||||||
queue_application_deployment(
|
queue_application_deployment(
|
||||||
application: $application,
|
application: $application,
|
||||||
@@ -927,7 +927,7 @@ class ApplicationsController extends Controller
|
|||||||
$application->isConfigurationChanged(true);
|
$application->isConfigurationChanged(true);
|
||||||
|
|
||||||
if ($instantDeploy) {
|
if ($instantDeploy) {
|
||||||
$deployment_uuid = new Cuid2(7);
|
$deployment_uuid = new Cuid2;
|
||||||
|
|
||||||
queue_application_deployment(
|
queue_application_deployment(
|
||||||
application: $application,
|
application: $application,
|
||||||
@@ -947,7 +947,7 @@ class ApplicationsController extends Controller
|
|||||||
]));
|
]));
|
||||||
} elseif ($type === 'dockerfile') {
|
} elseif ($type === 'dockerfile') {
|
||||||
if (! $request->has('name')) {
|
if (! $request->has('name')) {
|
||||||
$request->offsetSet('name', 'dockerfile-'.new Cuid2(7));
|
$request->offsetSet('name', 'dockerfile-'.new Cuid2);
|
||||||
}
|
}
|
||||||
$validator = customApiValidator($request->all(), [
|
$validator = customApiValidator($request->all(), [
|
||||||
sharedDataApplications(),
|
sharedDataApplications(),
|
||||||
@@ -1009,7 +1009,7 @@ class ApplicationsController extends Controller
|
|||||||
$application->isConfigurationChanged(true);
|
$application->isConfigurationChanged(true);
|
||||||
|
|
||||||
if ($instantDeploy) {
|
if ($instantDeploy) {
|
||||||
$deployment_uuid = new Cuid2(7);
|
$deployment_uuid = new Cuid2;
|
||||||
|
|
||||||
queue_application_deployment(
|
queue_application_deployment(
|
||||||
application: $application,
|
application: $application,
|
||||||
@@ -1025,7 +1025,7 @@ class ApplicationsController extends Controller
|
|||||||
]));
|
]));
|
||||||
} elseif ($type === 'dockerimage') {
|
} elseif ($type === 'dockerimage') {
|
||||||
if (! $request->has('name')) {
|
if (! $request->has('name')) {
|
||||||
$request->offsetSet('name', 'docker-image-'.new Cuid2(7));
|
$request->offsetSet('name', 'docker-image-'.new Cuid2);
|
||||||
}
|
}
|
||||||
$validator = customApiValidator($request->all(), [
|
$validator = customApiValidator($request->all(), [
|
||||||
sharedDataApplications(),
|
sharedDataApplications(),
|
||||||
@@ -1067,7 +1067,7 @@ class ApplicationsController extends Controller
|
|||||||
$application->isConfigurationChanged(true);
|
$application->isConfigurationChanged(true);
|
||||||
|
|
||||||
if ($instantDeploy) {
|
if ($instantDeploy) {
|
||||||
$deployment_uuid = new Cuid2(7);
|
$deployment_uuid = new Cuid2;
|
||||||
|
|
||||||
queue_application_deployment(
|
queue_application_deployment(
|
||||||
application: $application,
|
application: $application,
|
||||||
@@ -1099,7 +1099,7 @@ class ApplicationsController extends Controller
|
|||||||
], 422);
|
], 422);
|
||||||
}
|
}
|
||||||
if (! $request->has('name')) {
|
if (! $request->has('name')) {
|
||||||
$request->offsetSet('name', 'service'.new Cuid2(7));
|
$request->offsetSet('name', 'service'.new Cuid2);
|
||||||
}
|
}
|
||||||
$validator = customApiValidator($request->all(), [
|
$validator = customApiValidator($request->all(), [
|
||||||
sharedDataApplications(),
|
sharedDataApplications(),
|
||||||
@@ -1320,7 +1320,7 @@ class ApplicationsController extends Controller
|
|||||||
#[OA\Patch(
|
#[OA\Patch(
|
||||||
summary: 'Update',
|
summary: 'Update',
|
||||||
description: 'Update application by UUID.',
|
description: 'Update application by UUID.',
|
||||||
path: '/applications',
|
path: '/applications/{uuid}',
|
||||||
security: [
|
security: [
|
||||||
['bearerAuth' => []],
|
['bearerAuth' => []],
|
||||||
],
|
],
|
||||||
@@ -2322,7 +2322,7 @@ class ApplicationsController extends Controller
|
|||||||
return response()->json(['message' => 'Application not found.'], 404);
|
return response()->json(['message' => 'Application not found.'], 404);
|
||||||
}
|
}
|
||||||
|
|
||||||
$deployment_uuid = new Cuid2(7);
|
$deployment_uuid = new Cuid2;
|
||||||
|
|
||||||
queue_application_deployment(
|
queue_application_deployment(
|
||||||
application: $application,
|
application: $application,
|
||||||
@@ -2479,7 +2479,7 @@ class ApplicationsController extends Controller
|
|||||||
return response()->json(['message' => 'Application not found.'], 404);
|
return response()->json(['message' => 'Application not found.'], 404);
|
||||||
}
|
}
|
||||||
|
|
||||||
$deployment_uuid = new Cuid2(7);
|
$deployment_uuid = new Cuid2;
|
||||||
|
|
||||||
queue_application_deployment(
|
queue_application_deployment(
|
||||||
application: $application,
|
application: $application,
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ class DeployController extends Controller
|
|||||||
],
|
],
|
||||||
tags: ['Deployments'],
|
tags: ['Deployments'],
|
||||||
parameters: [
|
parameters: [
|
||||||
new OA\Parameter(name: 'uuid', in: 'path', required: true, description: 'Deployment Uuid', schema: new OA\Schema(type: 'integer')),
|
new OA\Parameter(name: 'uuid', in: 'path', required: true, description: 'Deployment Uuid', schema: new OA\Schema(type: 'string')),
|
||||||
],
|
],
|
||||||
responses: [
|
responses: [
|
||||||
new OA\Response(
|
new OA\Response(
|
||||||
@@ -290,7 +290,7 @@ class DeployController extends Controller
|
|||||||
}
|
}
|
||||||
switch ($resource?->getMorphClass()) {
|
switch ($resource?->getMorphClass()) {
|
||||||
case 'App\Models\Application':
|
case 'App\Models\Application':
|
||||||
$deployment_uuid = new Cuid2(7);
|
$deployment_uuid = new Cuid2;
|
||||||
queue_application_deployment(
|
queue_application_deployment(
|
||||||
application: $resource,
|
application: $resource,
|
||||||
deployment_uuid: $deployment_uuid,
|
deployment_uuid: $deployment_uuid,
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ namespace App\Http\Controllers\Api;
|
|||||||
use OpenApi\Attributes as OA;
|
use OpenApi\Attributes as OA;
|
||||||
|
|
||||||
#[OA\Info(title: 'Coolify', version: '0.1')]
|
#[OA\Info(title: 'Coolify', version: '0.1')]
|
||||||
#[OA\Server(url: 'https://app.coolify.io/api/v1')]
|
#[OA\Server(url: 'https://app.coolify.io/api/v1', description: 'Coolify Cloud API. Change the host to your own instance if you are self-hosting.')]
|
||||||
#[OA\SecurityScheme(
|
#[OA\SecurityScheme(
|
||||||
type: 'http',
|
type: 'http',
|
||||||
scheme: 'bearer',
|
scheme: 'bearer',
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ class ProjectController extends Controller
|
|||||||
],
|
],
|
||||||
tags: ['Projects'],
|
tags: ['Projects'],
|
||||||
parameters: [
|
parameters: [
|
||||||
new OA\Parameter(name: 'uuid', in: 'path', required: true, description: 'Project UUID', schema: new OA\Schema(type: 'integer')),
|
new OA\Parameter(name: 'uuid', in: 'path', required: true, description: 'Project UUID', schema: new OA\Schema(type: 'string')),
|
||||||
],
|
],
|
||||||
responses: [
|
responses: [
|
||||||
new OA\Response(
|
new OA\Response(
|
||||||
@@ -107,7 +107,7 @@ class ProjectController extends Controller
|
|||||||
],
|
],
|
||||||
tags: ['Projects'],
|
tags: ['Projects'],
|
||||||
parameters: [
|
parameters: [
|
||||||
new OA\Parameter(name: 'uuid', in: 'path', required: true, description: 'Project UUID', schema: new OA\Schema(type: 'integer')),
|
new OA\Parameter(name: 'uuid', in: 'path', required: true, description: 'Project UUID', schema: new OA\Schema(type: 'string')),
|
||||||
new OA\Parameter(name: 'environment_name', in: 'path', required: true, description: 'Environment name', schema: new OA\Schema(type: 'string')),
|
new OA\Parameter(name: 'environment_name', in: 'path', required: true, description: 'Environment name', schema: new OA\Schema(type: 'string')),
|
||||||
],
|
],
|
||||||
responses: [
|
responses: [
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ class SecurityController extends Controller
|
|||||||
],
|
],
|
||||||
tags: ['Private Keys'],
|
tags: ['Private Keys'],
|
||||||
parameters: [
|
parameters: [
|
||||||
new OA\Parameter(name: 'uuid', in: 'path', required: true, description: 'Private Key Uuid', schema: new OA\Schema(type: 'integer')),
|
new OA\Parameter(name: 'uuid', in: 'path', required: true, description: 'Private Key Uuid', schema: new OA\Schema(type: 'string')),
|
||||||
],
|
],
|
||||||
responses: [
|
responses: [
|
||||||
new OA\Response(
|
new OA\Response(
|
||||||
@@ -318,7 +318,7 @@ class SecurityController extends Controller
|
|||||||
],
|
],
|
||||||
tags: ['Private Keys'],
|
tags: ['Private Keys'],
|
||||||
parameters: [
|
parameters: [
|
||||||
new OA\Parameter(name: 'uuid', in: 'path', required: true, description: 'Private Key Uuid', schema: new OA\Schema(type: 'integer')),
|
new OA\Parameter(name: 'uuid', in: 'path', required: true, description: 'Private Key Uuid', schema: new OA\Schema(type: 'string')),
|
||||||
],
|
],
|
||||||
responses: [
|
responses: [
|
||||||
new OA\Response(
|
new OA\Response(
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ class ServersController extends Controller
|
|||||||
],
|
],
|
||||||
tags: ['Servers'],
|
tags: ['Servers'],
|
||||||
parameters: [
|
parameters: [
|
||||||
new OA\Parameter(name: 'uuid', in: 'path', required: true, description: 'Server\'s Uuid', schema: new OA\Schema(type: 'integer')),
|
new OA\Parameter(name: 'uuid', in: 'path', required: true, description: 'Server\'s Uuid', schema: new OA\Schema(type: 'string')),
|
||||||
],
|
],
|
||||||
responses: [
|
responses: [
|
||||||
new OA\Response(
|
new OA\Response(
|
||||||
@@ -182,7 +182,7 @@ class ServersController extends Controller
|
|||||||
],
|
],
|
||||||
tags: ['Servers'],
|
tags: ['Servers'],
|
||||||
parameters: [
|
parameters: [
|
||||||
new OA\Parameter(name: 'uuid', in: 'path', required: true, description: 'Server\'s Uuid', schema: new OA\Schema(type: 'integer')),
|
new OA\Parameter(name: 'uuid', in: 'path', required: true, description: 'Server\'s Uuid', schema: new OA\Schema(type: 'string')),
|
||||||
],
|
],
|
||||||
responses: [
|
responses: [
|
||||||
new OA\Response(
|
new OA\Response(
|
||||||
@@ -259,7 +259,7 @@ class ServersController extends Controller
|
|||||||
],
|
],
|
||||||
tags: ['Servers'],
|
tags: ['Servers'],
|
||||||
parameters: [
|
parameters: [
|
||||||
new OA\Parameter(name: 'uuid', in: 'path', required: true, description: 'Server\'s Uuid', schema: new OA\Schema(type: 'integer')),
|
new OA\Parameter(name: 'uuid', in: 'path', required: true, description: 'Server\'s Uuid', schema: new OA\Schema(type: 'string')),
|
||||||
],
|
],
|
||||||
responses: [
|
responses: [
|
||||||
new OA\Response(
|
new OA\Response(
|
||||||
@@ -732,7 +732,7 @@ class ServersController extends Controller
|
|||||||
],
|
],
|
||||||
tags: ['Servers'],
|
tags: ['Servers'],
|
||||||
parameters: [
|
parameters: [
|
||||||
new OA\Parameter(name: 'uuid', in: 'path', required: true, description: 'Server UUID', schema: new OA\Schema(type: 'integer')),
|
new OA\Parameter(name: 'uuid', in: 'path', required: true, description: 'Server UUID', schema: new OA\Schema(type: 'string')),
|
||||||
],
|
],
|
||||||
responses: [
|
responses: [
|
||||||
new OA\Response(
|
new OA\Response(
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ class Bitbucket extends Controller
|
|||||||
if ($x_bitbucket_event === 'repo:push') {
|
if ($x_bitbucket_event === 'repo:push') {
|
||||||
if ($application->isDeployable()) {
|
if ($application->isDeployable()) {
|
||||||
ray('Deploying '.$application->name.' with branch '.$branch);
|
ray('Deploying '.$application->name.' with branch '.$branch);
|
||||||
$deployment_uuid = new Cuid2(7);
|
$deployment_uuid = new Cuid2;
|
||||||
queue_application_deployment(
|
queue_application_deployment(
|
||||||
application: $application,
|
application: $application,
|
||||||
deployment_uuid: $deployment_uuid,
|
deployment_uuid: $deployment_uuid,
|
||||||
@@ -127,7 +127,7 @@ class Bitbucket extends Controller
|
|||||||
if ($x_bitbucket_event === 'pullrequest:created') {
|
if ($x_bitbucket_event === 'pullrequest:created') {
|
||||||
if ($application->isPRDeployable()) {
|
if ($application->isPRDeployable()) {
|
||||||
ray('Deploying preview for '.$application->name.' with branch '.$branch.' and base branch '.$base_branch.' and pull request id '.$pull_request_id);
|
ray('Deploying preview for '.$application->name.' with branch '.$branch.' and base branch '.$base_branch.' and pull request id '.$pull_request_id);
|
||||||
$deployment_uuid = new Cuid2(7);
|
$deployment_uuid = new Cuid2;
|
||||||
$found = ApplicationPreview::where('application_id', $application->id)->where('pull_request_id', $pull_request_id)->first();
|
$found = ApplicationPreview::where('application_id', $application->id)->where('pull_request_id', $pull_request_id)->first();
|
||||||
if (! $found) {
|
if (! $found) {
|
||||||
if ($application->build_pack === 'dockercompose') {
|
if ($application->build_pack === 'dockercompose') {
|
||||||
|
|||||||
@@ -123,7 +123,7 @@ class Gitea extends Controller
|
|||||||
$is_watch_path_triggered = $application->isWatchPathsTriggered($changed_files);
|
$is_watch_path_triggered = $application->isWatchPathsTriggered($changed_files);
|
||||||
if ($is_watch_path_triggered || is_null($application->watch_paths)) {
|
if ($is_watch_path_triggered || is_null($application->watch_paths)) {
|
||||||
ray('Deploying '.$application->name.' with branch '.$branch);
|
ray('Deploying '.$application->name.' with branch '.$branch);
|
||||||
$deployment_uuid = new Cuid2(7);
|
$deployment_uuid = new Cuid2;
|
||||||
queue_application_deployment(
|
queue_application_deployment(
|
||||||
application: $application,
|
application: $application,
|
||||||
deployment_uuid: $deployment_uuid,
|
deployment_uuid: $deployment_uuid,
|
||||||
@@ -162,7 +162,7 @@ class Gitea extends Controller
|
|||||||
if ($x_gitea_event === 'pull_request') {
|
if ($x_gitea_event === 'pull_request') {
|
||||||
if ($action === 'opened' || $action === 'synchronize' || $action === 'reopened') {
|
if ($action === 'opened' || $action === 'synchronize' || $action === 'reopened') {
|
||||||
if ($application->isPRDeployable()) {
|
if ($application->isPRDeployable()) {
|
||||||
$deployment_uuid = new Cuid2(7);
|
$deployment_uuid = new Cuid2;
|
||||||
$found = ApplicationPreview::where('application_id', $application->id)->where('pull_request_id', $pull_request_id)->first();
|
$found = ApplicationPreview::where('application_id', $application->id)->where('pull_request_id', $pull_request_id)->first();
|
||||||
if (! $found) {
|
if (! $found) {
|
||||||
if ($application->build_pack === 'dockercompose') {
|
if ($application->build_pack === 'dockercompose') {
|
||||||
|
|||||||
@@ -128,7 +128,7 @@ class Github extends Controller
|
|||||||
$is_watch_path_triggered = $application->isWatchPathsTriggered($changed_files);
|
$is_watch_path_triggered = $application->isWatchPathsTriggered($changed_files);
|
||||||
if ($is_watch_path_triggered || is_null($application->watch_paths)) {
|
if ($is_watch_path_triggered || is_null($application->watch_paths)) {
|
||||||
ray('Deploying '.$application->name.' with branch '.$branch);
|
ray('Deploying '.$application->name.' with branch '.$branch);
|
||||||
$deployment_uuid = new Cuid2(7);
|
$deployment_uuid = new Cuid2;
|
||||||
queue_application_deployment(
|
queue_application_deployment(
|
||||||
application: $application,
|
application: $application,
|
||||||
deployment_uuid: $deployment_uuid,
|
deployment_uuid: $deployment_uuid,
|
||||||
@@ -167,7 +167,7 @@ class Github extends Controller
|
|||||||
if ($x_github_event === 'pull_request') {
|
if ($x_github_event === 'pull_request') {
|
||||||
if ($action === 'opened' || $action === 'synchronize' || $action === 'reopened') {
|
if ($action === 'opened' || $action === 'synchronize' || $action === 'reopened') {
|
||||||
if ($application->isPRDeployable()) {
|
if ($application->isPRDeployable()) {
|
||||||
$deployment_uuid = new Cuid2(7);
|
$deployment_uuid = new Cuid2;
|
||||||
$found = ApplicationPreview::where('application_id', $application->id)->where('pull_request_id', $pull_request_id)->first();
|
$found = ApplicationPreview::where('application_id', $application->id)->where('pull_request_id', $pull_request_id)->first();
|
||||||
if (! $found) {
|
if (! $found) {
|
||||||
if ($application->build_pack === 'dockercompose') {
|
if ($application->build_pack === 'dockercompose') {
|
||||||
@@ -357,7 +357,7 @@ class Github extends Controller
|
|||||||
$is_watch_path_triggered = $application->isWatchPathsTriggered($changed_files);
|
$is_watch_path_triggered = $application->isWatchPathsTriggered($changed_files);
|
||||||
if ($is_watch_path_triggered || is_null($application->watch_paths)) {
|
if ($is_watch_path_triggered || is_null($application->watch_paths)) {
|
||||||
ray('Deploying '.$application->name.' with branch '.$branch);
|
ray('Deploying '.$application->name.' with branch '.$branch);
|
||||||
$deployment_uuid = new Cuid2(7);
|
$deployment_uuid = new Cuid2;
|
||||||
queue_application_deployment(
|
queue_application_deployment(
|
||||||
application: $application,
|
application: $application,
|
||||||
deployment_uuid: $deployment_uuid,
|
deployment_uuid: $deployment_uuid,
|
||||||
@@ -396,7 +396,7 @@ class Github extends Controller
|
|||||||
if ($x_github_event === 'pull_request') {
|
if ($x_github_event === 'pull_request') {
|
||||||
if ($action === 'opened' || $action === 'synchronize' || $action === 'reopened') {
|
if ($action === 'opened' || $action === 'synchronize' || $action === 'reopened') {
|
||||||
if ($application->isPRDeployable()) {
|
if ($application->isPRDeployable()) {
|
||||||
$deployment_uuid = new Cuid2(7);
|
$deployment_uuid = new Cuid2;
|
||||||
$found = ApplicationPreview::where('application_id', $application->id)->where('pull_request_id', $pull_request_id)->first();
|
$found = ApplicationPreview::where('application_id', $application->id)->where('pull_request_id', $pull_request_id)->first();
|
||||||
if (! $found) {
|
if (! $found) {
|
||||||
ApplicationPreview::create([
|
ApplicationPreview::create([
|
||||||
|
|||||||
@@ -137,7 +137,7 @@ class Gitlab extends Controller
|
|||||||
$is_watch_path_triggered = $application->isWatchPathsTriggered($changed_files);
|
$is_watch_path_triggered = $application->isWatchPathsTriggered($changed_files);
|
||||||
if ($is_watch_path_triggered || is_null($application->watch_paths)) {
|
if ($is_watch_path_triggered || is_null($application->watch_paths)) {
|
||||||
ray('Deploying '.$application->name.' with branch '.$branch);
|
ray('Deploying '.$application->name.' with branch '.$branch);
|
||||||
$deployment_uuid = new Cuid2(7);
|
$deployment_uuid = new Cuid2;
|
||||||
queue_application_deployment(
|
queue_application_deployment(
|
||||||
application: $application,
|
application: $application,
|
||||||
deployment_uuid: $deployment_uuid,
|
deployment_uuid: $deployment_uuid,
|
||||||
@@ -177,7 +177,7 @@ class Gitlab extends Controller
|
|||||||
if ($x_gitlab_event === 'merge_request') {
|
if ($x_gitlab_event === 'merge_request') {
|
||||||
if ($action === 'open' || $action === 'opened' || $action === 'synchronize' || $action === 'reopened' || $action === 'reopen' || $action === 'update') {
|
if ($action === 'open' || $action === 'opened' || $action === 'synchronize' || $action === 'reopened' || $action === 'reopen' || $action === 'update') {
|
||||||
if ($application->isPRDeployable()) {
|
if ($application->isPRDeployable()) {
|
||||||
$deployment_uuid = new Cuid2(7);
|
$deployment_uuid = new Cuid2;
|
||||||
$found = ApplicationPreview::where('application_id', $application->id)->where('pull_request_id', $pull_request_id)->first();
|
$found = ApplicationPreview::where('application_id', $application->id)->where('pull_request_id', $pull_request_id)->first();
|
||||||
if (! $found) {
|
if (! $found) {
|
||||||
if ($application->build_pack === 'dockercompose') {
|
if ($application->build_pack === 'dockercompose') {
|
||||||
|
|||||||
@@ -307,14 +307,6 @@ class ApplicationDeploymentJob implements ShouldBeEncrypted, ShouldQueue
|
|||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
// $this->execute_remote_command(
|
|
||||||
// [
|
|
||||||
// "docker image prune -f >/dev/null 2>&1",
|
|
||||||
// "hidden" => true,
|
|
||||||
// "ignore_errors" => true,
|
|
||||||
// ]
|
|
||||||
// );
|
|
||||||
|
|
||||||
ApplicationStatusChanged::dispatch(data_get($this->application, 'environment.project.team.id'));
|
ApplicationStatusChanged::dispatch(data_get($this->application, 'environment.project.team.id'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -497,13 +489,13 @@ class ApplicationDeploymentJob implements ShouldBeEncrypted, ShouldQueue
|
|||||||
} else {
|
} else {
|
||||||
$this->write_deployment_configurations();
|
$this->write_deployment_configurations();
|
||||||
$server_workdir = $this->application->workdir();
|
$server_workdir = $this->application->workdir();
|
||||||
|
$this->docker_compose_location = '/docker-compose.yaml';
|
||||||
|
|
||||||
$command = "{$this->coolify_variables} docker compose";
|
$command = "{$this->coolify_variables} docker compose";
|
||||||
if ($this->env_filename) {
|
if ($this->env_filename) {
|
||||||
$command .= " --env-file {$this->workdir}/{$this->env_filename}";
|
$command .= " --env-file {$server_workdir}/{$this->env_filename}";
|
||||||
}
|
}
|
||||||
$command .= " --project-directory {$server_workdir} -f {$server_workdir}{$this->docker_compose_location} up -d";
|
$command .= " --project-directory {$server_workdir} -f {$server_workdir}{$this->docker_compose_location} up -d";
|
||||||
|
|
||||||
$this->execute_remote_command(
|
$this->execute_remote_command(
|
||||||
['command' => $command, 'hidden' => true],
|
['command' => $command, 'hidden' => true],
|
||||||
);
|
);
|
||||||
@@ -636,21 +628,26 @@ class ApplicationDeploymentJob implements ShouldBeEncrypted, ShouldQueue
|
|||||||
$this->server = $this->original_server;
|
$this->server = $this->original_server;
|
||||||
}
|
}
|
||||||
$readme = generate_readme_file($this->application->name, $this->application_deployment_queue->updated_at);
|
$readme = generate_readme_file($this->application->name, $this->application_deployment_queue->updated_at);
|
||||||
|
|
||||||
|
$mainDir = $this->configuration_dir;
|
||||||
|
if ($this->application->settings->is_raw_compose_deployment_enabled) {
|
||||||
|
$mainDir = $this->application->workdir();
|
||||||
|
}
|
||||||
if ($this->pull_request_id === 0) {
|
if ($this->pull_request_id === 0) {
|
||||||
$composeFileName = "$this->configuration_dir/docker-compose.yaml";
|
$composeFileName = "$mainDir/docker-compose.yaml";
|
||||||
} else {
|
} else {
|
||||||
$composeFileName = "$this->configuration_dir/docker-compose-pr-{$this->pull_request_id}.yaml";
|
$composeFileName = "$mainDir/docker-compose-pr-{$this->pull_request_id}.yaml";
|
||||||
$this->docker_compose_location = "/docker-compose-pr-{$this->pull_request_id}.yaml";
|
$this->docker_compose_location = "/docker-compose-pr-{$this->pull_request_id}.yaml";
|
||||||
}
|
}
|
||||||
$this->execute_remote_command(
|
$this->execute_remote_command(
|
||||||
[
|
[
|
||||||
"mkdir -p $this->configuration_dir",
|
"mkdir -p $mainDir",
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"echo '{$this->docker_compose_base64}' | base64 -d | tee $composeFileName > /dev/null",
|
"echo '{$this->docker_compose_base64}' | base64 -d | tee $composeFileName > /dev/null",
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"echo '{$readme}' > $this->configuration_dir/README.md",
|
"echo '{$readme}' > $mainDir/README.md",
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
if ($this->use_build_server) {
|
if ($this->use_build_server) {
|
||||||
|
|||||||
@@ -90,6 +90,7 @@ class DatabaseBackupJob implements ShouldBeEncrypted, ShouldQueue
|
|||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
BackupCreated::dispatch($this->team->id);
|
BackupCreated::dispatch($this->team->id);
|
||||||
|
|
||||||
// Check if team is exists
|
// Check if team is exists
|
||||||
if (is_null($this->team)) {
|
if (is_null($this->team)) {
|
||||||
$this->backup->update(['status' => 'failed']);
|
$this->backup->update(['status' => 'failed']);
|
||||||
@@ -476,7 +477,7 @@ class DatabaseBackupJob implements ShouldBeEncrypted, ShouldQueue
|
|||||||
} else {
|
} else {
|
||||||
$network = $this->database->destination->network;
|
$network = $this->database->destination->network;
|
||||||
}
|
}
|
||||||
$commands[] = "docker run --pull=always -d --network {$network} --name backup-of-{$this->backup->uuid} --rm -v $this->backup_location:$this->backup_location:ro ghcr.io/coollabsio/coolify-helper";
|
$commands[] = "docker run -d --network {$network} --name backup-of-{$this->backup->uuid} --rm -v $this->backup_location:$this->backup_location:ro ghcr.io/coollabsio/coolify-helper";
|
||||||
$commands[] = "docker exec backup-of-{$this->backup->uuid} mc config host add temporary {$endpoint} $key $secret";
|
$commands[] = "docker exec backup-of-{$this->backup->uuid} mc config host add temporary {$endpoint} $key $secret";
|
||||||
$commands[] = "docker exec backup-of-{$this->backup->uuid} mc cp $this->backup_location temporary/$bucket{$this->backup_dir}/";
|
$commands[] = "docker exec backup-of-{$this->backup->uuid} mc cp $this->backup_location temporary/$bucket{$this->backup_dir}/";
|
||||||
instant_remote_process($commands, $this->server);
|
instant_remote_process($commands, $this->server);
|
||||||
|
|||||||
486
app/Jobs/ServerCheckJob.php
Normal file
486
app/Jobs/ServerCheckJob.php
Normal file
@@ -0,0 +1,486 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Jobs;
|
||||||
|
|
||||||
|
use App\Actions\Database\StartDatabaseProxy;
|
||||||
|
use App\Actions\Proxy\CheckProxy;
|
||||||
|
use App\Actions\Proxy\StartProxy;
|
||||||
|
use App\Actions\Server\InstallLogDrain;
|
||||||
|
use App\Models\ApplicationPreview;
|
||||||
|
use App\Models\Server;
|
||||||
|
use App\Models\ServiceDatabase;
|
||||||
|
use App\Notifications\Container\ContainerRestarted;
|
||||||
|
use Illuminate\Bus\Queueable;
|
||||||
|
use Illuminate\Contracts\Queue\ShouldBeEncrypted;
|
||||||
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
|
use Illuminate\Foundation\Bus\Dispatchable;
|
||||||
|
use Illuminate\Queue\InteractsWithQueue;
|
||||||
|
use Illuminate\Queue\Middleware\WithoutOverlapping;
|
||||||
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
use Illuminate\Support\Arr;
|
||||||
|
|
||||||
|
class ServerCheckJob implements ShouldBeEncrypted, ShouldQueue
|
||||||
|
{
|
||||||
|
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||||
|
|
||||||
|
public $tries = 3;
|
||||||
|
|
||||||
|
public $containers;
|
||||||
|
|
||||||
|
public $applications;
|
||||||
|
|
||||||
|
public $databases;
|
||||||
|
|
||||||
|
public $services;
|
||||||
|
|
||||||
|
public $previews;
|
||||||
|
|
||||||
|
public function backoff(): int
|
||||||
|
{
|
||||||
|
return isDev() ? 1 : 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function __construct(public Server $server) {}
|
||||||
|
|
||||||
|
public function middleware(): array
|
||||||
|
{
|
||||||
|
return [(new WithoutOverlapping($this->server->uuid))];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function uniqueId(): int
|
||||||
|
{
|
||||||
|
return $this->server->uuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handle()
|
||||||
|
{
|
||||||
|
|
||||||
|
try {
|
||||||
|
$up = $this->serverStatus();
|
||||||
|
if (! $up) {
|
||||||
|
ray('Server is not reachable.');
|
||||||
|
|
||||||
|
return 'Server is not reachable.';
|
||||||
|
}
|
||||||
|
if (! $this->server->isFunctional()) {
|
||||||
|
ray('Server is not ready.');
|
||||||
|
|
||||||
|
return 'Server is not ready.';
|
||||||
|
}
|
||||||
|
$this->checkSentinel();
|
||||||
|
$this->getContainers();
|
||||||
|
|
||||||
|
if (is_null($this->containers)) {
|
||||||
|
return 'No containers found.';
|
||||||
|
}
|
||||||
|
$this->checkLogDrainContainer();
|
||||||
|
$this->containerStatus();
|
||||||
|
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
ray($e->getMessage());
|
||||||
|
|
||||||
|
return handleError($e);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private function checkSentinel()
|
||||||
|
{
|
||||||
|
if ($this->server->isSentinelEnabled()) {
|
||||||
|
$sentinelContainerFound = $this->containers->filter(function ($value, $key) {
|
||||||
|
return data_get($value, 'Name') === '/coolify-sentinel';
|
||||||
|
})->first();
|
||||||
|
if ($sentinelContainerFound) {
|
||||||
|
$status = data_get($sentinelContainerFound, 'State.Status');
|
||||||
|
if ($status !== 'running') {
|
||||||
|
PullSentinelImageJob::dispatch($this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function serverStatus()
|
||||||
|
{
|
||||||
|
$this->removeUnnevessaryCoolifyYaml();
|
||||||
|
['uptime' => $uptime] = $this->server->validateConnection();
|
||||||
|
if ($uptime) {
|
||||||
|
if ($this->server->unreachable_notification_sent === true) {
|
||||||
|
$this->server->update(['unreachable_notification_sent' => false]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
foreach ($this->applications as $application) {
|
||||||
|
$application->update(['status' => 'exited']);
|
||||||
|
}
|
||||||
|
foreach ($this->databases as $database) {
|
||||||
|
$database->update(['status' => 'exited']);
|
||||||
|
}
|
||||||
|
foreach ($this->services as $service) {
|
||||||
|
$apps = $service->applications()->get();
|
||||||
|
$dbs = $service->databases()->get();
|
||||||
|
foreach ($apps as $app) {
|
||||||
|
$app->update(['status' => 'exited']);
|
||||||
|
}
|
||||||
|
foreach ($dbs as $db) {
|
||||||
|
$db->update(['status' => 'exited']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private function removeUnnevessaryCoolifyYaml()
|
||||||
|
{
|
||||||
|
// This will remote the coolify.yaml file from the server as it is not needed on cloud servers
|
||||||
|
if (isCloud() && $this->server->id !== 0) {
|
||||||
|
$file = $this->server->proxyPath().'/dynamic/coolify.yaml';
|
||||||
|
|
||||||
|
return instant_remote_process([
|
||||||
|
"rm -f $file",
|
||||||
|
], $this->server, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function checkLogDrainContainer()
|
||||||
|
{
|
||||||
|
$foundLogDrainContainer = $this->containers->filter(function ($value, $key) {
|
||||||
|
return data_get($value, 'Name') === '/coolify-log-drain';
|
||||||
|
})->first();
|
||||||
|
if ($foundLogDrainContainer) {
|
||||||
|
$status = data_get($foundLogDrainContainer, 'State.Status');
|
||||||
|
if ($status !== 'running') {
|
||||||
|
InstallLogDrain::dispatch($this->server);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
InstallLogDrain::dispatch($this->server);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getContainers()
|
||||||
|
{
|
||||||
|
if ($this->server->isSwarm()) {
|
||||||
|
$this->containers = instant_remote_process(["docker service inspect $(docker service ls -q) --format '{{json .}}'"], $this->server, false);
|
||||||
|
$this->containers = format_docker_command_output_to_json($this->containers);
|
||||||
|
$containerReplicates = instant_remote_process(["docker service ls --format '{{json .}}'"], $this->server, false);
|
||||||
|
if ($containerReplicates) {
|
||||||
|
$containerReplicates = format_docker_command_output_to_json($containerReplicates);
|
||||||
|
foreach ($containerReplicates as $containerReplica) {
|
||||||
|
$name = data_get($containerReplica, 'Name');
|
||||||
|
$this->containers = $this->containers->map(function ($container) use ($name, $containerReplica) {
|
||||||
|
if (data_get($container, 'Spec.Name') === $name) {
|
||||||
|
$replicas = data_get($containerReplica, 'Replicas');
|
||||||
|
$running = str($replicas)->explode('/')[0];
|
||||||
|
$total = str($replicas)->explode('/')[1];
|
||||||
|
if ($running === $total) {
|
||||||
|
data_set($container, 'State.Status', 'running');
|
||||||
|
data_set($container, 'State.Health.Status', 'healthy');
|
||||||
|
} else {
|
||||||
|
data_set($container, 'State.Status', 'starting');
|
||||||
|
data_set($container, 'State.Health.Status', 'unhealthy');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $container;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$this->containers = instant_remote_process(["docker container inspect $(docker container ls -q) --format '{{json .}}'"], $this->server, false);
|
||||||
|
$this->containers = format_docker_command_output_to_json($this->containers);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private function containerStatus()
|
||||||
|
{
|
||||||
|
|
||||||
|
$this->applications = $this->server->applications();
|
||||||
|
$this->databases = $this->server->databases();
|
||||||
|
$this->services = $this->server->services()->get();
|
||||||
|
$this->previews = $this->server->previews();
|
||||||
|
|
||||||
|
$foundApplications = [];
|
||||||
|
$foundApplicationPreviews = [];
|
||||||
|
$foundDatabases = [];
|
||||||
|
$foundServices = [];
|
||||||
|
|
||||||
|
foreach ($this->containers as $container) {
|
||||||
|
if ($this->server->isSwarm()) {
|
||||||
|
$labels = data_get($container, 'Spec.Labels');
|
||||||
|
$uuid = data_get($labels, 'coolify.name');
|
||||||
|
} else {
|
||||||
|
$labels = data_get($container, 'Config.Labels');
|
||||||
|
}
|
||||||
|
$containerStatus = data_get($container, 'State.Status');
|
||||||
|
$containerHealth = data_get($container, 'State.Health.Status', 'unhealthy');
|
||||||
|
$containerStatus = "$containerStatus ($containerHealth)";
|
||||||
|
$labels = Arr::undot(format_docker_labels_to_json($labels));
|
||||||
|
$applicationId = data_get($labels, 'coolify.applicationId');
|
||||||
|
if ($applicationId) {
|
||||||
|
$pullRequestId = data_get($labels, 'coolify.pullRequestId');
|
||||||
|
if ($pullRequestId) {
|
||||||
|
if (str($applicationId)->contains('-')) {
|
||||||
|
$applicationId = str($applicationId)->before('-');
|
||||||
|
}
|
||||||
|
$preview = ApplicationPreview::where('application_id', $applicationId)->where('pull_request_id', $pullRequestId)->first();
|
||||||
|
if ($preview) {
|
||||||
|
$foundApplicationPreviews[] = $preview->id;
|
||||||
|
$statusFromDb = $preview->status;
|
||||||
|
if ($statusFromDb !== $containerStatus) {
|
||||||
|
$preview->update(['status' => $containerStatus]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//Notify user that this container should not be there.
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$application = $this->applications->where('id', $applicationId)->first();
|
||||||
|
if ($application) {
|
||||||
|
$foundApplications[] = $application->id;
|
||||||
|
$statusFromDb = $application->status;
|
||||||
|
if ($statusFromDb !== $containerStatus) {
|
||||||
|
$application->update(['status' => $containerStatus]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//Notify user that this container should not be there.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$uuid = data_get($labels, 'com.docker.compose.service');
|
||||||
|
$type = data_get($labels, 'coolify.type');
|
||||||
|
|
||||||
|
if ($uuid) {
|
||||||
|
if ($type === 'service') {
|
||||||
|
$database_id = data_get($labels, 'coolify.service.subId');
|
||||||
|
if ($database_id) {
|
||||||
|
$service_db = ServiceDatabase::where('id', $database_id)->first();
|
||||||
|
if ($service_db) {
|
||||||
|
$uuid = data_get($service_db, 'service.uuid');
|
||||||
|
if ($uuid) {
|
||||||
|
$isPublic = data_get($service_db, 'is_public');
|
||||||
|
if ($isPublic) {
|
||||||
|
$foundTcpProxy = $this->containers->filter(function ($value, $key) use ($uuid) {
|
||||||
|
if ($this->server->isSwarm()) {
|
||||||
|
return data_get($value, 'Spec.Name') === "coolify-proxy_$uuid";
|
||||||
|
} else {
|
||||||
|
return data_get($value, 'Name') === "/$uuid-proxy";
|
||||||
|
}
|
||||||
|
})->first();
|
||||||
|
if (! $foundTcpProxy) {
|
||||||
|
StartDatabaseProxy::run($service_db);
|
||||||
|
// $this->server->team?->notify(new ContainerRestarted("TCP Proxy for {$service_db->service->name}", $this->server));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$database = $this->databases->where('uuid', $uuid)->first();
|
||||||
|
if ($database) {
|
||||||
|
$isPublic = data_get($database, 'is_public');
|
||||||
|
$foundDatabases[] = $database->id;
|
||||||
|
$statusFromDb = $database->status;
|
||||||
|
if ($statusFromDb !== $containerStatus) {
|
||||||
|
$database->update(['status' => $containerStatus]);
|
||||||
|
}
|
||||||
|
if ($isPublic) {
|
||||||
|
$foundTcpProxy = $this->containers->filter(function ($value, $key) use ($uuid) {
|
||||||
|
if ($this->server->isSwarm()) {
|
||||||
|
return data_get($value, 'Spec.Name') === "coolify-proxy_$uuid";
|
||||||
|
} else {
|
||||||
|
return data_get($value, 'Name') === "/$uuid-proxy";
|
||||||
|
}
|
||||||
|
})->first();
|
||||||
|
if (! $foundTcpProxy) {
|
||||||
|
StartDatabaseProxy::run($database);
|
||||||
|
$this->server->team?->notify(new ContainerRestarted("TCP Proxy for {$database->name}", $this->server));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Notify user that this container should not be there.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (data_get($container, 'Name') === '/coolify-db') {
|
||||||
|
$foundDatabases[] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$serviceLabelId = data_get($labels, 'coolify.serviceId');
|
||||||
|
if ($serviceLabelId) {
|
||||||
|
$subType = data_get($labels, 'coolify.service.subType');
|
||||||
|
$subId = data_get($labels, 'coolify.service.subId');
|
||||||
|
$service = $this->services->where('id', $serviceLabelId)->first();
|
||||||
|
if (! $service) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ($subType === 'application') {
|
||||||
|
$service = $service->applications()->where('id', $subId)->first();
|
||||||
|
} else {
|
||||||
|
$service = $service->databases()->where('id', $subId)->first();
|
||||||
|
}
|
||||||
|
if ($service) {
|
||||||
|
$foundServices[] = "$service->id-$service->name";
|
||||||
|
$statusFromDb = $service->status;
|
||||||
|
if ($statusFromDb !== $containerStatus) {
|
||||||
|
// ray('Updating status: ' . $containerStatus);
|
||||||
|
$service->update(['status' => $containerStatus]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$exitedServices = collect([]);
|
||||||
|
foreach ($this->services as $service) {
|
||||||
|
$apps = $service->applications()->get();
|
||||||
|
$dbs = $service->databases()->get();
|
||||||
|
foreach ($apps as $app) {
|
||||||
|
if (in_array("$app->id-$app->name", $foundServices)) {
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
$exitedServices->push($app);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
foreach ($dbs as $db) {
|
||||||
|
if (in_array("$db->id-$db->name", $foundServices)) {
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
$exitedServices->push($db);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$exitedServices = $exitedServices->unique('id');
|
||||||
|
foreach ($exitedServices as $exitedService) {
|
||||||
|
if (str($exitedService->status)->startsWith('exited')) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$name = data_get($exitedService, 'name');
|
||||||
|
$fqdn = data_get($exitedService, 'fqdn');
|
||||||
|
if ($name) {
|
||||||
|
if ($fqdn) {
|
||||||
|
$containerName = "$name, available at $fqdn";
|
||||||
|
} else {
|
||||||
|
$containerName = $name;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if ($fqdn) {
|
||||||
|
$containerName = $fqdn;
|
||||||
|
} else {
|
||||||
|
$containerName = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$projectUuid = data_get($service, 'environment.project.uuid');
|
||||||
|
$serviceUuid = data_get($service, 'uuid');
|
||||||
|
$environmentName = data_get($service, 'environment.name');
|
||||||
|
|
||||||
|
if ($projectUuid && $serviceUuid && $environmentName) {
|
||||||
|
$url = base_url().'/project/'.$projectUuid.'/'.$environmentName.'/service/'.$serviceUuid;
|
||||||
|
} else {
|
||||||
|
$url = null;
|
||||||
|
}
|
||||||
|
// $this->server->team?->notify(new ContainerStopped($containerName, $this->server, $url));
|
||||||
|
$exitedService->update(['status' => 'exited']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$notRunningApplications = $this->applications->pluck('id')->diff($foundApplications);
|
||||||
|
foreach ($notRunningApplications as $applicationId) {
|
||||||
|
$application = $this->applications->where('id', $applicationId)->first();
|
||||||
|
if (str($application->status)->startsWith('exited')) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$application->update(['status' => 'exited']);
|
||||||
|
|
||||||
|
$name = data_get($application, 'name');
|
||||||
|
$fqdn = data_get($application, 'fqdn');
|
||||||
|
|
||||||
|
$containerName = $name ? "$name ($fqdn)" : $fqdn;
|
||||||
|
|
||||||
|
$projectUuid = data_get($application, 'environment.project.uuid');
|
||||||
|
$applicationUuid = data_get($application, 'uuid');
|
||||||
|
$environment = data_get($application, 'environment.name');
|
||||||
|
|
||||||
|
if ($projectUuid && $applicationUuid && $environment) {
|
||||||
|
$url = base_url().'/project/'.$projectUuid.'/'.$environment.'/application/'.$applicationUuid;
|
||||||
|
} else {
|
||||||
|
$url = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// $this->server->team?->notify(new ContainerStopped($containerName, $this->server, $url));
|
||||||
|
}
|
||||||
|
$notRunningApplicationPreviews = $this->previews->pluck('id')->diff($foundApplicationPreviews);
|
||||||
|
foreach ($notRunningApplicationPreviews as $previewId) {
|
||||||
|
$preview = $this->previews->where('id', $previewId)->first();
|
||||||
|
if (str($preview->status)->startsWith('exited')) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$preview->update(['status' => 'exited']);
|
||||||
|
|
||||||
|
$name = data_get($preview, 'name');
|
||||||
|
$fqdn = data_get($preview, 'fqdn');
|
||||||
|
|
||||||
|
$containerName = $name ? "$name ($fqdn)" : $fqdn;
|
||||||
|
|
||||||
|
$projectUuid = data_get($preview, 'application.environment.project.uuid');
|
||||||
|
$environmentName = data_get($preview, 'application.environment.name');
|
||||||
|
$applicationUuid = data_get($preview, 'application.uuid');
|
||||||
|
|
||||||
|
if ($projectUuid && $applicationUuid && $environmentName) {
|
||||||
|
$url = base_url().'/project/'.$projectUuid.'/'.$environmentName.'/application/'.$applicationUuid;
|
||||||
|
} else {
|
||||||
|
$url = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// $this->server->team?->notify(new ContainerStopped($containerName, $this->server, $url));
|
||||||
|
}
|
||||||
|
$notRunningDatabases = $this->databases->pluck('id')->diff($foundDatabases);
|
||||||
|
foreach ($notRunningDatabases as $database) {
|
||||||
|
$database = $this->databases->where('id', $database)->first();
|
||||||
|
if (str($database->status)->startsWith('exited')) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$database->update(['status' => 'exited']);
|
||||||
|
|
||||||
|
$name = data_get($database, 'name');
|
||||||
|
$fqdn = data_get($database, 'fqdn');
|
||||||
|
|
||||||
|
$containerName = $name;
|
||||||
|
|
||||||
|
$projectUuid = data_get($database, 'environment.project.uuid');
|
||||||
|
$environmentName = data_get($database, 'environment.name');
|
||||||
|
$databaseUuid = data_get($database, 'uuid');
|
||||||
|
|
||||||
|
if ($projectUuid && $databaseUuid && $environmentName) {
|
||||||
|
$url = base_url().'/project/'.$projectUuid.'/'.$environmentName.'/database/'.$databaseUuid;
|
||||||
|
} else {
|
||||||
|
$url = null;
|
||||||
|
}
|
||||||
|
// $this->server->team?->notify(new ContainerStopped($containerName, $this->server, $url));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if proxy is running
|
||||||
|
$this->server->proxyType();
|
||||||
|
$foundProxyContainer = $this->containers->filter(function ($value, $key) {
|
||||||
|
if ($this->server->isSwarm()) {
|
||||||
|
return data_get($value, 'Spec.Name') === 'coolify-proxy_traefik';
|
||||||
|
} else {
|
||||||
|
return data_get($value, 'Name') === '/coolify-proxy';
|
||||||
|
}
|
||||||
|
})->first();
|
||||||
|
if (! $foundProxyContainer) {
|
||||||
|
try {
|
||||||
|
$shouldStart = CheckProxy::run($this->server);
|
||||||
|
if ($shouldStart) {
|
||||||
|
StartProxy::run($this->server, false);
|
||||||
|
$this->server->team?->notify(new ContainerRestarted('coolify-proxy', $this->server));
|
||||||
|
}
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
ray($e);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$this->server->proxy->status = data_get($foundProxyContainer, 'State.Status');
|
||||||
|
$this->server->save();
|
||||||
|
$connectProxyToDockerNetworks = connectProxyToNetworks($this->server);
|
||||||
|
instant_remote_process($connectProxyToDockerNetworks, $this->server, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -52,7 +52,7 @@ class Docker extends Component
|
|||||||
if (request()->query('network_name')) {
|
if (request()->query('network_name')) {
|
||||||
$this->network = request()->query('network_name');
|
$this->network = request()->query('network_name');
|
||||||
} else {
|
} else {
|
||||||
$this->network = new Cuid2(7);
|
$this->network = new Cuid2;
|
||||||
}
|
}
|
||||||
if ($this->servers->count() > 0) {
|
if ($this->servers->count() > 0) {
|
||||||
$this->name = str("{$this->servers->first()->name}-{$this->network}")->kebab();
|
$this->name = str("{$this->servers->first()->name}-{$this->network}")->kebab();
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ class MonacoEditor extends Component
|
|||||||
public function render()
|
public function render()
|
||||||
{
|
{
|
||||||
if (is_null($this->id)) {
|
if (is_null($this->id)) {
|
||||||
$this->id = new Cuid2(7);
|
$this->id = new Cuid2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_null($this->name)) {
|
if (is_null($this->name)) {
|
||||||
|
|||||||
@@ -96,6 +96,20 @@ class Advanced extends Component
|
|||||||
} else {
|
} else {
|
||||||
$this->application->settings->custom_internal_name = null;
|
$this->application->settings->custom_internal_name = null;
|
||||||
}
|
}
|
||||||
|
$customInternalName = $this->application->settings->custom_internal_name;
|
||||||
|
$server = $this->application->destination->server;
|
||||||
|
$allApplications = $server->applications();
|
||||||
|
|
||||||
|
$foundSameInternalName = $allApplications->filter(function ($application) {
|
||||||
|
return $application->id !== $this->application->id && $application->settings->custom_internal_name === $this->application->settings->custom_internal_name;
|
||||||
|
});
|
||||||
|
if ($foundSameInternalName->isNotEmpty()) {
|
||||||
|
$this->dispatch('error', 'This custom container name is already in use by another application on this server.');
|
||||||
|
$this->application->settings->custom_internal_name = $customInternalName;
|
||||||
|
$this->application->settings->refresh();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
$this->application->settings->save();
|
$this->application->settings->save();
|
||||||
$this->dispatch('success', 'Custom name saved.');
|
$this->dispatch('success', 'Custom name saved.');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -228,7 +228,7 @@ class General extends Component
|
|||||||
|
|
||||||
public function generateDomain(string $serviceName)
|
public function generateDomain(string $serviceName)
|
||||||
{
|
{
|
||||||
$uuid = new Cuid2(7);
|
$uuid = new Cuid2;
|
||||||
$domain = generateFqdn($this->application->destination->server, $uuid);
|
$domain = generateFqdn($this->application->destination->server, $uuid);
|
||||||
$this->parsedServiceDomains[$serviceName]['domain'] = $domain;
|
$this->parsedServiceDomains[$serviceName]['domain'] = $domain;
|
||||||
$this->application->docker_compose_domains = json_encode($this->parsedServiceDomains);
|
$this->application->docker_compose_domains = json_encode($this->parsedServiceDomains);
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ class Heading extends Component
|
|||||||
|
|
||||||
protected function setDeploymentUuid()
|
protected function setDeploymentUuid()
|
||||||
{
|
{
|
||||||
$this->deploymentUuid = new Cuid2(7);
|
$this->deploymentUuid = new Cuid2;
|
||||||
$this->parameters['deployment_uuid'] = $this->deploymentUuid;
|
$this->parameters['deployment_uuid'] = $this->deploymentUuid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ class Previews extends Component
|
|||||||
$template = $this->application->preview_url_template;
|
$template = $this->application->preview_url_template;
|
||||||
$host = $url->getHost();
|
$host = $url->getHost();
|
||||||
$schema = $url->getScheme();
|
$schema = $url->getScheme();
|
||||||
$random = new Cuid2(7);
|
$random = new Cuid2;
|
||||||
$preview_fqdn = str_replace('{{random}}', $random, $template);
|
$preview_fqdn = str_replace('{{random}}', $random, $template);
|
||||||
$preview_fqdn = str_replace('{{domain}}', $host, $preview_fqdn);
|
$preview_fqdn = str_replace('{{domain}}', $host, $preview_fqdn);
|
||||||
$preview_fqdn = str_replace('{{pr_id}}', $preview->pull_request_id, $preview_fqdn);
|
$preview_fqdn = str_replace('{{pr_id}}', $preview->pull_request_id, $preview_fqdn);
|
||||||
@@ -170,7 +170,7 @@ class Previews extends Component
|
|||||||
|
|
||||||
protected function setDeploymentUuid()
|
protected function setDeploymentUuid()
|
||||||
{
|
{
|
||||||
$this->deployment_uuid = new Cuid2(7);
|
$this->deployment_uuid = new Cuid2;
|
||||||
$this->parameters['deployment_uuid'] = $this->deployment_uuid;
|
$this->parameters['deployment_uuid'] = $this->deployment_uuid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ class PreviewsCompose extends Component
|
|||||||
$template = $this->preview->application->preview_url_template;
|
$template = $this->preview->application->preview_url_template;
|
||||||
$host = $url->getHost();
|
$host = $url->getHost();
|
||||||
$schema = $url->getScheme();
|
$schema = $url->getScheme();
|
||||||
$random = new Cuid2(7);
|
$random = new Cuid2;
|
||||||
$preview_fqdn = str_replace('{{random}}', $random, $template);
|
$preview_fqdn = str_replace('{{random}}', $random, $template);
|
||||||
$preview_fqdn = str_replace('{{domain}}', $host, $preview_fqdn);
|
$preview_fqdn = str_replace('{{domain}}', $host, $preview_fqdn);
|
||||||
$preview_fqdn = str_replace('{{pr_id}}', $this->preview->pull_request_id, $preview_fqdn);
|
$preview_fqdn = str_replace('{{pr_id}}', $this->preview->pull_request_id, $preview_fqdn);
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ class Rollback extends Component
|
|||||||
|
|
||||||
public function rollbackImage($commit)
|
public function rollbackImage($commit)
|
||||||
{
|
{
|
||||||
$deployment_uuid = new Cuid2(7);
|
$deployment_uuid = new Cuid2;
|
||||||
|
|
||||||
queue_application_deployment(
|
queue_application_deployment(
|
||||||
application: $this->application,
|
application: $this->application,
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ class CloneMe extends Component
|
|||||||
$this->environment = $this->project->environments->where('name', $this->environment_name)->first();
|
$this->environment = $this->project->environments->where('name', $this->environment_name)->first();
|
||||||
$this->project_id = $this->project->id;
|
$this->project_id = $this->project->id;
|
||||||
$this->servers = currentTeam()->servers;
|
$this->servers = currentTeam()->servers;
|
||||||
$this->newName = str($this->project->name.'-clone-'.(string) new Cuid2(7))->slug();
|
$this->newName = str($this->project->name.'-clone-'.(string) new Cuid2)->slug();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function render()
|
public function render()
|
||||||
@@ -106,7 +106,7 @@ class CloneMe extends Component
|
|||||||
$databases = $this->environment->databases();
|
$databases = $this->environment->databases();
|
||||||
$services = $this->environment->services;
|
$services = $this->environment->services;
|
||||||
foreach ($applications as $application) {
|
foreach ($applications as $application) {
|
||||||
$uuid = (string) new Cuid2(7);
|
$uuid = (string) new Cuid2;
|
||||||
$newApplication = $application->replicate()->fill([
|
$newApplication = $application->replicate()->fill([
|
||||||
'uuid' => $uuid,
|
'uuid' => $uuid,
|
||||||
'fqdn' => generateFqdn($this->server, $uuid),
|
'fqdn' => generateFqdn($this->server, $uuid),
|
||||||
@@ -133,7 +133,7 @@ class CloneMe extends Component
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
foreach ($databases as $database) {
|
foreach ($databases as $database) {
|
||||||
$uuid = (string) new Cuid2(7);
|
$uuid = (string) new Cuid2;
|
||||||
$newDatabase = $database->replicate()->fill([
|
$newDatabase = $database->replicate()->fill([
|
||||||
'uuid' => $uuid,
|
'uuid' => $uuid,
|
||||||
'status' => 'exited',
|
'status' => 'exited',
|
||||||
@@ -161,7 +161,7 @@ class CloneMe extends Component
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
foreach ($services as $service) {
|
foreach ($services as $service) {
|
||||||
$uuid = (string) new Cuid2(7);
|
$uuid = (string) new Cuid2;
|
||||||
$newService = $service->replicate()->fill([
|
$newService = $service->replicate()->fill([
|
||||||
'uuid' => $uuid,
|
'uuid' => $uuid,
|
||||||
'environment_id' => $environment->id,
|
'environment_id' => $environment->id,
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ class DockerImage extends Component
|
|||||||
$environment = $project->load(['environments'])->environments->where('name', $this->parameters['environment_name'])->first();
|
$environment = $project->load(['environments'])->environments->where('name', $this->parameters['environment_name'])->first();
|
||||||
ray($image, $tag);
|
ray($image, $tag);
|
||||||
$application = Application::create([
|
$application = Application::create([
|
||||||
'name' => 'docker-image-'.new Cuid2(7),
|
'name' => 'docker-image-'.new Cuid2,
|
||||||
'repository_project_id' => 0,
|
'repository_project_id' => 0,
|
||||||
'git_repository' => 'coollabsio/coolify',
|
'git_repository' => 'coollabsio/coolify',
|
||||||
'git_branch' => 'main',
|
'git_branch' => 'main',
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ CMD ["nginx", "-g", "daemon off;"]
|
|||||||
$port = 80;
|
$port = 80;
|
||||||
}
|
}
|
||||||
$application = Application::create([
|
$application = Application::create([
|
||||||
'name' => 'dockerfile-'.new Cuid2(7),
|
'name' => 'dockerfile-'.new Cuid2,
|
||||||
'repository_project_id' => 0,
|
'repository_project_id' => 0,
|
||||||
'git_repository' => 'coollabsio/coolify',
|
'git_repository' => 'coollabsio/coolify',
|
||||||
'git_branch' => 'main',
|
'git_branch' => 'main',
|
||||||
|
|||||||
@@ -63,6 +63,8 @@ class Navbar extends Component
|
|||||||
public function checkDeployments()
|
public function checkDeployments()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
// TODO: This is a temporary solution. We need to refactor this.
|
||||||
|
// We need to delete null bytes somehow.
|
||||||
$activity = Activity::where('properties->type_uuid', $this->service->uuid)->latest()->first();
|
$activity = Activity::where('properties->type_uuid', $this->service->uuid)->latest()->first();
|
||||||
$status = data_get($activity, 'properties.status');
|
$status = data_get($activity, 'properties.status');
|
||||||
if ($status === 'queued' || $status === 'in_progress') {
|
if ($status === 'queued' || $status === 'in_progress') {
|
||||||
@@ -70,7 +72,7 @@ class Navbar extends Component
|
|||||||
} else {
|
} else {
|
||||||
$this->isDeploymentProgress = false;
|
$this->isDeploymentProgress = false;
|
||||||
}
|
}
|
||||||
} catch (\Exception $e) {
|
} catch (\Throwable $e) {
|
||||||
$this->isDeploymentProgress = false;
|
$this->isDeploymentProgress = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ class Danger extends Component
|
|||||||
|
|
||||||
public function mount()
|
public function mount()
|
||||||
{
|
{
|
||||||
$this->modalId = new Cuid2(7);
|
$this->modalId = new Cuid2;
|
||||||
$parameters = get_route_parameters();
|
$parameters = get_route_parameters();
|
||||||
$this->projectUuid = data_get($parameters, 'project_uuid');
|
$this->projectUuid = data_get($parameters, 'project_uuid');
|
||||||
$this->environmentName = data_get($parameters, 'environment_name');
|
$this->environmentName = data_get($parameters, 'environment_name');
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ class Destination extends Component
|
|||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
$deployment_uuid = new Cuid2(7);
|
$deployment_uuid = new Cuid2;
|
||||||
$server = Server::find($server_id);
|
$server = Server::find($server_id);
|
||||||
$destination = StandaloneDocker::find($network_id);
|
$destination = StandaloneDocker::find($network_id);
|
||||||
queue_application_deployment(
|
queue_application_deployment(
|
||||||
|
|||||||
@@ -48,14 +48,14 @@ class Add extends Component
|
|||||||
public function submit()
|
public function submit()
|
||||||
{
|
{
|
||||||
$this->validate();
|
$this->validate();
|
||||||
if (str($this->value)->startsWith('{{') && str($this->value)->endsWith('}}')) {
|
// if (str($this->value)->startsWith('{{') && str($this->value)->endsWith('}}')) {
|
||||||
$type = str($this->value)->after('{{')->before('.')->value;
|
// $type = str($this->value)->after('{{')->before('.')->value;
|
||||||
if (! collect(SHARED_VARIABLE_TYPES)->contains($type)) {
|
// if (! collect(SHARED_VARIABLE_TYPES)->contains($type)) {
|
||||||
$this->dispatch('error', 'Invalid shared variable type.', 'Valid types are: team, project, environment.');
|
// $this->dispatch('error', 'Invalid shared variable type.', 'Valid types are: team, project, environment.');
|
||||||
|
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
$this->dispatch('saveKey', [
|
$this->dispatch('saveKey', [
|
||||||
'key' => $this->key,
|
'key' => $this->key,
|
||||||
'value' => $this->value,
|
'value' => $this->value,
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ class All extends Component
|
|||||||
if (str($this->resourceClass)->contains($resourceWithPreviews) && ! $simpleDockerfile) {
|
if (str($this->resourceClass)->contains($resourceWithPreviews) && ! $simpleDockerfile) {
|
||||||
$this->showPreview = true;
|
$this->showPreview = true;
|
||||||
}
|
}
|
||||||
$this->modalId = new Cuid2(7);
|
$this->modalId = new Cuid2;
|
||||||
$this->sortMe();
|
$this->sortMe();
|
||||||
$this->getDevView();
|
$this->getDevView();
|
||||||
}
|
}
|
||||||
@@ -125,14 +125,14 @@ class All extends Component
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
$found->value = $variable;
|
$found->value = $variable;
|
||||||
if (str($found->value)->startsWith('{{') && str($found->value)->endsWith('}}')) {
|
// if (str($found->value)->startsWith('{{') && str($found->value)->endsWith('}}')) {
|
||||||
$type = str($found->value)->after('{{')->before('.')->value;
|
// $type = str($found->value)->after('{{')->before('.')->value;
|
||||||
if (! collect(SHARED_VARIABLE_TYPES)->contains($type)) {
|
// if (! collect(SHARED_VARIABLE_TYPES)->contains($type)) {
|
||||||
$this->dispatch('error', 'Invalid shared variable type.', 'Valid types are: team, project, environment.');
|
// $this->dispatch('error', 'Invalid shared variable type.', 'Valid types are: team, project, environment.');
|
||||||
|
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
$found->save();
|
$found->save();
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
@@ -140,14 +140,14 @@ class All extends Component
|
|||||||
$environment = new EnvironmentVariable;
|
$environment = new EnvironmentVariable;
|
||||||
$environment->key = $key;
|
$environment->key = $key;
|
||||||
$environment->value = $variable;
|
$environment->value = $variable;
|
||||||
if (str($environment->value)->startsWith('{{') && str($environment->value)->endsWith('}}')) {
|
// if (str($environment->value)->startsWith('{{') && str($environment->value)->endsWith('}}')) {
|
||||||
$type = str($environment->value)->after('{{')->before('.')->value;
|
// $type = str($environment->value)->after('{{')->before('.')->value;
|
||||||
if (! collect(SHARED_VARIABLE_TYPES)->contains($type)) {
|
// if (! collect(SHARED_VARIABLE_TYPES)->contains($type)) {
|
||||||
$this->dispatch('error', 'Invalid shared variable type.', 'Valid types are: team, project, environment.');
|
// $this->dispatch('error', 'Invalid shared variable type.', 'Valid types are: team, project, environment.');
|
||||||
|
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
$environment->is_build_time = false;
|
$environment->is_build_time = false;
|
||||||
$environment->is_multiline = false;
|
$environment->is_multiline = false;
|
||||||
$environment->is_preview = $isPreview ? true : false;
|
$environment->is_preview = $isPreview ? true : false;
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ class Show extends Component
|
|||||||
if ($this->env->getMorphClass() === 'App\Models\SharedEnvironmentVariable') {
|
if ($this->env->getMorphClass() === 'App\Models\SharedEnvironmentVariable') {
|
||||||
$this->isSharedVariable = true;
|
$this->isSharedVariable = true;
|
||||||
}
|
}
|
||||||
$this->modalId = new Cuid2(7);
|
$this->modalId = new Cuid2;
|
||||||
$this->parameters = get_route_parameters();
|
$this->parameters = get_route_parameters();
|
||||||
$this->checkEnvs();
|
$this->checkEnvs();
|
||||||
}
|
}
|
||||||
@@ -108,14 +108,14 @@ class Show extends Component
|
|||||||
} else {
|
} else {
|
||||||
$this->validate();
|
$this->validate();
|
||||||
}
|
}
|
||||||
if (str($this->env->value)->startsWith('{{') && str($this->env->value)->endsWith('}}')) {
|
// if (str($this->env->value)->startsWith('{{') && str($this->env->value)->endsWith('}}')) {
|
||||||
$type = str($this->env->value)->after('{{')->before('.')->value;
|
// $type = str($this->env->value)->after('{{')->before('.')->value;
|
||||||
if (! collect(SHARED_VARIABLE_TYPES)->contains($type)) {
|
// if (! collect(SHARED_VARIABLE_TYPES)->contains($type)) {
|
||||||
$this->dispatch('error', 'Invalid shared variable type.', 'Valid types are: team, project, environment.');
|
// $this->dispatch('error', 'Invalid shared variable type.', 'Valid types are: team, project, environment.');
|
||||||
|
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
$this->serialize();
|
$this->serialize();
|
||||||
$this->env->save();
|
$this->env->save();
|
||||||
$this->dispatch('success', 'Environment variable updated.');
|
$this->dispatch('success', 'Environment variable updated.');
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ class ResourceOperations extends Component
|
|||||||
if (! $new_destination) {
|
if (! $new_destination) {
|
||||||
return $this->addError('destination_id', 'Destination not found.');
|
return $this->addError('destination_id', 'Destination not found.');
|
||||||
}
|
}
|
||||||
$uuid = (string) new Cuid2(7);
|
$uuid = (string) new Cuid2;
|
||||||
$server = $new_destination->server;
|
$server = $new_destination->server;
|
||||||
if ($this->resource->getMorphClass() === 'App\Models\Application') {
|
if ($this->resource->getMorphClass() === 'App\Models\Application') {
|
||||||
$new_resource = $this->resource->replicate()->fill([
|
$new_resource = $this->resource->replicate()->fill([
|
||||||
@@ -87,7 +87,7 @@ class ResourceOperations extends Component
|
|||||||
$this->resource->getMorphClass() === 'App\Models\StandaloneDragonfly' ||
|
$this->resource->getMorphClass() === 'App\Models\StandaloneDragonfly' ||
|
||||||
$this->resource->getMorphClass() === 'App\Models\StandaloneClickhouse'
|
$this->resource->getMorphClass() === 'App\Models\StandaloneClickhouse'
|
||||||
) {
|
) {
|
||||||
$uuid = (string) new Cuid2(7);
|
$uuid = (string) new Cuid2;
|
||||||
$new_resource = $this->resource->replicate()->fill([
|
$new_resource = $this->resource->replicate()->fill([
|
||||||
'uuid' => $uuid,
|
'uuid' => $uuid,
|
||||||
'name' => $this->resource->name.'-clone-'.$uuid,
|
'name' => $this->resource->name.'-clone-'.$uuid,
|
||||||
@@ -121,7 +121,7 @@ class ResourceOperations extends Component
|
|||||||
|
|
||||||
return redirect()->to($route);
|
return redirect()->to($route);
|
||||||
} elseif ($this->resource->type() === 'service') {
|
} elseif ($this->resource->type() === 'service') {
|
||||||
$uuid = (string) new Cuid2(7);
|
$uuid = (string) new Cuid2;
|
||||||
$new_resource = $this->resource->replicate()->fill([
|
$new_resource = $this->resource->replicate()->fill([
|
||||||
'uuid' => $uuid,
|
'uuid' => $uuid,
|
||||||
'name' => $this->resource->name.'-clone-'.$uuid,
|
'name' => $this->resource->name.'-clone-'.$uuid,
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ class Show extends Component
|
|||||||
$this->resource = Service::where('uuid', $this->parameters['service_uuid'])->firstOrFail();
|
$this->resource = Service::where('uuid', $this->parameters['service_uuid'])->firstOrFail();
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->modalId = new Cuid2(7);
|
$this->modalId = new Cuid2;
|
||||||
$this->task = ModelsScheduledTask::where('uuid', request()->route('task_uuid'))->first();
|
$this->task = ModelsScheduledTask::where('uuid', request()->route('task_uuid'))->first();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -232,12 +232,24 @@ class Application extends BaseModel
|
|||||||
public function failedTaskLink($task_uuid)
|
public function failedTaskLink($task_uuid)
|
||||||
{
|
{
|
||||||
if (data_get($this, 'environment.project.uuid')) {
|
if (data_get($this, 'environment.project.uuid')) {
|
||||||
return route('project.application.scheduled-tasks', [
|
$route = route('project.application.scheduled-tasks', [
|
||||||
'project_uuid' => data_get($this, 'environment.project.uuid'),
|
'project_uuid' => data_get($this, 'environment.project.uuid'),
|
||||||
'environment_name' => data_get($this, 'environment.name'),
|
'environment_name' => data_get($this, 'environment.name'),
|
||||||
'application_uuid' => data_get($this, 'uuid'),
|
'application_uuid' => data_get($this, 'uuid'),
|
||||||
'task_uuid' => $task_uuid,
|
'task_uuid' => $task_uuid,
|
||||||
]);
|
]);
|
||||||
|
$settings = InstanceSettings::get();
|
||||||
|
if (data_get($settings, 'fqdn')) {
|
||||||
|
$url = Url::fromString($route);
|
||||||
|
$url = $url->withPort(null);
|
||||||
|
$fqdn = data_get($settings, 'fqdn');
|
||||||
|
$fqdn = str_replace(['http://', 'https://'], '', $fqdn);
|
||||||
|
$url = $url->withHost($fqdn);
|
||||||
|
|
||||||
|
return $url->__toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $route;
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
@@ -275,12 +287,20 @@ class Application extends BaseModel
|
|||||||
return Attribute::make(
|
return Attribute::make(
|
||||||
get: function () {
|
get: function () {
|
||||||
if (! is_null($this->source?->html_url) && ! is_null($this->git_repository) && ! is_null($this->git_branch)) {
|
if (! is_null($this->source?->html_url) && ! is_null($this->git_repository) && ! is_null($this->git_branch)) {
|
||||||
|
if (str($this->git_repository)->contains('bitbucket')) {
|
||||||
|
return "{$this->source->html_url}/{$this->git_repository}/src/{$this->git_branch}";
|
||||||
|
}
|
||||||
|
|
||||||
return "{$this->source->html_url}/{$this->git_repository}/tree/{$this->git_branch}";
|
return "{$this->source->html_url}/{$this->git_repository}/tree/{$this->git_branch}";
|
||||||
}
|
}
|
||||||
// Convert the SSH URL to HTTPS URL
|
// Convert the SSH URL to HTTPS URL
|
||||||
if (strpos($this->git_repository, 'git@') === 0) {
|
if (strpos($this->git_repository, 'git@') === 0) {
|
||||||
$git_repository = str_replace(['git@', ':', '.git'], ['', '/', ''], $this->git_repository);
|
$git_repository = str_replace(['git@', ':', '.git'], ['', '/', ''], $this->git_repository);
|
||||||
|
|
||||||
|
if (str($this->git_repository)->contains('bitbucket')) {
|
||||||
|
return "https://{$git_repository}/src/{$this->git_branch}";
|
||||||
|
}
|
||||||
|
|
||||||
return "https://{$git_repository}/tree/{$this->git_branch}";
|
return "https://{$git_repository}/tree/{$this->git_branch}";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -431,6 +451,11 @@ class Application extends BaseModel
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function isRunning()
|
||||||
|
{
|
||||||
|
return (bool) str($this->status)->startsWith('running');
|
||||||
|
}
|
||||||
|
|
||||||
public function isExited()
|
public function isExited()
|
||||||
{
|
{
|
||||||
return (bool) str($this->status)->startsWith('exited');
|
return (bool) str($this->status)->startsWith('exited');
|
||||||
@@ -1270,7 +1295,7 @@ class Application extends BaseModel
|
|||||||
$template = $this->preview_url_template;
|
$template = $this->preview_url_template;
|
||||||
$host = $url->getHost();
|
$host = $url->getHost();
|
||||||
$schema = $url->getScheme();
|
$schema = $url->getScheme();
|
||||||
$random = new Cuid2(7);
|
$random = new Cuid2;
|
||||||
$preview_fqdn = str_replace('{{random}}', $random, $template);
|
$preview_fqdn = str_replace('{{random}}', $random, $template);
|
||||||
$preview_fqdn = str_replace('{{domain}}', $host, $preview_fqdn);
|
$preview_fqdn = str_replace('{{domain}}', $host, $preview_fqdn);
|
||||||
$preview_fqdn = str_replace('{{pr_id}}', $pull_request_id, $preview_fqdn);
|
$preview_fqdn = str_replace('{{pr_id}}', $pull_request_id, $preview_fqdn);
|
||||||
|
|||||||
@@ -35,6 +35,11 @@ class ApplicationPreview extends BaseModel
|
|||||||
return self::where('application_id', $application_id)->where('pull_request_id', $pull_request_id)->firstOrFail();
|
return self::where('application_id', $application_id)->where('pull_request_id', $pull_request_id)->firstOrFail();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function isRunning()
|
||||||
|
{
|
||||||
|
return (bool) str($this->status)->startsWith('running');
|
||||||
|
}
|
||||||
|
|
||||||
public function application()
|
public function application()
|
||||||
{
|
{
|
||||||
return $this->belongsTo(Application::class);
|
return $this->belongsTo(Application::class);
|
||||||
@@ -49,7 +54,7 @@ class ApplicationPreview extends BaseModel
|
|||||||
$template = $this->application->preview_url_template;
|
$template = $this->application->preview_url_template;
|
||||||
$host = $url->getHost();
|
$host = $url->getHost();
|
||||||
$schema = $url->getScheme();
|
$schema = $url->getScheme();
|
||||||
$random = new Cuid2(7);
|
$random = new Cuid2;
|
||||||
$preview_fqdn = str_replace('{{random}}', $random, $template);
|
$preview_fqdn = str_replace('{{random}}', $random, $template);
|
||||||
$preview_fqdn = str_replace('{{domain}}', $host, $preview_fqdn);
|
$preview_fqdn = str_replace('{{domain}}', $host, $preview_fqdn);
|
||||||
$preview_fqdn = str_replace('{{pr_id}}', $this->pull_request_id, $preview_fqdn);
|
$preview_fqdn = str_replace('{{pr_id}}', $this->pull_request_id, $preview_fqdn);
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ abstract class BaseModel extends Model
|
|||||||
static::creating(function (Model $model) {
|
static::creating(function (Model $model) {
|
||||||
// Generate a UUID if one isn't set
|
// Generate a UUID if one isn't set
|
||||||
if (! $model->uuid) {
|
if (! $model->uuid) {
|
||||||
$model->uuid = (string) new Cuid2(7);
|
$model->uuid = (string) new Cuid2;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ namespace App\Models;
|
|||||||
use App\Models\EnvironmentVariable as ModelsEnvironmentVariable;
|
use App\Models\EnvironmentVariable as ModelsEnvironmentVariable;
|
||||||
use Illuminate\Database\Eloquent\Casts\Attribute;
|
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Support\Str;
|
|
||||||
use OpenApi\Attributes as OA;
|
use OpenApi\Attributes as OA;
|
||||||
use Symfony\Component\Yaml\Yaml;
|
use Symfony\Component\Yaml\Yaml;
|
||||||
use Visus\Cuid2\Cuid2;
|
use Visus\Cuid2\Cuid2;
|
||||||
@@ -200,28 +199,33 @@ class EnvironmentVariable extends Model
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
$environment_variable = trim($environment_variable);
|
$environment_variable = trim($environment_variable);
|
||||||
$type = str($environment_variable)->after('{{')->before('.')->value;
|
$sharedEnvsFound = str($environment_variable)->matchAll('/{{(.*?)}}/');
|
||||||
if (str($environment_variable)->startsWith('{{'.$type) && str($environment_variable)->endsWith('}}')) {
|
if ($sharedEnvsFound->isEmpty()) {
|
||||||
$variable = Str::after($environment_variable, "{$type}.");
|
return $environment_variable;
|
||||||
$variable = Str::before($variable, '}}');
|
|
||||||
$variable = str($variable)->trim()->value;
|
|
||||||
if (! collect(SHARED_VARIABLE_TYPES)->contains($type)) {
|
|
||||||
return $variable;
|
|
||||||
}
|
}
|
||||||
if ($type === 'environment') {
|
foreach ($sharedEnvsFound as $sharedEnv) {
|
||||||
|
$type = str($sharedEnv)->match('/(.*?)\./');
|
||||||
|
if (! collect(SHARED_VARIABLE_TYPES)->contains($type)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$variable = str($sharedEnv)->match('/\.(.*)/');
|
||||||
|
if ($type->value() === 'environment') {
|
||||||
$id = $resource->environment->id;
|
$id = $resource->environment->id;
|
||||||
} elseif ($type === 'project') {
|
} elseif ($type->value() === 'project') {
|
||||||
$id = $resource->environment->project->id;
|
$id = $resource->environment->project->id;
|
||||||
} else {
|
} elseif ($type->value() === 'team') {
|
||||||
$id = $resource->team()->id;
|
$id = $resource->team()->id;
|
||||||
}
|
}
|
||||||
|
if (is_null($id)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
$environment_variable_found = SharedEnvironmentVariable::where('type', $type)->where('key', $variable)->where('team_id', $resource->team()->id)->where("{$type}_id", $id)->first();
|
$environment_variable_found = SharedEnvironmentVariable::where('type', $type)->where('key', $variable)->where('team_id', $resource->team()->id)->where("{$type}_id", $id)->first();
|
||||||
if ($environment_variable_found) {
|
if ($environment_variable_found) {
|
||||||
return $environment_variable_found;
|
$environment_variable = str($environment_variable)->replace("{{{$sharedEnv}}}", $environment_variable_found->value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $environment_variable;
|
return str($environment_variable)->value();
|
||||||
}
|
}
|
||||||
|
|
||||||
private function get_environment_variables(?string $environment_variable = null): ?string
|
private function get_environment_variables(?string $environment_variable = null): ?string
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ use Illuminate\Database\Eloquent\Relations\HasMany;
|
|||||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
use OpenApi\Attributes as OA;
|
use OpenApi\Attributes as OA;
|
||||||
|
use Spatie\Url\Url;
|
||||||
use Symfony\Component\Yaml\Yaml;
|
use Symfony\Component\Yaml\Yaml;
|
||||||
|
|
||||||
#[OA\Schema(
|
#[OA\Schema(
|
||||||
@@ -76,6 +77,11 @@ class Service extends BaseModel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function isRunning()
|
||||||
|
{
|
||||||
|
return (bool) str($this->status())->contains('running');
|
||||||
|
}
|
||||||
|
|
||||||
public function isExited()
|
public function isExited()
|
||||||
{
|
{
|
||||||
return (bool) str($this->status())->contains('exited');
|
return (bool) str($this->status())->contains('exited');
|
||||||
@@ -575,6 +581,30 @@ class Service extends BaseModel
|
|||||||
|
|
||||||
$fields->put('Vaultwarden', $data);
|
$fields->put('Vaultwarden', $data);
|
||||||
break;
|
break;
|
||||||
|
case str($image)->contains('gitlab/gitlab'):
|
||||||
|
$password = $this->environment_variables()->where('key', 'SERVICE_PASSWORD_GITLAB')->first();
|
||||||
|
$data = collect([]);
|
||||||
|
if ($password) {
|
||||||
|
$data = $data->merge([
|
||||||
|
'Root Password' => [
|
||||||
|
'key' => data_get($password, 'key'),
|
||||||
|
'value' => data_get($password, 'value'),
|
||||||
|
'rules' => 'required',
|
||||||
|
'isPassword' => true,
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
$data = $data->merge([
|
||||||
|
'Root User' => [
|
||||||
|
'key' => 'N/A',
|
||||||
|
'value' => 'root',
|
||||||
|
'rules' => 'required',
|
||||||
|
'isPassword' => true,
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
|
||||||
|
$fields->put('GitLab', $data->toArray());
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$databases = $this->databases()->get();
|
$databases = $this->databases()->get();
|
||||||
@@ -764,12 +794,24 @@ class Service extends BaseModel
|
|||||||
public function failedTaskLink($task_uuid)
|
public function failedTaskLink($task_uuid)
|
||||||
{
|
{
|
||||||
if (data_get($this, 'environment.project.uuid')) {
|
if (data_get($this, 'environment.project.uuid')) {
|
||||||
return route('project.service.scheduled-tasks', [
|
$route = route('project.service.scheduled-tasks', [
|
||||||
'project_uuid' => data_get($this, 'environment.project.uuid'),
|
'project_uuid' => data_get($this, 'environment.project.uuid'),
|
||||||
'environment_name' => data_get($this, 'environment.name'),
|
'environment_name' => data_get($this, 'environment.name'),
|
||||||
'service_uuid' => data_get($this, 'uuid'),
|
'service_uuid' => data_get($this, 'uuid'),
|
||||||
'task_uuid' => $task_uuid,
|
'task_uuid' => $task_uuid,
|
||||||
]);
|
]);
|
||||||
|
$settings = InstanceSettings::get();
|
||||||
|
if (data_get($settings, 'fqdn')) {
|
||||||
|
$url = Url::fromString($route);
|
||||||
|
$url = $url->withPort(null);
|
||||||
|
$fqdn = data_get($settings, 'fqdn');
|
||||||
|
$fqdn = str_replace(['http://', 'https://'], '', $fqdn);
|
||||||
|
$url = $url->withHost($fqdn);
|
||||||
|
|
||||||
|
return $url->__toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $route;
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -180,6 +180,10 @@ class User extends Authenticatable implements SendsEmail
|
|||||||
{
|
{
|
||||||
$found_root_team = auth()->user()->teams->filter(function ($team) {
|
$found_root_team = auth()->user()->teams->filter(function ($team) {
|
||||||
if ($team->id == 0) {
|
if ($team->id == 0) {
|
||||||
|
if (! auth()->user()->isAdmin()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ class Datalist extends Component
|
|||||||
public function render(): View|Closure|string
|
public function render(): View|Closure|string
|
||||||
{
|
{
|
||||||
if (is_null($this->id)) {
|
if (is_null($this->id)) {
|
||||||
$this->id = new Cuid2(7);
|
$this->id = new Cuid2;
|
||||||
}
|
}
|
||||||
if (is_null($this->name)) {
|
if (is_null($this->name)) {
|
||||||
$this->name = $this->id;
|
$this->name = $this->id;
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ class Input extends Component
|
|||||||
public function render(): View|Closure|string
|
public function render(): View|Closure|string
|
||||||
{
|
{
|
||||||
if (is_null($this->id)) {
|
if (is_null($this->id)) {
|
||||||
$this->id = new Cuid2(7);
|
$this->id = new Cuid2;
|
||||||
}
|
}
|
||||||
if (is_null($this->name)) {
|
if (is_null($this->name)) {
|
||||||
$this->name = $this->id;
|
$this->name = $this->id;
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ class Select extends Component
|
|||||||
public function render(): View|Closure|string
|
public function render(): View|Closure|string
|
||||||
{
|
{
|
||||||
if (is_null($this->id)) {
|
if (is_null($this->id)) {
|
||||||
$this->id = new Cuid2(7);
|
$this->id = new Cuid2;
|
||||||
}
|
}
|
||||||
if (is_null($this->name)) {
|
if (is_null($this->name)) {
|
||||||
$this->name = $this->id;
|
$this->name = $this->id;
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ class Textarea extends Component
|
|||||||
public function render(): View|Closure|string
|
public function render(): View|Closure|string
|
||||||
{
|
{
|
||||||
if (is_null($this->id)) {
|
if (is_null($this->id)) {
|
||||||
$this->id = new Cuid2(7);
|
$this->id = new Cuid2;
|
||||||
}
|
}
|
||||||
if (is_null($this->name)) {
|
if (is_null($this->name)) {
|
||||||
$this->name = $this->id;
|
$this->name = $this->id;
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ use Visus\Cuid2\Cuid2;
|
|||||||
|
|
||||||
function generate_database_name(string $type): string
|
function generate_database_name(string $type): string
|
||||||
{
|
{
|
||||||
$cuid = new Cuid2(7);
|
$cuid = new Cuid2;
|
||||||
|
|
||||||
return $type.'-database-'.$cuid;
|
return $type.'-database-'.$cuid;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -338,7 +338,7 @@ function fqdnLabelsForTraefik(string $uuid, Collection $domains, bool $is_force_
|
|||||||
foreach ($domains as $loop => $domain) {
|
foreach ($domains as $loop => $domain) {
|
||||||
try {
|
try {
|
||||||
if ($generate_unique_uuid) {
|
if ($generate_unique_uuid) {
|
||||||
$uuid = new Cuid2(7);
|
$uuid = new Cuid2;
|
||||||
}
|
}
|
||||||
|
|
||||||
$url = Url::fromString($domain);
|
$url = Url::fromString($domain);
|
||||||
|
|||||||
@@ -36,16 +36,23 @@ function collectDockerNetworksByServer(Server $server)
|
|||||||
}
|
}
|
||||||
// Service networks
|
// Service networks
|
||||||
foreach ($server->services()->get() as $service) {
|
foreach ($server->services()->get() as $service) {
|
||||||
|
if ($service->isRunning()) {
|
||||||
$networks->push($service->networks());
|
$networks->push($service->networks());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// Docker compose based apps
|
// Docker compose based apps
|
||||||
$docker_compose_apps = $server->dockerComposeBasedApplications();
|
$docker_compose_apps = $server->dockerComposeBasedApplications();
|
||||||
foreach ($docker_compose_apps as $app) {
|
foreach ($docker_compose_apps as $app) {
|
||||||
|
if ($app->isRunning()) {
|
||||||
$networks->push($app->uuid);
|
$networks->push($app->uuid);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// Docker compose based preview deployments
|
// Docker compose based preview deployments
|
||||||
$docker_compose_previews = $server->dockerComposeBasedPreviewDeployments();
|
$docker_compose_previews = $server->dockerComposeBasedPreviewDeployments();
|
||||||
foreach ($docker_compose_previews as $preview) {
|
foreach ($docker_compose_previews as $preview) {
|
||||||
|
if (! $preview->isRunning()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
$pullRequestId = $preview->pull_request_id;
|
$pullRequestId = $preview->pull_request_id;
|
||||||
$applicationId = $preview->application_id;
|
$applicationId = $preview->application_id;
|
||||||
$application = Application::find($applicationId);
|
$application = Application::find($applicationId);
|
||||||
|
|||||||
@@ -200,7 +200,7 @@ function generate_random_name(?string $cuid = null): string
|
|||||||
]
|
]
|
||||||
);
|
);
|
||||||
if (is_null($cuid)) {
|
if (is_null($cuid)) {
|
||||||
$cuid = new Cuid2(7);
|
$cuid = new Cuid2;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Str::kebab("{$generator->getName()}-$cuid");
|
return Str::kebab("{$generator->getName()}-$cuid");
|
||||||
@@ -236,7 +236,7 @@ function formatPrivateKey(string $privateKey)
|
|||||||
function generate_application_name(string $git_repository, string $git_branch, ?string $cuid = null): string
|
function generate_application_name(string $git_repository, string $git_branch, ?string $cuid = null): string
|
||||||
{
|
{
|
||||||
if (is_null($cuid)) {
|
if (is_null($cuid)) {
|
||||||
$cuid = new Cuid2(7);
|
$cuid = new Cuid2;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Str::kebab("$git_repository:$git_branch-$cuid");
|
return Str::kebab("$git_repository:$git_branch-$cuid");
|
||||||
@@ -2022,7 +2022,7 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
|
|||||||
$template = $resource->preview_url_template;
|
$template = $resource->preview_url_template;
|
||||||
$host = $url->getHost();
|
$host = $url->getHost();
|
||||||
$schema = $url->getScheme();
|
$schema = $url->getScheme();
|
||||||
$random = new Cuid2(7);
|
$random = new Cuid2;
|
||||||
$preview_fqdn = str_replace('{{random}}', $random, $template);
|
$preview_fqdn = str_replace('{{random}}', $random, $template);
|
||||||
$preview_fqdn = str_replace('{{domain}}', $host, $preview_fqdn);
|
$preview_fqdn = str_replace('{{domain}}', $host, $preview_fqdn);
|
||||||
$preview_fqdn = str_replace('{{pr_id}}', $pull_request_id, $preview_fqdn);
|
$preview_fqdn = str_replace('{{pr_id}}', $pull_request_id, $preview_fqdn);
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ return [
|
|||||||
|
|
||||||
// The release version of your application
|
// The release version of your application
|
||||||
// Example with dynamic git hash: trim(exec('git --git-dir ' . base_path('.git') . ' log --pretty="%h" -n1 HEAD'))
|
// Example with dynamic git hash: trim(exec('git --git-dir ' . base_path('.git') . ' log --pretty="%h" -n1 HEAD'))
|
||||||
'release' => '4.0.0-beta.319',
|
'release' => '4.0.0-beta.320',
|
||||||
// When left empty or `null` the Laravel environment will be used
|
// When left empty or `null` the Laravel environment will be used
|
||||||
'environment' => config('app.env'),
|
'environment' => config('app.env'),
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
return '4.0.0-beta.319';
|
return '4.0.0-beta.320';
|
||||||
|
|||||||
457
openapi.yaml
457
openapi.yaml
@@ -5,6 +5,7 @@ info:
|
|||||||
servers:
|
servers:
|
||||||
-
|
-
|
||||||
url: 'https://app.coolify.io/api/v1'
|
url: 'https://app.coolify.io/api/v1'
|
||||||
|
description: 'Coolify Cloud API. Change the host to your own instance if you are self-hosting.'
|
||||||
paths:
|
paths:
|
||||||
/applications:
|
/applications:
|
||||||
get:
|
get:
|
||||||
@@ -29,225 +30,6 @@ paths:
|
|||||||
security:
|
security:
|
||||||
-
|
-
|
||||||
bearerAuth: []
|
bearerAuth: []
|
||||||
patch:
|
|
||||||
tags:
|
|
||||||
- Applications
|
|
||||||
summary: Update
|
|
||||||
description: 'Update application by UUID.'
|
|
||||||
operationId: ff28a22d25b1f658c40b54d2073abbca
|
|
||||||
requestBody:
|
|
||||||
description: 'Application updated.'
|
|
||||||
required: true
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
properties:
|
|
||||||
project_uuid:
|
|
||||||
type: string
|
|
||||||
description: 'The project UUID.'
|
|
||||||
server_uuid:
|
|
||||||
type: string
|
|
||||||
description: 'The server UUID.'
|
|
||||||
environment_name:
|
|
||||||
type: string
|
|
||||||
description: 'The environment name.'
|
|
||||||
github_app_uuid:
|
|
||||||
type: string
|
|
||||||
description: 'The Github App UUID.'
|
|
||||||
git_repository:
|
|
||||||
type: string
|
|
||||||
description: 'The git repository URL.'
|
|
||||||
git_branch:
|
|
||||||
type: string
|
|
||||||
description: 'The git branch.'
|
|
||||||
ports_exposes:
|
|
||||||
type: string
|
|
||||||
description: 'The ports to expose.'
|
|
||||||
destination_uuid:
|
|
||||||
type: string
|
|
||||||
description: 'The destination UUID.'
|
|
||||||
build_pack:
|
|
||||||
type: string
|
|
||||||
enum: [nixpacks, static, dockerfile, dockercompose]
|
|
||||||
description: 'The build pack type.'
|
|
||||||
name:
|
|
||||||
type: string
|
|
||||||
description: 'The application name.'
|
|
||||||
description:
|
|
||||||
type: string
|
|
||||||
description: 'The application description.'
|
|
||||||
domains:
|
|
||||||
type: string
|
|
||||||
description: 'The application domains.'
|
|
||||||
git_commit_sha:
|
|
||||||
type: string
|
|
||||||
description: 'The git commit SHA.'
|
|
||||||
docker_registry_image_name:
|
|
||||||
type: string
|
|
||||||
description: 'The docker registry image name.'
|
|
||||||
docker_registry_image_tag:
|
|
||||||
type: string
|
|
||||||
description: 'The docker registry image tag.'
|
|
||||||
is_static:
|
|
||||||
type: boolean
|
|
||||||
description: 'The flag to indicate if the application is static.'
|
|
||||||
install_command:
|
|
||||||
type: string
|
|
||||||
description: 'The install command.'
|
|
||||||
build_command:
|
|
||||||
type: string
|
|
||||||
description: 'The build command.'
|
|
||||||
start_command:
|
|
||||||
type: string
|
|
||||||
description: 'The start command.'
|
|
||||||
ports_mappings:
|
|
||||||
type: string
|
|
||||||
description: 'The ports mappings.'
|
|
||||||
base_directory:
|
|
||||||
type: string
|
|
||||||
description: 'The base directory for all commands.'
|
|
||||||
publish_directory:
|
|
||||||
type: string
|
|
||||||
description: 'The publish directory.'
|
|
||||||
health_check_enabled:
|
|
||||||
type: boolean
|
|
||||||
description: 'Health check enabled.'
|
|
||||||
health_check_path:
|
|
||||||
type: string
|
|
||||||
description: 'Health check path.'
|
|
||||||
health_check_port:
|
|
||||||
type: string
|
|
||||||
nullable: true
|
|
||||||
description: 'Health check port.'
|
|
||||||
health_check_host:
|
|
||||||
type: string
|
|
||||||
nullable: true
|
|
||||||
description: 'Health check host.'
|
|
||||||
health_check_method:
|
|
||||||
type: string
|
|
||||||
description: 'Health check method.'
|
|
||||||
health_check_return_code:
|
|
||||||
type: integer
|
|
||||||
description: 'Health check return code.'
|
|
||||||
health_check_scheme:
|
|
||||||
type: string
|
|
||||||
description: 'Health check scheme.'
|
|
||||||
health_check_response_text:
|
|
||||||
type: string
|
|
||||||
nullable: true
|
|
||||||
description: 'Health check response text.'
|
|
||||||
health_check_interval:
|
|
||||||
type: integer
|
|
||||||
description: 'Health check interval in seconds.'
|
|
||||||
health_check_timeout:
|
|
||||||
type: integer
|
|
||||||
description: 'Health check timeout in seconds.'
|
|
||||||
health_check_retries:
|
|
||||||
type: integer
|
|
||||||
description: 'Health check retries count.'
|
|
||||||
health_check_start_period:
|
|
||||||
type: integer
|
|
||||||
description: 'Health check start period in seconds.'
|
|
||||||
limits_memory:
|
|
||||||
type: string
|
|
||||||
description: 'Memory limit.'
|
|
||||||
limits_memory_swap:
|
|
||||||
type: string
|
|
||||||
description: 'Memory swap limit.'
|
|
||||||
limits_memory_swappiness:
|
|
||||||
type: integer
|
|
||||||
description: 'Memory swappiness.'
|
|
||||||
limits_memory_reservation:
|
|
||||||
type: string
|
|
||||||
description: 'Memory reservation.'
|
|
||||||
limits_cpus:
|
|
||||||
type: string
|
|
||||||
description: 'CPU limit.'
|
|
||||||
limits_cpuset:
|
|
||||||
type: string
|
|
||||||
nullable: true
|
|
||||||
description: 'CPU set.'
|
|
||||||
limits_cpu_shares:
|
|
||||||
type: integer
|
|
||||||
description: 'CPU shares.'
|
|
||||||
custom_labels:
|
|
||||||
type: string
|
|
||||||
description: 'Custom labels.'
|
|
||||||
custom_docker_run_options:
|
|
||||||
type: string
|
|
||||||
description: 'Custom docker run options.'
|
|
||||||
post_deployment_command:
|
|
||||||
type: string
|
|
||||||
description: 'Post deployment command.'
|
|
||||||
post_deployment_command_container:
|
|
||||||
type: string
|
|
||||||
description: 'Post deployment command container.'
|
|
||||||
pre_deployment_command:
|
|
||||||
type: string
|
|
||||||
description: 'Pre deployment command.'
|
|
||||||
pre_deployment_command_container:
|
|
||||||
type: string
|
|
||||||
description: 'Pre deployment command container.'
|
|
||||||
manual_webhook_secret_github:
|
|
||||||
type: string
|
|
||||||
description: 'Manual webhook secret for Github.'
|
|
||||||
manual_webhook_secret_gitlab:
|
|
||||||
type: string
|
|
||||||
description: 'Manual webhook secret for Gitlab.'
|
|
||||||
manual_webhook_secret_bitbucket:
|
|
||||||
type: string
|
|
||||||
description: 'Manual webhook secret for Bitbucket.'
|
|
||||||
manual_webhook_secret_gitea:
|
|
||||||
type: string
|
|
||||||
description: 'Manual webhook secret for Gitea.'
|
|
||||||
redirect:
|
|
||||||
type: string
|
|
||||||
nullable: true
|
|
||||||
description: 'How to set redirect with Traefik / Caddy. www<->non-www.'
|
|
||||||
enum: [www, non-www, both]
|
|
||||||
instant_deploy:
|
|
||||||
type: boolean
|
|
||||||
description: 'The flag to indicate if the application should be deployed instantly.'
|
|
||||||
dockerfile:
|
|
||||||
type: string
|
|
||||||
description: 'The Dockerfile content.'
|
|
||||||
docker_compose_location:
|
|
||||||
type: string
|
|
||||||
description: 'The Docker Compose location.'
|
|
||||||
docker_compose_raw:
|
|
||||||
type: string
|
|
||||||
description: 'The Docker Compose raw content.'
|
|
||||||
docker_compose_custom_start_command:
|
|
||||||
type: string
|
|
||||||
description: 'The Docker Compose custom start command.'
|
|
||||||
docker_compose_custom_build_command:
|
|
||||||
type: string
|
|
||||||
description: 'The Docker Compose custom build command.'
|
|
||||||
docker_compose_domains:
|
|
||||||
type: array
|
|
||||||
description: 'The Docker Compose domains.'
|
|
||||||
watch_paths:
|
|
||||||
type: string
|
|
||||||
description: 'The watch paths.'
|
|
||||||
type: object
|
|
||||||
responses:
|
|
||||||
'200':
|
|
||||||
description: 'Application updated.'
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
properties:
|
|
||||||
uuid: { type: string }
|
|
||||||
type: object
|
|
||||||
'401':
|
|
||||||
$ref: '#/components/responses/401'
|
|
||||||
'400':
|
|
||||||
$ref: '#/components/responses/400'
|
|
||||||
'404':
|
|
||||||
$ref: '#/components/responses/404'
|
|
||||||
security:
|
|
||||||
-
|
|
||||||
bearerAuth: []
|
|
||||||
/applications/public:
|
/applications/public:
|
||||||
post:
|
post:
|
||||||
tags:
|
tags:
|
||||||
@@ -1369,6 +1151,225 @@ paths:
|
|||||||
security:
|
security:
|
||||||
-
|
-
|
||||||
bearerAuth: []
|
bearerAuth: []
|
||||||
|
patch:
|
||||||
|
tags:
|
||||||
|
- Applications
|
||||||
|
summary: Update
|
||||||
|
description: 'Update application by UUID.'
|
||||||
|
operationId: 62a3b1775e8cba5d39a236ebb69830b7
|
||||||
|
requestBody:
|
||||||
|
description: 'Application updated.'
|
||||||
|
required: true
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
properties:
|
||||||
|
project_uuid:
|
||||||
|
type: string
|
||||||
|
description: 'The project UUID.'
|
||||||
|
server_uuid:
|
||||||
|
type: string
|
||||||
|
description: 'The server UUID.'
|
||||||
|
environment_name:
|
||||||
|
type: string
|
||||||
|
description: 'The environment name.'
|
||||||
|
github_app_uuid:
|
||||||
|
type: string
|
||||||
|
description: 'The Github App UUID.'
|
||||||
|
git_repository:
|
||||||
|
type: string
|
||||||
|
description: 'The git repository URL.'
|
||||||
|
git_branch:
|
||||||
|
type: string
|
||||||
|
description: 'The git branch.'
|
||||||
|
ports_exposes:
|
||||||
|
type: string
|
||||||
|
description: 'The ports to expose.'
|
||||||
|
destination_uuid:
|
||||||
|
type: string
|
||||||
|
description: 'The destination UUID.'
|
||||||
|
build_pack:
|
||||||
|
type: string
|
||||||
|
enum: [nixpacks, static, dockerfile, dockercompose]
|
||||||
|
description: 'The build pack type.'
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
description: 'The application name.'
|
||||||
|
description:
|
||||||
|
type: string
|
||||||
|
description: 'The application description.'
|
||||||
|
domains:
|
||||||
|
type: string
|
||||||
|
description: 'The application domains.'
|
||||||
|
git_commit_sha:
|
||||||
|
type: string
|
||||||
|
description: 'The git commit SHA.'
|
||||||
|
docker_registry_image_name:
|
||||||
|
type: string
|
||||||
|
description: 'The docker registry image name.'
|
||||||
|
docker_registry_image_tag:
|
||||||
|
type: string
|
||||||
|
description: 'The docker registry image tag.'
|
||||||
|
is_static:
|
||||||
|
type: boolean
|
||||||
|
description: 'The flag to indicate if the application is static.'
|
||||||
|
install_command:
|
||||||
|
type: string
|
||||||
|
description: 'The install command.'
|
||||||
|
build_command:
|
||||||
|
type: string
|
||||||
|
description: 'The build command.'
|
||||||
|
start_command:
|
||||||
|
type: string
|
||||||
|
description: 'The start command.'
|
||||||
|
ports_mappings:
|
||||||
|
type: string
|
||||||
|
description: 'The ports mappings.'
|
||||||
|
base_directory:
|
||||||
|
type: string
|
||||||
|
description: 'The base directory for all commands.'
|
||||||
|
publish_directory:
|
||||||
|
type: string
|
||||||
|
description: 'The publish directory.'
|
||||||
|
health_check_enabled:
|
||||||
|
type: boolean
|
||||||
|
description: 'Health check enabled.'
|
||||||
|
health_check_path:
|
||||||
|
type: string
|
||||||
|
description: 'Health check path.'
|
||||||
|
health_check_port:
|
||||||
|
type: string
|
||||||
|
nullable: true
|
||||||
|
description: 'Health check port.'
|
||||||
|
health_check_host:
|
||||||
|
type: string
|
||||||
|
nullable: true
|
||||||
|
description: 'Health check host.'
|
||||||
|
health_check_method:
|
||||||
|
type: string
|
||||||
|
description: 'Health check method.'
|
||||||
|
health_check_return_code:
|
||||||
|
type: integer
|
||||||
|
description: 'Health check return code.'
|
||||||
|
health_check_scheme:
|
||||||
|
type: string
|
||||||
|
description: 'Health check scheme.'
|
||||||
|
health_check_response_text:
|
||||||
|
type: string
|
||||||
|
nullable: true
|
||||||
|
description: 'Health check response text.'
|
||||||
|
health_check_interval:
|
||||||
|
type: integer
|
||||||
|
description: 'Health check interval in seconds.'
|
||||||
|
health_check_timeout:
|
||||||
|
type: integer
|
||||||
|
description: 'Health check timeout in seconds.'
|
||||||
|
health_check_retries:
|
||||||
|
type: integer
|
||||||
|
description: 'Health check retries count.'
|
||||||
|
health_check_start_period:
|
||||||
|
type: integer
|
||||||
|
description: 'Health check start period in seconds.'
|
||||||
|
limits_memory:
|
||||||
|
type: string
|
||||||
|
description: 'Memory limit.'
|
||||||
|
limits_memory_swap:
|
||||||
|
type: string
|
||||||
|
description: 'Memory swap limit.'
|
||||||
|
limits_memory_swappiness:
|
||||||
|
type: integer
|
||||||
|
description: 'Memory swappiness.'
|
||||||
|
limits_memory_reservation:
|
||||||
|
type: string
|
||||||
|
description: 'Memory reservation.'
|
||||||
|
limits_cpus:
|
||||||
|
type: string
|
||||||
|
description: 'CPU limit.'
|
||||||
|
limits_cpuset:
|
||||||
|
type: string
|
||||||
|
nullable: true
|
||||||
|
description: 'CPU set.'
|
||||||
|
limits_cpu_shares:
|
||||||
|
type: integer
|
||||||
|
description: 'CPU shares.'
|
||||||
|
custom_labels:
|
||||||
|
type: string
|
||||||
|
description: 'Custom labels.'
|
||||||
|
custom_docker_run_options:
|
||||||
|
type: string
|
||||||
|
description: 'Custom docker run options.'
|
||||||
|
post_deployment_command:
|
||||||
|
type: string
|
||||||
|
description: 'Post deployment command.'
|
||||||
|
post_deployment_command_container:
|
||||||
|
type: string
|
||||||
|
description: 'Post deployment command container.'
|
||||||
|
pre_deployment_command:
|
||||||
|
type: string
|
||||||
|
description: 'Pre deployment command.'
|
||||||
|
pre_deployment_command_container:
|
||||||
|
type: string
|
||||||
|
description: 'Pre deployment command container.'
|
||||||
|
manual_webhook_secret_github:
|
||||||
|
type: string
|
||||||
|
description: 'Manual webhook secret for Github.'
|
||||||
|
manual_webhook_secret_gitlab:
|
||||||
|
type: string
|
||||||
|
description: 'Manual webhook secret for Gitlab.'
|
||||||
|
manual_webhook_secret_bitbucket:
|
||||||
|
type: string
|
||||||
|
description: 'Manual webhook secret for Bitbucket.'
|
||||||
|
manual_webhook_secret_gitea:
|
||||||
|
type: string
|
||||||
|
description: 'Manual webhook secret for Gitea.'
|
||||||
|
redirect:
|
||||||
|
type: string
|
||||||
|
nullable: true
|
||||||
|
description: 'How to set redirect with Traefik / Caddy. www<->non-www.'
|
||||||
|
enum: [www, non-www, both]
|
||||||
|
instant_deploy:
|
||||||
|
type: boolean
|
||||||
|
description: 'The flag to indicate if the application should be deployed instantly.'
|
||||||
|
dockerfile:
|
||||||
|
type: string
|
||||||
|
description: 'The Dockerfile content.'
|
||||||
|
docker_compose_location:
|
||||||
|
type: string
|
||||||
|
description: 'The Docker Compose location.'
|
||||||
|
docker_compose_raw:
|
||||||
|
type: string
|
||||||
|
description: 'The Docker Compose raw content.'
|
||||||
|
docker_compose_custom_start_command:
|
||||||
|
type: string
|
||||||
|
description: 'The Docker Compose custom start command.'
|
||||||
|
docker_compose_custom_build_command:
|
||||||
|
type: string
|
||||||
|
description: 'The Docker Compose custom build command.'
|
||||||
|
docker_compose_domains:
|
||||||
|
type: array
|
||||||
|
description: 'The Docker Compose domains.'
|
||||||
|
watch_paths:
|
||||||
|
type: string
|
||||||
|
description: 'The watch paths.'
|
||||||
|
type: object
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: 'Application updated.'
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
properties:
|
||||||
|
uuid: { type: string }
|
||||||
|
type: object
|
||||||
|
'401':
|
||||||
|
$ref: '#/components/responses/401'
|
||||||
|
'400':
|
||||||
|
$ref: '#/components/responses/400'
|
||||||
|
'404':
|
||||||
|
$ref: '#/components/responses/404'
|
||||||
|
security:
|
||||||
|
-
|
||||||
|
bearerAuth: []
|
||||||
'/applications/{uuid}/envs':
|
'/applications/{uuid}/envs':
|
||||||
get:
|
get:
|
||||||
tags:
|
tags:
|
||||||
@@ -2833,7 +2834,7 @@ paths:
|
|||||||
description: 'Deployment Uuid'
|
description: 'Deployment Uuid'
|
||||||
required: true
|
required: true
|
||||||
schema:
|
schema:
|
||||||
type: integer
|
type: string
|
||||||
responses:
|
responses:
|
||||||
'200':
|
'200':
|
||||||
description: 'Get deployment by UUID.'
|
description: 'Get deployment by UUID.'
|
||||||
@@ -3062,7 +3063,7 @@ paths:
|
|||||||
description: 'Project UUID'
|
description: 'Project UUID'
|
||||||
required: true
|
required: true
|
||||||
schema:
|
schema:
|
||||||
type: integer
|
type: string
|
||||||
responses:
|
responses:
|
||||||
'200':
|
'200':
|
||||||
description: 'Project details'
|
description: 'Project details'
|
||||||
@@ -3166,7 +3167,7 @@ paths:
|
|||||||
description: 'Project UUID'
|
description: 'Project UUID'
|
||||||
required: true
|
required: true
|
||||||
schema:
|
schema:
|
||||||
type: integer
|
type: string
|
||||||
-
|
-
|
||||||
name: environment_name
|
name: environment_name
|
||||||
in: path
|
in: path
|
||||||
@@ -3325,7 +3326,7 @@ paths:
|
|||||||
description: 'Private Key Uuid'
|
description: 'Private Key Uuid'
|
||||||
required: true
|
required: true
|
||||||
schema:
|
schema:
|
||||||
type: integer
|
type: string
|
||||||
responses:
|
responses:
|
||||||
'200':
|
'200':
|
||||||
description: 'Get all private keys.'
|
description: 'Get all private keys.'
|
||||||
@@ -3357,7 +3358,7 @@ paths:
|
|||||||
description: 'Private Key Uuid'
|
description: 'Private Key Uuid'
|
||||||
required: true
|
required: true
|
||||||
schema:
|
schema:
|
||||||
type: integer
|
type: string
|
||||||
responses:
|
responses:
|
||||||
'200':
|
'200':
|
||||||
description: 'Private Key deleted.'
|
description: 'Private Key deleted.'
|
||||||
@@ -3477,7 +3478,7 @@ paths:
|
|||||||
description: "Server's Uuid"
|
description: "Server's Uuid"
|
||||||
required: true
|
required: true
|
||||||
schema:
|
schema:
|
||||||
type: integer
|
type: string
|
||||||
responses:
|
responses:
|
||||||
'200':
|
'200':
|
||||||
description: 'Get server by UUID'
|
description: 'Get server by UUID'
|
||||||
@@ -3597,7 +3598,7 @@ paths:
|
|||||||
description: "Server's Uuid"
|
description: "Server's Uuid"
|
||||||
required: true
|
required: true
|
||||||
schema:
|
schema:
|
||||||
type: integer
|
type: string
|
||||||
responses:
|
responses:
|
||||||
'200':
|
'200':
|
||||||
description: 'Get resources by server'
|
description: 'Get resources by server'
|
||||||
@@ -3629,7 +3630,7 @@ paths:
|
|||||||
description: "Server's Uuid"
|
description: "Server's Uuid"
|
||||||
required: true
|
required: true
|
||||||
schema:
|
schema:
|
||||||
type: integer
|
type: string
|
||||||
responses:
|
responses:
|
||||||
'200':
|
'200':
|
||||||
description: 'Get domains by server'
|
description: 'Get domains by server'
|
||||||
@@ -3661,7 +3662,7 @@ paths:
|
|||||||
description: 'Server UUID'
|
description: 'Server UUID'
|
||||||
required: true
|
required: true
|
||||||
schema:
|
schema:
|
||||||
type: integer
|
type: string
|
||||||
responses:
|
responses:
|
||||||
'201':
|
'201':
|
||||||
description: 'Server validation started.'
|
description: 'Server validation started.'
|
||||||
|
|||||||
1
public/svgs/gitlab.svg
Normal file
1
public/svgs/gitlab.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 380 380"><defs><style>.cls-1{fill:#e24329;}.cls-2{fill:#fc6d26;}.cls-3{fill:#fca326;}</style></defs><g id="LOGO"><path class="cls-1" d="M282.83,170.73l-.27-.69-26.14-68.22a6.81,6.81,0,0,0-2.69-3.24,7,7,0,0,0-8,.43,7,7,0,0,0-2.32,3.52l-17.65,54H154.29l-17.65-54A6.86,6.86,0,0,0,134.32,99a7,7,0,0,0-8-.43,6.87,6.87,0,0,0-2.69,3.24L97.44,170l-.26.69a48.54,48.54,0,0,0,16.1,56.1l.09.07.24.17,39.82,29.82,19.7,14.91,12,9.06a8.07,8.07,0,0,0,9.76,0l12-9.06,19.7-14.91,40.06-30,.1-.08A48.56,48.56,0,0,0,282.83,170.73Z"/><path class="cls-2" d="M282.83,170.73l-.27-.69a88.3,88.3,0,0,0-35.15,15.8L190,229.25c19.55,14.79,36.57,27.64,36.57,27.64l40.06-30,.1-.08A48.56,48.56,0,0,0,282.83,170.73Z"/><path class="cls-3" d="M153.43,256.89l19.7,14.91,12,9.06a8.07,8.07,0,0,0,9.76,0l12-9.06,19.7-14.91S209.55,244,190,229.25C170.45,244,153.43,256.89,153.43,256.89Z"/><path class="cls-2" d="M132.58,185.84A88.19,88.19,0,0,0,97.44,170l-.26.69a48.54,48.54,0,0,0,16.1,56.1l.09.07.24.17,39.82,29.82s17-12.85,36.57-27.64Z"/></g></svg>
|
||||||
|
After Width: | Height: | Size: 1.0 KiB |
@@ -1,5 +1,6 @@
|
|||||||
<form wire:submit.prevent='submit' class="flex flex-col w-full gap-2">
|
<form wire:submit.prevent='submit' class="flex flex-col w-full gap-2">
|
||||||
<div class="pb-2">Note: If a service has a defined port, do not delete it. <br>If you want to use your custom domain, you can add it with a port.</div>
|
<div class="pb-2">Note: If a service has a defined port, do not delete it. <br>If you want to use your custom
|
||||||
|
domain, you can add it with a port.</div>
|
||||||
<x-forms.input placeholder="https://app.coolify.io" label="Domains" id="application.fqdn"
|
<x-forms.input placeholder="https://app.coolify.io" label="Domains" id="application.fqdn"
|
||||||
helper="You can specify one domain with path or more with comma. You can specify a port to bind the domain to.<br><br><span class='text-helper'>Example</span><br>- http://app.coolify.io,https://cloud.coolify.io/dashboard<br>- http://app.coolify.io/api/v3<br>- http://app.coolify.io:3000 -> app.coolify.io will point to port 3000 inside the container. "></x-forms.input>
|
helper="You can specify one domain with path or more with comma. You can specify a port to bind the domain to.<br><br><span class='text-helper'>Example</span><br>- http://app.coolify.io,https://cloud.coolify.io/dashboard<br>- http://app.coolify.io/api/v3<br>- http://app.coolify.io:3000 -> app.coolify.io will point to port 3000 inside the container. "></x-forms.input>
|
||||||
<x-forms.button type="submit">Save</x-forms.button>
|
<x-forms.button type="submit">Save</x-forms.button>
|
||||||
|
|||||||
@@ -73,7 +73,7 @@
|
|||||||
Traefik
|
Traefik
|
||||||
</x-forms.button>
|
</x-forms.button>
|
||||||
<x-forms.button class="box" wire:click="select_proxy('CADDY')">
|
<x-forms.button class="box" wire:click="select_proxy('CADDY')">
|
||||||
Caddy (experimental)
|
Caddy
|
||||||
</x-forms.button>
|
</x-forms.button>
|
||||||
<x-forms.button disabled class="box">
|
<x-forms.button disabled class="box">
|
||||||
Nginx
|
Nginx
|
||||||
|
|||||||
@@ -36,6 +36,8 @@ services:
|
|||||||
- GOOGLE_CLIENT_ID=${GOOGLE_CLIENT_ID}
|
- GOOGLE_CLIENT_ID=${GOOGLE_CLIENT_ID}
|
||||||
- GOOGLE_CLIENT_SECRET=${GOOGLE_CLIENT_SECRET}
|
- GOOGLE_CLIENT_SECRET=${GOOGLE_CLIENT_SECRET}
|
||||||
- ASSET_PREFIX_URL=${ASSET_PREFIX_URL}
|
- ASSET_PREFIX_URL=${ASSET_PREFIX_URL}
|
||||||
|
- CRON_SECRET=$SERVICE_BASE64_64_CRON
|
||||||
|
- ENCRYPTION_KEY=$SERVICE_BASE64_64_ENCRYPTION
|
||||||
volumes:
|
volumes:
|
||||||
- formbricks-uploads:/apps/web/uploads/
|
- formbricks-uploads:/apps/web/uploads/
|
||||||
depends_on:
|
depends_on:
|
||||||
|
|||||||
34
templates/compose/gitlab.yaml
Normal file
34
templates/compose/gitlab.yaml
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
# documentation: https://docs.gitlab.com/ee/install/docker.html
|
||||||
|
# slogan: The all-in-one DevOps platform for seamless collaboration and continuous delivery.
|
||||||
|
# tags: gitlab, devops, continuousintegration, continuousdelivery, versioncontrol, collaboration, ci/cd, sourcecodemanagement, automation, codereview, agiledevelopment, projectmanagement, opensource, repositoryhosting, pipelineautomation, git, softwaredevelopment, issuetracking, teamcollaboration, deploymentautomation, securityintegration
|
||||||
|
# logo: svgs/gitlab.svg
|
||||||
|
# port: 80
|
||||||
|
|
||||||
|
services:
|
||||||
|
gitlab:
|
||||||
|
image: "gitlab/gitlab-ce:latest"
|
||||||
|
environment:
|
||||||
|
- SERVICE_FQDN_GITLAB_80
|
||||||
|
- TZ=${TZ:-UTC}
|
||||||
|
- GITLAB_TIMEZONE=${GITLAB_TIMEZONE:-UTC}
|
||||||
|
- GITLAB_ROOT_PASSWORD=$SERVICE_PASSWORD_GITLAB
|
||||||
|
- EXTERNAL_URL=$SERVICE_FQDN_GITLAB
|
||||||
|
- GITLAB_HOST=$SERVICE_FQDN_GITLAB
|
||||||
|
- GITLAB_SMTP_ENABLE=${GITLAB_SMTP_ENABLE:-false}
|
||||||
|
- GITLAB_SMTP_ADDRESS=$GITLAB_SMTP_ADDRESS
|
||||||
|
- GITLAB_SMTP_PORT=${GITLAB_SMTP_PORT:-587}
|
||||||
|
- GITLAB_SMTP_USER_NAME=${GITLAB_SMTP_USER_NAME}
|
||||||
|
- GITLAB_SMTP_PASSWORD=${GITLAB_SMTP_PASSWORD}
|
||||||
|
- GITLAB_SMTP_DOMAIN=${GITLAB_SMTP_DOMAIN}
|
||||||
|
- GITLAB_STARTTLS_AUTO=${GITLAB_STARTTLS_AUTO:-true}
|
||||||
|
- GITLAB_SMTP_TLS=${GITLAB_SMTP_TLS:-false}
|
||||||
|
- GITLAB_EMAIL_FROM=${GITLAB_EMAIL_FROM}
|
||||||
|
- GITLAB_EMAIL_REPLY_TO=$GITLAB_EMAIL_REPLY_TO
|
||||||
|
- 'GITLAB_OMNIBUS_CONFIG=external_url "${SERVICE_FQDN_GITLAB}"; nginx["listen_https"] = false; nginx["listen_port"] = 80; gitlab_rails["gitlab_shell_ssh_port"] = 2222; gitlab_rails["smtp_enable"] = ${GITLAB_SMTP_ENABLE}; gitlab_rails["smtp_address"] = "${GITLAB_SMTP_ADDRESS}"; gitlab_rails["smtp_port"] = ${GITLAB_SMTP_PORT}; gitlab_rails["smtp_user_name"] = "${GITLAB_SMTP_USER_NAME}"; gitlab_rails["smtp_password"] = "${GITLAB_SMTP_PASSWORD}"; gitlab_rails["smtp_domain"] = "${GITLAB_SMTP_DOMAIN}"; gitlab_rails["smtp_authentication"] = "login"; gitlab_rails["smtp_enable_starttls_auto"] = ${GITLAB_STARTTLS_AUTO}; gitlab_rails["smtp_tls"] = ${GITLAB_SMTP_TLS}; gitlab_rails["gitlab_email_from"] = "${GITLAB_EMAIL_FROM}"; gitlab_rails["gitlab_email_reply_to"] = "${GITLAB_EMAIL_REPLY_TO}";'
|
||||||
|
ports:
|
||||||
|
- "2222:22"
|
||||||
|
volumes:
|
||||||
|
- "gitlab-config:/etc/gitlab"
|
||||||
|
- "gitlab-logs:/var/log/gitlab"
|
||||||
|
- "gitlab-data:/var/opt/gitlab"
|
||||||
|
shm_size: 256m
|
||||||
File diff suppressed because one or more lines are too long
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"coolify": {
|
"coolify": {
|
||||||
"v4": {
|
"v4": {
|
||||||
"version": "4.0.0-beta.319"
|
"version": "4.0.0-beta.320"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user