Merge branch 'next' into next

This commit is contained in:
Leonardo Cabeza
2024-07-22 16:58:52 -05:00
committed by GitHub
15 changed files with 78 additions and 81 deletions

View File

@@ -40,7 +40,7 @@ body:
label: Cloud? label: Cloud?
description: "Are you using the cloud version of Coolify?" description: "Are you using the cloud version of Coolify?"
options: options:
- label: Yes - label: 'Yes'
required: false required: false
- label: No - label: 'No'
required: false required: false

View File

@@ -9,7 +9,7 @@ class StopApplication
{ {
use AsAction; use AsAction;
public function handle(Application $application) public function handle(Application $application, bool $previewDeployments = false)
{ {
if ($application->destination->server->isSwarm()) { if ($application->destination->server->isSwarm()) {
instant_remote_process(["docker stack rm {$application->uuid}"], $application->destination->server); instant_remote_process(["docker stack rm {$application->uuid}"], $application->destination->server);
@@ -26,7 +26,12 @@ class StopApplication
if (! $server->isFunctional()) { if (! $server->isFunctional()) {
return 'Server is not functional'; return 'Server is not functional';
} }
$containers = getCurrentApplicationContainerStatus($server, $application->id, 0); if ($previewDeployments) {
$containers = getCurrentApplicationContainerStatus($server, $application->id, includePullrequests: true);
} else {
$containers = getCurrentApplicationContainerStatus($server, $application->id, 0);
}
ray($containers);
if ($containers->count() > 0) { if ($containers->count() > 0) {
foreach ($containers as $container) { foreach ($containers as $container) {
$containerName = data_get($container, 'Names'); $containerName = data_get($container, 'Names');

View File

@@ -18,7 +18,7 @@ class CleanupUnreachableServers extends Command
if ($servers->count() > 0) { if ($servers->count() > 0) {
foreach ($servers as $server) { foreach ($servers as $server) {
echo "Cleanup unreachable server ($server->id) with name $server->name"; echo "Cleanup unreachable server ($server->id) with name $server->name";
send_internal_notification("Server $server->name is unreachable for 7 days. Cleaning up..."); // send_internal_notification("Server $server->name is unreachable for 7 days. Cleaning up...");
$server->update([ $server->update([
'ip' => '1.2.3.4', 'ip' => '1.2.3.4',
]); ]);

View File

@@ -340,7 +340,6 @@ class Github extends Controller
return response("Nothing to do. No applications found with branch '$base_branch'."); return response("Nothing to do. No applications found with branch '$base_branch'.");
} }
} }
foreach ($applications as $application) { foreach ($applications as $application) {
$isFunctional = $application->destination->server->isFunctional(); $isFunctional = $application->destination->server->isFunctional();
if (! $isFunctional) { if (! $isFunctional) {
@@ -432,8 +431,13 @@ class Github extends Controller
if ($action === 'closed' || $action === 'close') { if ($action === 'closed' || $action === 'close') {
$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) {
$container_name = generateApplicationContainerName($application, $pull_request_id); $containers = getCurrentApplicationContainerStatus($application->destination->server, $application->id, $pull_request_id);
instant_remote_process(["docker rm -f $container_name"], $application->destination->server); if ($containers->isNotEmpty()) {
$containers->each(function ($container) use ($application) {
$container_name = data_get($container, 'Names');
instant_remote_process(["docker rm -f $container_name"], $application->destination->server);
});
}
ApplicationPullRequestUpdateJob::dispatchSync(application: $application, preview: $found, status: ProcessStatus::CLOSED); ApplicationPullRequestUpdateJob::dispatchSync(application: $application, preview: $found, status: ProcessStatus::CLOSED);
$found->delete(); $found->delete();

View File

@@ -490,10 +490,10 @@ class ApplicationDeploymentJob implements ShouldBeEncrypted, ShouldQueue
// Start compose file // Start compose file
if ($this->application->settings->is_raw_compose_deployment_enabled) { if ($this->application->settings->is_raw_compose_deployment_enabled) {
if ($this->docker_compose_custom_start_command) { if ($this->docker_compose_custom_start_command) {
$this->write_deployment_configurations();
$this->execute_remote_command( $this->execute_remote_command(
[executeInDocker($this->deployment_uuid, "cd {$this->workdir} && {$this->docker_compose_custom_start_command}"), 'hidden' => true], [executeInDocker($this->deployment_uuid, "cd {$this->workdir} && {$this->docker_compose_custom_start_command}"), 'hidden' => true],
); );
$this->write_deployment_configurations();
} else { } else {
$this->write_deployment_configurations(); $this->write_deployment_configurations();
$server_workdir = $this->application->workdir(); $server_workdir = $this->application->workdir();
@@ -510,22 +510,21 @@ class ApplicationDeploymentJob implements ShouldBeEncrypted, ShouldQueue
} }
} else { } else {
if ($this->docker_compose_custom_start_command) { if ($this->docker_compose_custom_start_command) {
$this->write_deployment_configurations();
$this->execute_remote_command( $this->execute_remote_command(
[executeInDocker($this->deployment_uuid, "cd {$this->basedir} && {$this->docker_compose_custom_start_command}"), 'hidden' => true], [executeInDocker($this->deployment_uuid, "cd {$this->basedir} && {$this->docker_compose_custom_start_command}"), 'hidden' => true],
); );
$this->write_deployment_configurations();
} else { } else {
$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 {$this->workdir}/{$this->env_filename}";
} }
$command .= " --project-name {$this->application->uuid} --project-directory {$this->workdir} -f {$this->workdir}{$this->docker_compose_location} up -d"; $command .= " --project-name {$this->application->uuid} --project-directory {$this->workdir} -f {$this->workdir}{$this->docker_compose_location} up -d";
ray($command);
$this->write_deployment_configurations();
$this->execute_remote_command( $this->execute_remote_command(
[executeInDocker($this->deployment_uuid, $command), 'hidden' => true], [executeInDocker($this->deployment_uuid, $command), 'hidden' => true],
); );
$this->write_deployment_configurations();
} }
} }
@@ -615,14 +614,14 @@ class ApplicationDeploymentJob implements ShouldBeEncrypted, ShouldQueue
$this->server = $this->original_server; $this->server = $this->original_server;
} }
if (str($this->configuration_dir)->isNotEmpty()) { if (str($this->configuration_dir)->isNotEmpty()) {
ray("docker cp {$this->deployment_uuid}:{$this->workdir} {$this->configuration_dir}");
$this->execute_remote_command( $this->execute_remote_command(
[ [
"mkdir -p $this->configuration_dir", "mkdir -p $this->configuration_dir",
], ],
[ // removing this now as we are using docker cp
"rm -rf $this->configuration_dir/{*,.*}", // [
], // "rm -rf $this->configuration_dir/{*,.*}",
// ],
[ [
"docker cp {$this->deployment_uuid}:{$this->workdir}/. {$this->configuration_dir}", "docker cp {$this->deployment_uuid}:{$this->workdir}/. {$this->configuration_dir}",
], ],

View File

@@ -40,7 +40,7 @@ class DeleteResourceJob implements ShouldBeEncrypted, ShouldQueue
switch ($this->resource->type()) { switch ($this->resource->type()) {
case 'application': case 'application':
$persistentStorages = $this->resource?->persistentStorages()?->get(); $persistentStorages = $this->resource?->persistentStorages()?->get();
StopApplication::run($this->resource); StopApplication::run($this->resource, previewDeployments: true);
break; break;
case 'standalone-postgresql': case 'standalone-postgresql':
case 'standalone-redis': case 'standalone-redis':

View File

@@ -87,19 +87,21 @@ class LocalFileVolume extends BaseModel
$fileVolume->save(); $fileVolume->save();
throw new \Exception('The following file is a directory on the server, but you are trying to mark it as a file. <br><br>Please delete the directory on the server or mark it as directory.'); throw new \Exception('The following file is a directory on the server, but you are trying to mark it as a file. <br><br>Please delete the directory on the server or mark it as directory.');
} }
if (! $fileVolume->is_directory && $isDir == 'NOK') { if ($isDir == 'NOK' && ! $fileVolume->is_directory) {
$chmod = data_get($fileVolume, 'chmod');
$chown = data_get($fileVolume, 'chown');
if ($content) { if ($content) {
$content = base64_encode($content); $content = base64_encode($content);
$chmod = $fileVolume->chmod;
$chown = $fileVolume->chown;
$commands->push("echo '$content' | base64 -d | tee $path > /dev/null"); $commands->push("echo '$content' | base64 -d | tee $path > /dev/null");
$commands->push("chmod +x $path"); } else {
if ($chown) { $commands->push("touch $path");
$commands->push("chown $chown $path"); }
} $commands->push("chmod +x $path");
if ($chmod) { if ($chown) {
$commands->push("chmod $chmod $path"); $commands->push("chown $chown $path");
} }
if ($chmod) {
$commands->push("chmod $chmod $path");
} }
} elseif ($isDir == 'NOK' && $fileVolume->is_directory) { } elseif ($isDir == 'NOK' && $fileVolume->is_directory) {
$commands->push("mkdir -p $path > /dev/null 2>&1 || true"); $commands->push("mkdir -p $path > /dev/null 2>&1 || true");

View File

@@ -73,6 +73,13 @@ function getFilesystemVolumesFromServer(ServiceApplication|ServiceDatabase|Appli
"echo '$content' | base64 -d | tee $fileLocation", "echo '$content' | base64 -d | tee $fileLocation",
], $server); ], $server);
} elseif ($isFile == 'NOK' && $isDir == 'NOK' && $fileVolume->is_directory && $isInit) { } elseif ($isFile == 'NOK' && $isDir == 'NOK' && $fileVolume->is_directory && $isInit) {
// Does not exists (no dir or file), flagged as directory, is init
$fileVolume->content = null;
$fileVolume->is_directory = true;
$fileVolume->save();
instant_remote_process(["mkdir -p $fileLocation"], $server);
} elseif ($isFile == 'NOK' && $isDir == 'NOK' && ! $fileVolume->is_directory && $isInit && ! $content) {
// Does not exists (no dir or file), not flagged as directory, is init, has no content => create directory
$fileVolume->content = null; $fileVolume->content = null;
$fileVolume->is_directory = true; $fileVolume->is_directory = true;
$fileVolume->save(); $fileVolume->save();

View File

@@ -1735,6 +1735,7 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
if (is_array($volume)) { if (is_array($volume)) {
return data_get($volume, 'source'); return data_get($volume, 'source');
} }
dispatch(new ServerFilesFromServerJob($resource));
return $volume->value(); return $volume->value();
}); });

View File

@@ -1,32 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('services', function (Blueprint $table) {
$table->string('git_repository')->nullable();
$table->string('git_branch')->nullable();
$table->nullableMorphs('source');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('services', function (Blueprint $table) {
$table->dropColumn('git_repository');
$table->dropColumn('git_branch');
$table->dropMorphs('source');
});
}
};

View File

@@ -106,7 +106,7 @@
<livewire:project.shared.destination :resource="$application" :servers="$servers" /> <livewire:project.shared.destination :resource="$application" :servers="$servers" />
</div> </div>
<div x-cloak x-show="activeTab === 'storages'"> <div x-cloak x-show="activeTab === 'storages'">
<livewire:project.service.storage :resource="$application" /> <livewire:project.service.storage :resource="$application" lazy />
</div> </div>
<div x-cloak x-show="activeTab === 'webhooks'"> <div x-cloak x-show="activeTab === 'webhooks'">
<livewire:project.shared.webhooks :resource="$application" lazy /> <livewire:project.shared.webhooks :resource="$application" lazy />

View File

@@ -8,25 +8,35 @@
<h3 class="pt-4">Limit CPUs</h3> <h3 class="pt-4">Limit CPUs</h3>
<div class="flex gap-2"> <div class="flex gap-2">
<x-forms.input placeholder="1.5" <x-forms.input placeholder="1.5"
helper="0 means use all CPUs. Floating point number, like 0.002 or 1.5. More info <a class='dark:text-white underline' target='_blank' href='https://docs.docker.com/engine/reference/run/#cpu-share-constraint'>here</a>." helper="0 means use all CPUs. Floating point number, like 0.002 or 1.5. More info <a class='underline dark:text-white' target='_blank' href='https://docs.docker.com/engine/reference/run/#cpu-share-constraint'>here</a>."
label="Number of CPUs" id="resource.limits_cpus" /> label="Number of CPUs" id="resource.limits_cpus" />
<x-forms.input placeholder="0-2" <x-forms.input placeholder="0-2"
helper="Empty means, use all CPU sets. 0-2 will use CPU 0, CPU 1 and CPU 2. More info <a class='dark:text-white underline' target='_blank' href='https://docs.docker.com/engine/reference/run/#cpu-share-constraint'>here</a>." helper="Empty means, use all CPU sets. 0-2 will use CPU 0, CPU 1 and CPU 2. More info <a class='underline dark:text-white' target='_blank' href='https://docs.docker.com/engine/reference/run/#cpu-share-constraint'>here</a>."
label="CPU sets to use" id="resource.limits_cpuset" /> label="CPU sets to use" id="resource.limits_cpuset" />
<x-forms.input placeholder="1024" <x-forms.input placeholder="1024"
helper="More info <a class='dark:text-white underline' target='_blank' href='https://docs.docker.com/engine/reference/run/#cpu-share-constraint'>here</a>." helper="More info <a class='underline dark:text-white' target='_blank' href='https://docs.docker.com/engine/reference/run/#cpu-share-constraint'>here</a>."
label="CPU Weight" id="resource.limits_cpu_shares" /> label="CPU Weight" id="resource.limits_cpu_shares" />
</div> </div>
<h3 class="pt-4">Limit Memory</h3> <h3 class="pt-4">Limit Memory</h3>
<div class="flex gap-2"> <div class="flex flex-col gap-2">
<x-forms.input placeholder="69b or 420k or 1337m or 1g" label="Soft Memory Limit" <div class="flex gap-2">
id="resource.limits_memory_reservation" /> <x-forms.input
<x-forms.input placeholder="69b or 420k or 1337m or 1g" label="Maximum Memory Limit" helper="Examples: 69b (byte) or 420k (kilobyte) or 1337m (megabyte) or 1g (gigabyte).<br>More info <a class='underline dark:text-white' target='_blank' href='https://docs.docker.com/compose/compose-file/05-services/#mem_reservation'>here</a>."
id="resource.limits_memory" /> label="Soft Memory Limit" id="resource.limits_memory_reservation" />
<x-forms.input placeholder="69b or 420k or 1337m or 1g" label="Maximum Swap Limit" <x-forms.input
id="resource.limits_memory_swap" /> helper="0-100.<br>More info <a class='underline dark:text-white' target='_blank' href='https://docs.docker.com/compose/compose-file/05-services/#mem_swappiness'>here</a>."
<x-forms.input placeholder="0-100" type="number" min="0" max="100" label="Swappiness" type="number" min="0" max="100" label="Swappiness"
id="resource.limits_memory_swappiness" /> id="resource.limits_memory_swappiness" />
</div>
<div class="flex gap-2">
<x-forms.input
helper="Examples: 69b (byte) or 420k (kilobyte) or 1337m (megabyte) or 1g (gigabyte).<br>More info <a class='underline dark:text-white' target='_blank' href='https://docs.docker.com/compose/compose-file/05-services/#mem_limit'>here</a>."
label="Maximum Memory Limit" id="resource.limits_memory" />
<x-forms.input
helper="Examples:69b (byte) or 420k (kilobyte) or 1337m (megabyte) or 1g (gigabyte).<br>More info <a class='underline dark:text-white' target='_blank' href='https://docs.docker.com/compose/compose-file/05-services/#memswap_limit'>here</a>."
label="Maximum Swap Limit" id="resource.limits_memory_swap" />
</div>
</div> </div>
</form> </form>
</div> </div>

View File

@@ -5,9 +5,9 @@
x-app-env: &app-env x-app-env: &app-env
environment: environment:
- WEB_URL=http://localhost - WEB_URL=${SERVICE_FQDN_PLANE}
- DEBUG=${DEBUG:-0} - DEBUG=${DEBUG:-0}
- CORS_ALLOWED_ORIGINS=http://localhost - CORS_ALLOWED_ORIGINS=${CORS_ALLOWED_ORIGIN:-http://localhost}
# Gunicorn Workers # Gunicorn Workers
- GUNICORN_WORKERS=${GUNICORN_WORKERS:-1} - GUNICORN_WORKERS=${GUNICORN_WORKERS:-1}
#DB SETTINGS #DB SETTINGS
@@ -28,8 +28,8 @@ x-app-env: &app-env
# DATA STORE SETTINGS # DATA STORE SETTINGS
- USE_MINIO=${USE_MINIO:-1} - USE_MINIO=${USE_MINIO:-1}
- AWS_REGION=${AWS_REGION} - AWS_REGION=${AWS_REGION}
- AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID} - AWS_ACCESS_KEY_ID=$SERVICE_USER_MINIO
- AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY} - AWS_SECRET_ACCESS_KEY=$SERVICE_PASSWORD_MINIO
- AWS_S3_ENDPOINT_URL=${AWS_S3_ENDPOINT_URL:-http://plane-minio:9000} - AWS_S3_ENDPOINT_URL=${AWS_S3_ENDPOINT_URL:-http://plane-minio:9000}
- AWS_S3_BUCKET_NAME=${AWS_S3_BUCKET_NAME:-uploads} - AWS_S3_BUCKET_NAME=${AWS_S3_BUCKET_NAME:-uploads}
- MINIO_ROOT_USER=$SERVICE_USER_MINIO - MINIO_ROOT_USER=$SERVICE_USER_MINIO
@@ -39,13 +39,14 @@ x-app-env: &app-env
# Admin and Space URLs # Admin and Space URLs
- ADMIN_BASE_URL=${ADMIN_BASE_URL} - ADMIN_BASE_URL=${ADMIN_BASE_URL}
- SPACE_BASE_URL=${SPACE_BASE_URL} - SPACE_BASE_URL=${SPACE_BASE_URL}
- APP_BASE_URL=${APP_BASE_URL} - APP_BASE_URL=${SERVICE_FQDN_PLANE}
services: services:
proxy: proxy:
environment: environment:
- SERVICE_FQDN_PLANE - SERVICE_FQDN_PLANE
- FILE_SIZE_LIMIT=${FILE_SIZE_LIMIT:-5242880} - FILE_SIZE_LIMIT=${FILE_SIZE_LIMIT:-5242880}
- BUCKET_NAME=${BUCKET_NAME:-uploads}
image: makeplane/plane-proxy:stable image: makeplane/plane-proxy:stable
depends_on: depends_on:
- web - web

View File

@@ -301,7 +301,7 @@ services:
- DEFAULT_ORGANIZATION_NAME=${STUDIO_DEFAULT_ORGANIZATION:-Default Organization} - DEFAULT_ORGANIZATION_NAME=${STUDIO_DEFAULT_ORGANIZATION:-Default Organization}
- DEFAULT_PROJECT_NAME=${STUDIO_DEFAULT_PROJECT:-Default Project} - DEFAULT_PROJECT_NAME=${STUDIO_DEFAULT_PROJECT:-Default Project}
- SUPABASE_URL=${SERVICE_FQDN_SUPABASEKONG:-http://supabase-kong:8000} - SUPABASE_URL=${SERVICE_FQDN_SUPABASEKONG}
- SUPABASE_PUBLIC_URL=${SERVICE_FQDN_SUPABASEKONG} - SUPABASE_PUBLIC_URL=${SERVICE_FQDN_SUPABASEKONG}
- SUPABASE_ANON_KEY=${SERVICE_SUPABASEANON_KEY} - SUPABASE_ANON_KEY=${SERVICE_SUPABASEANON_KEY}
- SUPABASE_SERVICE_KEY=${SERVICE_SUPABASESERVICE_KEY} - SUPABASE_SERVICE_KEY=${SERVICE_SUPABASESERVICE_KEY}
@@ -1013,7 +1013,7 @@ services:
"/dev/null", "/dev/null",
"-H", "-H",
"Authorization: Bearer ${SERVICE_SUPABASEANON_KEY}", "Authorization: Bearer ${SERVICE_SUPABASEANON_KEY}",
"http://127.0.0.1:4000/api/tenants/realtime-dev/health" "http://127.0.0.1:4000/api/tenants/realtime-dev/health",
] ]
timeout: 5s timeout: 5s
interval: 5s interval: 5s
@@ -1182,7 +1182,7 @@ services:
retries: 3 retries: 3
environment: environment:
- JWT_SECRET=${SERVICE_PASSWORD_JWT} - JWT_SECRET=${SERVICE_PASSWORD_JWT}
- SUPABASE_URL=${SERVICE_FQDN_SUPABASEKONG:-http://supabase-kong:8000} - SUPABASE_URL=${SERVICE_FQDN_SUPABASEKONG}
- SUPABASE_ANON_KEY=${SERVICE_SUPABASEANON_KEY} - SUPABASE_ANON_KEY=${SERVICE_SUPABASEANON_KEY}
- SUPABASE_SERVICE_ROLE_KEY=${SERVICE_SUPABASESERVICE_KEY} - SUPABASE_SERVICE_ROLE_KEY=${SERVICE_SUPABASESERVICE_KEY}
- SUPABASE_DB_URL=postgresql://postgres:${SERVICE_PASSWORD_POSTGRES}@${POSTGRES_HOSTNAME:-supabase-db}:${POSTGRES_PORT:-5432}/${POSTGRES_DB:-postgres} - SUPABASE_DB_URL=postgresql://postgres:${SERVICE_PASSWORD_POSTGRES}@${POSTGRES_HOSTNAME:-supabase-db}:${POSTGRES_PORT:-5432}/${POSTGRES_DB:-postgres}

File diff suppressed because one or more lines are too long