diff --git a/README.md b/README.md
index 2abca8f58..000134c64 100644
--- a/README.md
+++ b/README.md
@@ -19,10 +19,12 @@ Thank you so much!
Special thanks to our biggest sponsors, [CCCareers](https://cccareers.org/) and [Appwrite](https://appwrite.io)!
-
+
## Github Sponsors ($15+)
+
+
@@ -32,7 +34,6 @@ Special thanks to our biggest sponsors, [CCCareers](https://cccareers.org/) and
-
## Organizations
diff --git a/app/Actions/Service/DeleteService.php b/app/Actions/Service/DeleteService.php
index e7cc049b1..2d2c10ccb 100644
--- a/app/Actions/Service/DeleteService.php
+++ b/app/Actions/Service/DeleteService.php
@@ -21,14 +21,14 @@ class DeleteService
foreach ($storages as $storage) {
$storagesToDelete->push($storage);
}
- $application->delete();
+ $application->forceDelete();
}
foreach ($service->databases()->get() as $database) {
$storages = $database->persistentStorages()->get();
foreach ($storages as $storage) {
$storagesToDelete->push($storage);
}
- $database->delete();
+ $database->forceDelete();
}
foreach ($storagesToDelete as $storage) {
$commands[] = "docker volume rm -f $storage->name";
diff --git a/app/Console/Commands/Init.php b/app/Console/Commands/Init.php
index b784c4e67..b0073e1f0 100644
--- a/app/Console/Commands/Init.php
+++ b/app/Console/Commands/Init.php
@@ -55,7 +55,8 @@ class Init extends Command
}
}
}
- private function restore_coolify_db_backup() {
+ private function restore_coolify_db_backup()
+ {
try {
$database = StandalonePostgresql::withTrashed()->find(0);
if ($database && $database->trashed()) {
@@ -73,9 +74,8 @@ class Init extends Command
'team_id' => 0,
]);
}
-
}
- } catch(\Throwable $e) {
+ } catch (\Throwable $e) {
echo "Error in restoring coolify db backup: {$e->getMessage()}\n";
}
}
@@ -138,6 +138,89 @@ class Init extends Command
}
private function cleanup_stucked_resources()
{
+
+ try {
+ $applications = Application::withTrashed()->whereNotNull('deleted_at')->get();
+ foreach ($applications as $application) {
+ echo "Deleting stucked application: {$application->name}\n";
+ $application->forceDelete();
+ }
+ } catch (\Throwable $e) {
+ echo "Error in cleaning stucked application: {$e->getMessage()}\n";
+ }
+ try {
+ $postgresqls = StandalonePostgresql::withTrashed()->whereNotNull('deleted_at')->get();
+ foreach ($postgresqls as $postgresql) {
+ echo "Deleting stucked postgresql: {$postgresql->name}\n";
+ $postgresql->forceDelete();
+ }
+ } catch (\Throwable $e) {
+ echo "Error in cleaning stucked postgresql: {$e->getMessage()}\n";
+ }
+ try {
+ $redis = StandaloneRedis::withTrashed()->whereNotNull('deleted_at')->get();
+ foreach ($redis as $redis) {
+ echo "Deleting stucked redis: {$redis->name}\n";
+ $redis->forceDelete();
+ }
+ } catch (\Throwable $e) {
+ echo "Error in cleaning stucked redis: {$e->getMessage()}\n";
+ }
+ try {
+ $mongodbs = StandaloneMongodb::withTrashed()->whereNotNull('deleted_at')->get();
+ foreach ($mongodbs as $mongodb) {
+ echo "Deleting stucked mongodb: {$mongodb->name}\n";
+ $mongodb->forceDelete();
+ }
+ } catch (\Throwable $e) {
+ echo "Error in cleaning stucked mongodb: {$e->getMessage()}\n";
+ }
+ try {
+ $mysqls = StandaloneMysql::withTrashed()->whereNotNull('deleted_at')->get();
+ foreach ($mysqls as $mysql) {
+ echo "Deleting stucked mysql: {$mysql->name}\n";
+ $mysql->forceDelete();
+ }
+ } catch (\Throwable $e) {
+ echo "Error in cleaning stucked mysql: {$e->getMessage()}\n";
+ }
+ try {
+ $mariadbs = StandaloneMariadb::withTrashed()->whereNotNull('deleted_at')->get();
+ foreach ($mariadbs as $mariadb) {
+ echo "Deleting stucked mariadb: {$mariadb->name}\n";
+ $mariadb->forceDelete();
+ }
+ } catch (\Throwable $e) {
+ echo "Error in cleaning stucked mariadb: {$e->getMessage()}\n";
+ }
+ try {
+ $services = Service::withTrashed()->whereNotNull('deleted_at')->get();
+ foreach ($services as $service) {
+ echo "Deleting stucked service: {$service->name}\n";
+ $service->forceDelete();
+ }
+ } catch (\Throwable $e) {
+ echo "Error in cleaning stucked service: {$e->getMessage()}\n";
+ }
+ try {
+ $serviceApps = ServiceApplication::withTrashed()->whereNotNull('deleted_at')->get();
+ foreach ($serviceApps as $serviceApp) {
+ echo "Deleting stucked serviceapp: {$serviceApp->name}\n";
+ $serviceApp->forceDelete();
+ }
+ } catch (\Throwable $e) {
+ echo "Error in cleaning stucked serviceapp: {$e->getMessage()}\n";
+ }
+ try {
+ $serviceDbs = ServiceDatabase::withTrashed()->whereNotNull('deleted_at')->get();
+ foreach ($serviceDbs as $serviceDb) {
+ echo "Deleting stucked serviceapp: {$serviceDb->name}\n";
+ $serviceDb->forceDelete();
+ }
+ } catch (\Throwable $e) {
+ echo "Error in cleaning stucked serviceapp: {$e->getMessage()}\n";
+ }
+
// Cleanup any resources that are not attached to any environment or destination or server
try {
$applications = Application::all();
diff --git a/app/Jobs/ApplicationDeploymentJob.php b/app/Jobs/ApplicationDeploymentJob.php
index cb0b11679..5ce4040e7 100644
--- a/app/Jobs/ApplicationDeploymentJob.php
+++ b/app/Jobs/ApplicationDeploymentJob.php
@@ -164,11 +164,15 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
$ips = collect([]);
if (count($allContainers) > 0) {
$allContainers = $allContainers[0];
+ $allContainers = collect($allContainers)->sort()->values();
foreach ($allContainers as $container) {
$containerName = data_get($container, 'Name');
if ($containerName === 'coolify-proxy') {
continue;
}
+ if (preg_match('/-(\d{12})/',$containerName)) {
+ continue;
+ }
$containerIp = data_get($container, 'IPv4Address');
if ($containerName && $containerIp) {
$containerIp = str($containerIp)->before('/');
@@ -446,8 +450,12 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
$this->generate_image_names();
$this->cleanup_git();
$this->application->loadComposeFile(isInit: false);
- $composeFile = $this->application->parseCompose(pull_request_id: $this->pull_request_id);
- $yaml = Yaml::dump($composeFile->toArray(), 10);
+ if ($this->application->settings->is_raw_compose_deployment_enabled) {
+ $yaml = $composeFile = $this->application->docker_compose_raw;
+ } else {
+ $composeFile = $this->application->parseCompose(pull_request_id: $this->pull_request_id);
+ $yaml = Yaml::dump($composeFile->toArray(), 10);
+ }
$this->docker_compose_base64 = base64_encode($yaml);
$this->execute_remote_command([
executeInDocker($this->deployment_uuid, "echo '{$this->docker_compose_base64}' | base64 -d > {$this->workdir}{$this->docker_compose_location}"), "hidden" => true
@@ -871,11 +879,11 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
private function nixpacks_build_cmd()
{
$this->generate_env_variables();
- $cacheKey = $this->application->uuid;
- if ($this->pull_request_id !== 0) {
- $cacheKey = "{$this->application->uuid}-pr-{$this->pull_request_id}";
- }
- $nixpacks_command = "nixpacks build --cache-key '{$cacheKey}' -o {$this->workdir} {$this->env_args} --no-error-without-start";
+ // $cacheKey = $this->application->uuid;
+ // if ($this->pull_request_id !== 0) {
+ // $cacheKey = "{$this->application->uuid}-pr-{$this->pull_request_id}";
+ // }
+ $nixpacks_command = "nixpacks build {$this->env_args} --no-error-without-start";
if ($this->application->build_command) {
$nixpacks_command .= " --build-cmd \"{$this->application->build_command}\"";
}
@@ -885,7 +893,7 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
if ($this->application->install_command) {
$nixpacks_command .= " --install-cmd \"{$this->application->install_command}\"";
}
- $nixpacks_command .= " {$this->workdir}";
+ $nixpacks_command .= " -o {$this->workdir} {$this->workdir}";
return $nixpacks_command;
}
@@ -1129,7 +1137,8 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
// Add PORT if not exists, use the first port as default
if ($environment_variables->filter(fn ($env) => Str::of($env)->contains('PORT'))->isEmpty()) {
$environment_variables->push("PORT={$ports[0]}");
- } if ($environment_variables->filter(fn ($env) => Str::of($env)->contains('SOURCE_COMMIT'))->isEmpty()) {
+ }
+ if ($environment_variables->filter(fn ($env) => Str::of($env)->contains('SOURCE_COMMIT'))->isEmpty()) {
if (!is_null($this->commit)) {
$environment_variables->push("SOURCE_COMMIT={$this->commit}");
}
@@ -1192,6 +1201,9 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
if ($this->application->settings->is_static || $this->application->build_pack === 'static') {
if ($this->application->static_image) {
$this->pull_latest_image($this->application->static_image);
+ $this->execute_remote_command(
+ ["echo -n 'Continue with the building process.'"],
+ );
}
if ($this->application->build_pack === 'static') {
$dockerfile = base64_encode("FROM {$this->application->static_image}
@@ -1218,9 +1230,23 @@ COPY ./nginx.conf /etc/nginx/conf.d/default.conf");
}
}");
} else {
- $this->execute_remote_command([
- executeInDocker($this->deployment_uuid, "docker build $this->buildTarget $this->addHosts --network host -f {$this->workdir}{$this->dockerfile_location} {$this->build_args} --progress plain -t $this->build_image_name {$this->workdir}"), "hidden" => true
- ]);
+ if ($this->application->build_pack === 'nixpacks') {
+ $this->execute_remote_command(
+ [
+ executeInDocker($this->deployment_uuid, "cp {$this->workdir}/Dockerfile {$this->workdir}/.nixpacks/Dockerfile")
+ ],
+ );
+ }
+ if ($this->force_rebuild) {
+ $this->execute_remote_command([
+ executeInDocker($this->deployment_uuid, "docker build --no-cache $this->buildTarget $this->addHosts --network host -f {$this->workdir}{$this->dockerfile_location} {$this->build_args} --progress plain -t $this->build_image_name {$this->workdir}"), "hidden" => true
+ ]);
+ } else {
+ $this->execute_remote_command([
+ executeInDocker($this->deployment_uuid, "docker build $this->buildTarget $this->addHosts --network host -f {$this->workdir}{$this->dockerfile_location} {$this->build_args} --progress plain -t $this->build_image_name {$this->workdir}"), "hidden" => true
+ ]);
+ }
+ // }
$dockerfile = base64_encode("FROM {$this->application->static_image}
WORKDIR /usr/share/nginx/html/
@@ -1263,9 +1289,23 @@ COPY ./nginx.conf /etc/nginx/conf.d/default.conf");
executeInDocker($this->deployment_uuid, "docker build --pull $this->buildTarget $this->addHosts --network host -f {$this->workdir}{$this->dockerfile_location} {$this->build_args} --progress plain -t $this->production_image_name {$this->workdir}"), "hidden" => true
]);
} else {
- $this->execute_remote_command([
- executeInDocker($this->deployment_uuid, "docker build $this->buildTarget $this->addHosts --network host -f {$this->workdir}{$this->dockerfile_location} {$this->build_args} --progress plain -t $this->production_image_name {$this->workdir}"), "hidden" => true
- ]);
+ if ($this->application->build_pack === 'nixpacks') {
+ $this->execute_remote_command(
+ [
+ executeInDocker($this->deployment_uuid, "cp {$this->workdir}/Dockerfile {$this->workdir}/.nixpacks/Dockerfile")
+ ],
+ );
+ }
+
+ if ($this->force_rebuild) {
+ $this->execute_remote_command([
+ executeInDocker($this->deployment_uuid, "docker build --no-cache $this->buildTarget $this->addHosts --network host -f {$this->workdir}{$this->dockerfile_location} {$this->build_args} --progress plain -t $this->production_image_name {$this->workdir}"), "hidden" => true
+ ]);
+ } else {
+ $this->execute_remote_command([
+ executeInDocker($this->deployment_uuid, "docker build $this->buildTarget $this->addHosts --network host -f {$this->workdir}{$this->dockerfile_location} {$this->build_args} --progress plain -t $this->production_image_name {$this->workdir}"), "hidden" => true
+ ]);
+ }
}
}
$this->execute_remote_command([
@@ -1291,6 +1331,9 @@ COPY ./nginx.conf /etc/nginx/conf.d/default.conf");
});
} else {
$this->application_deployment_queue->addLogEntry("New container is not healthy, rolling back to the old container.");
+ $this->application_deployment_queue->update([
+ 'status' => ApplicationDeploymentStatus::FAILED->value,
+ ]);
$this->execute_remote_command(
[executeInDocker($this->deployment_uuid, "docker rm -f $this->container_name >/dev/null 2>&1"), "hidden" => true, "ignore_errors" => true],
);
diff --git a/app/Livewire/Project/Application/General.php b/app/Livewire/Project/Application/General.php
index 39cb15b27..f54a46e09 100644
--- a/app/Livewire/Project/Application/General.php
+++ b/app/Livewire/Project/Application/General.php
@@ -66,6 +66,7 @@ class General extends Component
'application.settings.is_static' => 'boolean|required',
'application.docker_compose_custom_start_command' => 'nullable',
'application.docker_compose_custom_build_command' => 'nullable',
+ 'application.settings.is_raw_compose_deployment_enabled' => 'boolean|required',
];
protected $validationAttributes = [
'application.name' => 'name',
@@ -98,6 +99,7 @@ class General extends Component
'application.settings.is_static' => 'Is static',
'application.docker_compose_custom_start_command' => 'Docker compose custom start command',
'application.docker_compose_custom_build_command' => 'Docker compose custom build command',
+ 'application.settings.is_raw_compose_deployment_enabled' => 'Is raw compose deployment enabled',
];
public function mount()
{
@@ -114,6 +116,11 @@ class General extends Component
}
$this->isConfigurationChanged = $this->application->isConfigurationChanged();
$this->customLabels = $this->application->parseContainerLabels();
+ if (!$this->customLabels && $this->application->destination->server->proxyType() === 'TRAEFIK_V2') {
+ $this->customLabels = str(implode(",", generateLabelsApplication($this->application)))->replace(',', "\n");
+ $this->application->custom_labels = base64_encode($this->customLabels);
+ $this->application->save();
+ }
$this->initialDockerComposeLocation = $this->application->docker_compose_location;
$this->checkLabelUpdates();
}
@@ -199,7 +206,12 @@ class General extends Component
public function submit($showToaster = true)
{
try {
- ray($this->initialDockerComposeLocation, $this->application->docker_compose_location);
+ if (!$this->customLabels && $this->application->destination->server->proxyType() === 'TRAEFIK_V2') {
+ $this->customLabels = str(implode(",", generateLabelsApplication($this->application)))->replace(',', "\n");
+ $this->application->custom_labels = base64_encode($this->customLabels);
+ $this->application->save();
+ }
+
if ($this->application->build_pack === 'dockercompose' && $this->initialDockerComposeLocation !== $this->application->docker_compose_location) {
$this->loadComposeFile();
}
@@ -207,6 +219,7 @@ class General extends Component
if ($this->ports_exposes !== $this->application->ports_exposes) {
$this->resetDefaultLabels(false);
}
+
if (data_get($this->application, 'build_pack') === 'dockerimage') {
$this->validate([
'application.docker_registry_image_name' => 'required',
diff --git a/app/Models/Application.php b/app/Models/Application.php
index fc1b7d500..995c28f7d 100644
--- a/app/Models/Application.php
+++ b/app/Models/Application.php
@@ -430,7 +430,7 @@ class Application extends BaseModel
public function isConfigurationChanged($save = false)
{
$newConfigHash = $this->fqdn . $this->git_repository . $this->git_branch . $this->git_commit_sha . $this->build_pack . $this->static_image . $this->install_command . $this->build_command . $this->start_command . $this->port_exposes . $this->port_mappings . $this->base_directory . $this->publish_directory . $this->health_check_path . $this->health_check_port . $this->health_check_host . $this->health_check_method . $this->health_check_return_code . $this->health_check_scheme . $this->health_check_response_text . $this->health_check_interval . $this->health_check_timeout . $this->health_check_retries . $this->health_check_start_period . $this->health_check_enabled . $this->limits_memory . $this->limits_swap . $this->limits_swappiness . $this->limits_reservation . $this->limits_cpus . $this->limits_cpuset . $this->limits_cpu_shares . $this->dockerfile . $this->dockerfile_location . $this->custom_labels;
- if ($this->pull_request_id === 0) {
+ if ($this->pull_request_id === 0 || $this->pull_request_id === null) {
$newConfigHash .= json_encode($this->environment_variables->all());
} else {
$newConfigHash .= json_encode($this->environment_variables_preview->all());
diff --git a/bootstrap/helpers/applications.php b/bootstrap/helpers/applications.php
index cfd5c4ebc..d3e28d524 100644
--- a/bootstrap/helpers/applications.php
+++ b/bootstrap/helpers/applications.php
@@ -41,11 +41,11 @@ function queue_application_deployment(int $application_id, string $deployment_uu
dispatch(new ApplicationDeploymentNewJob(
deployment: $deployment,
application: Application::find($application_id)
- ))->onConnection('long-running')->onQueue('long-running');
+ ));
} else {
dispatch(new ApplicationDeploymentJob(
application_deployment_queue_id: $deployment->id,
- ))->onConnection('long-running')->onQueue('long-running');
+ ));
}
}
@@ -57,11 +57,11 @@ function queue_next_deployment(Application $application, bool $isNew = false)
dispatch(new ApplicationDeploymentNewJob(
deployment: $next_found,
application: $application
- ))->onConnection('long-running')->onQueue('long-running');
+ ));
} else {
dispatch(new ApplicationDeploymentJob(
application_deployment_queue_id: $next_found->id,
- ))->onConnection('long-running')->onQueue('long-running');
+ ));
}
}
}
diff --git a/bootstrap/helpers/shared.php b/bootstrap/helpers/shared.php
index 2bb619aa8..08315b422 100644
--- a/bootstrap/helpers/shared.php
+++ b/bootstrap/helpers/shared.php
@@ -1035,7 +1035,9 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
}
data_set($service, 'labels', $serviceLabels->toArray());
data_forget($service, 'is_database');
- data_set($service, 'restart', RESTART_MODE);
+ if (!data_get($service, 'restart')) {
+ data_set($service, 'restart', RESTART_MODE);
+ }
data_set($service, 'container_name', $containerName);
data_forget($service, 'volumes.*.content');
data_forget($service, 'volumes.*.isDirectory');
@@ -1399,6 +1401,11 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
$key = $value;
$defaultValue = null;
}
+ $foundEnv = EnvironmentVariable::where([
+ 'key' => $key,
+ 'application_id' => $resource->id,
+ 'is_preview' => false,
+ ])->first();
if ($foundEnv) {
$defaultValue = data_get($foundEnv, 'value');
}
@@ -1468,7 +1475,9 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
}
data_set($service, 'labels', $serviceLabels->toArray());
data_forget($service, 'is_database');
- data_set($service, 'restart', RESTART_MODE);
+ if (!data_get($service, 'restart')) {
+ data_set($service, 'restart', RESTART_MODE);
+ }
data_set($service, 'container_name', $containerName);
data_forget($service, 'volumes.*.content');
data_forget($service, 'volumes.*.isDirectory');
diff --git a/config/horizon.php b/config/horizon.php
index 060e67bad..49df24b57 100644
--- a/config/horizon.php
+++ b/config/horizon.php
@@ -184,19 +184,8 @@ return [
'connection' => 'redis',
'queue' => ['default'],
'balance' => 'auto',
- 'autoScalingStrategy' => 'time',
- 'maxProcesses' => 1,
- 'maxTime' => 0,
- 'maxJobs' => 0,
- 'memory' => 128,
- 'tries' => 1,
- 'timeout' => 300,
- 'nice' => 0,
- ],
- 'long-running' => [
- 'connection' => 'redis',
- 'queue' => ['long-running'],
- 'balance' => 'auto',
+ // 'autoScalingStrategy' => 'time',
+ // 'maxProcesses' => 1,
'maxTime' => 0,
'maxJobs' => 0,
'memory' => 128,
@@ -209,27 +198,15 @@ return [
'environments' => [
'production' => [
's6' => [
- 'autoScalingStrategy' => 'size',
- 'maxProcesses' => env('HORIZON_MAX_PROCESSES', 2),
- 'balanceMaxShift' => env('HORIZON_BALANCE_MAX_SHIFT', 1),
- 'balanceCooldown' => env('HORIZON_BALANCE_COOLDOWN', 1),
- ],
- 'long-running' => [
'autoScalingStrategy' => 'size',
'maxProcesses' => env('HORIZON_MAX_PROCESSES', 6),
'balanceMaxShift' => env('HORIZON_BALANCE_MAX_SHIFT', 1),
'balanceCooldown' => env('HORIZON_BALANCE_COOLDOWN', 1),
],
- ],
+ ],
'local' => [
's6' => [
- 'autoScalingStrategy' => 'size',
- 'maxProcesses' => env('HORIZON_MAX_PROCESSES', 2),
- 'balanceMaxShift' => env('HORIZON_BALANCE_MAX_SHIFT', 1),
- 'balanceCooldown' => env('HORIZON_BALANCE_COOLDOWN', 1),
- ],
- 'long-running' => [
'autoScalingStrategy' => 'size',
'maxProcesses' => env('HORIZON_MAX_PROCESSES', 6),
'balanceMaxShift' => env('HORIZON_BALANCE_MAX_SHIFT', 1),
diff --git a/config/queue.php b/config/queue.php
index fb846f999..29b79353a 100644
--- a/config/queue.php
+++ b/config/queue.php
@@ -33,14 +33,6 @@ return [
'sync' => [
'driver' => 'sync',
],
- 'long-running' => [
- 'driver' => 'redis',
- 'connection' => 'default',
- 'queue' => 'long-running',
- 'retry_after' => 3600,
- 'block_for' => null,
- 'after_commit' => true,
- ],
'database' => [
'driver' => 'database',
'table' => 'jobs',
diff --git a/config/sentry.php b/config/sentry.php
index 150fd9d8b..e243eb466 100644
--- a/config/sentry.php
+++ b/config/sentry.php
@@ -7,7 +7,7 @@ return [
// The release version of your application
// Example with dynamic git hash: trim(exec('git --git-dir ' . base_path('.git') . ' log --pretty="%h" -n1 HEAD'))
- 'release' => '4.0.0-beta.175',
+ 'release' => '4.0.0-beta.182',
// When left empty or `null` the Laravel environment will be used
'environment' => config('app.env'),
diff --git a/config/version.php b/config/version.php
index 6b0870bf8..e853b7527 100644
--- a/config/version.php
+++ b/config/version.php
@@ -1,3 +1,3 @@
boolean('is_raw_compose_deployment_enabled')->default(false);
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ */
+ public function down(): void
+ {
+ Schema::table('application_settings', function (Blueprint $table) {
+ $table->dropColumn('is_raw_compose_deployment_enabled');
+ });
+ }
+};
diff --git a/docker/coolify-helper/Dockerfile b/docker/coolify-helper/Dockerfile
index 850cad7a1..4cf996904 100644
--- a/docker/coolify-helper/Dockerfile
+++ b/docker/coolify-helper/Dockerfile
@@ -8,9 +8,9 @@ ARG DOCKER_COMPOSE_VERSION=2.21.0
# https://github.com/docker/buildx/releases
ARG DOCKER_BUILDX_VERSION=0.11.2
# https://github.com/buildpacks/pack/releases
-ARG PACK_VERSION=0.31.0
+ARG PACK_VERSION=0.32.1
# https://github.com/railwayapp/nixpacks/releases
-ARG NIXPACKS_VERSION=1.18.0
+ARG NIXPACKS_VERSION=1.20.0
USER root
WORKDIR /artifacts
diff --git a/resources/views/components/collapsible.blade.php b/resources/views/components/collapsible.blade.php
deleted file mode 100644
index f8d4d92fd..000000000
--- a/resources/views/components/collapsible.blade.php
+++ /dev/null
@@ -1,12 +0,0 @@
-@isset($title, $action)
-