Skip to content

Commit 627cec1

Browse files
authored
Merge branch 'next' into fix-traefik-startup
2 parents cb0f230 + a25e553 commit 627cec1

File tree

12 files changed

+290
-50
lines changed

12 files changed

+290
-50
lines changed

app/Http/Controllers/Api/ApplicationsController.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1652,6 +1652,10 @@ private function create_application(Request $request, $type)
16521652
$service->save();
16531653

16541654
$service->parse(isNew: true);
1655+
1656+
// Apply service-specific application prerequisites
1657+
applyServiceApplicationPrerequisites($service);
1658+
16551659
if ($instantDeploy) {
16561660
StartService::dispatch($service);
16571661
}

app/Http/Controllers/Api/ServicesController.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -376,6 +376,10 @@ public function create_service(Request $request)
376376
});
377377
}
378378
$service->parse(isNew: true);
379+
380+
// Apply service-specific application prerequisites
381+
applyServiceApplicationPrerequisites($service);
382+
379383
if ($instantDeploy) {
380384
StartService::dispatch($service);
381385
}

app/Livewire/Project/New/DockerCompose.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,9 @@ public function submit()
7474
}
7575
$service->parse(isNew: true);
7676

77+
// Apply service-specific application prerequisites
78+
applyServiceApplicationPrerequisites($service);
79+
7780
return redirect()->route('project.service.configuration', [
7881
'service_uuid' => $service->uuid,
7982
'environment_uuid' => $environment->uuid,

app/Livewire/Project/Resource/Create.php

Lines changed: 8 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -102,33 +102,16 @@ public function mount()
102102
}
103103
});
104104
}
105-
$service->parse(isNew: true);
105+
$service->parse(isNew: true);
106106

107-
// For Beszel service disable gzip (fixes realtime not working issue)
108-
if ($oneClickServiceName === 'beszel') {
109-
$appService = $service->applications()->whereName('beszel')->first();
110-
if ($appService) {
111-
$appService->is_gzip_enabled = false;
112-
$appService->save();
113-
}
114-
}
115-
// For Appwrite services, disable strip prefix for services that handle domain requests
116-
if ($oneClickServiceName === 'appwrite') {
117-
$servicesToDisableStripPrefix = ['appwrite', 'appwrite-console', 'appwrite-realtime'];
118-
foreach ($servicesToDisableStripPrefix as $serviceName) {
119-
$appService = $service->applications()->whereName($serviceName)->first();
120-
if ($appService) {
121-
$appService->is_stripprefix_enabled = false;
122-
$appService->save();
123-
}
124-
}
125-
}
107+
// Apply service-specific application prerequisites
108+
applyServiceApplicationPrerequisites($service);
126109

127-
return redirect()->route('project.service.configuration', [
128-
'service_uuid' => $service->uuid,
129-
'environment_uuid' => $environment->uuid,
130-
'project_uuid' => $project->uuid,
131-
]);
110+
return redirect()->route('project.service.configuration', [
111+
'service_uuid' => $service->uuid,
112+
'environment_uuid' => $environment->uuid,
113+
'project_uuid' => $project->uuid,
114+
]);
132115
}
133116
}
134117
$this->type = $type->value();

app/Livewire/Server/Proxy.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ protected function getTraefikVersions(): ?array
9191

9292
public function getConfigurationFilePathProperty(): string
9393
{
94-
return rtrim($this->server->proxyPath(), '/') . '/docker-compose.yml';
94+
return rtrim($this->server->proxyPath(), '/').'/docker-compose.yml';
9595
}
9696

9797
public function changeProxy()

app/Livewire/Upgrade.php

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@
88

99
class Upgrade extends Component
1010
{
11-
public bool $showProgress = false;
12-
1311
public bool $updateInProgress = false;
1412

1513
public bool $isUpgradeAvailable = false;

bootstrap/helpers/constants.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,4 +71,10 @@
7171
'pgadmin',
7272
'postgresus',
7373
];
74+
const NEEDS_TO_DISABLE_GZIP = [
75+
'beszel' => ['beszel'],
76+
];
77+
const NEEDS_TO_DISABLE_STRIPPREFIX = [
78+
'appwrite' => ['appwrite', 'appwrite-console', 'appwrite-realtime'],
79+
];
7480
const SHARED_VARIABLE_TYPES = ['team', 'project', 'environment'];

bootstrap/helpers/services.php

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
use App\Models\Service;
55
use App\Models\ServiceApplication;
66
use App\Models\ServiceDatabase;
7+
use Illuminate\Support\Facades\Log;
78
use Illuminate\Support\Stringable;
89
use Spatie\Url\Url;
910
use Symfony\Component\Yaml\Yaml;
@@ -339,3 +340,54 @@ function parseServiceEnvironmentVariable(string $key): array
339340
'has_port' => $hasPort,
340341
];
341342
}
343+
344+
/**
345+
* Apply service-specific application prerequisites after service parse.
346+
*
347+
* This function configures application-level settings that are required for
348+
* specific one-click services to work correctly (e.g., disabling gzip for Beszel,
349+
* disabling strip prefix for Appwrite services).
350+
*
351+
* Must be called AFTER $service->parse() since it requires applications to exist.
352+
*
353+
* @param Service $service The service to apply prerequisites to
354+
*/
355+
function applyServiceApplicationPrerequisites(Service $service): void
356+
{
357+
try {
358+
// Extract service name from service name (format: "servicename-uuid")
359+
$serviceName = str($service->name)->beforeLast('-')->value();
360+
361+
// Apply gzip disabling if needed
362+
if (array_key_exists($serviceName, NEEDS_TO_DISABLE_GZIP)) {
363+
$applicationNames = NEEDS_TO_DISABLE_GZIP[$serviceName];
364+
foreach ($applicationNames as $applicationName) {
365+
$application = $service->applications()->whereName($applicationName)->first();
366+
if ($application) {
367+
$application->is_gzip_enabled = false;
368+
$application->save();
369+
}
370+
}
371+
}
372+
373+
// Apply stripprefix disabling if needed
374+
if (array_key_exists($serviceName, NEEDS_TO_DISABLE_STRIPPREFIX)) {
375+
$applicationNames = NEEDS_TO_DISABLE_STRIPPREFIX[$serviceName];
376+
foreach ($applicationNames as $applicationName) {
377+
$application = $service->applications()->whereName($applicationName)->first();
378+
if ($application) {
379+
$application->is_stripprefix_enabled = false;
380+
$application->save();
381+
}
382+
}
383+
}
384+
} catch (\Throwable $e) {
385+
// Log error but don't throw - prerequisites are nice-to-have, not critical
386+
Log::error('Failed to apply service application prerequisites', [
387+
'service_id' => $service->id,
388+
'service_name' => $service->name,
389+
'error' => $e->getMessage(),
390+
'trace' => $e->getTraceAsString(),
391+
]);
392+
}
393+
}

resources/views/livewire/upgrade.blade.php

Lines changed: 54 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,10 @@ class="w-24 dark:bg-coolgray-200 dark:hover:bg-coolgray-300">Cancel
9393
modalOpen: false,
9494
showProgress: false,
9595
currentStatus: '',
96+
checkHealthInterval: null,
97+
checkIfIamDeadInterval: null,
98+
healthCheckAttempts: 0,
99+
startTime: null,
96100
confirmed() {
97101
this.showProgress = true;
98102
this.$wire.$call('upgrade')
@@ -102,43 +106,78 @@ class="w-24 dark:bg-coolgray-200 dark:hover:bg-coolgray-300">Cancel
102106
event.returnValue = '';
103107
});
104108
},
109+
getReviveStatusMessage(elapsedMinutes, attempts) {
110+
if (elapsedMinutes === 0) {
111+
return `Waiting for Coolify to come back online... (attempt ${attempts})`;
112+
} else if (elapsedMinutes < 2) {
113+
return `Waiting for Coolify to come back online... (${elapsedMinutes} minute${elapsedMinutes !== 1 ? 's' : ''} elapsed)`;
114+
} else if (elapsedMinutes < 5) {
115+
return `Update in progress, this may take several minutes... (${elapsedMinutes} minutes elapsed)`;
116+
} else if (elapsedMinutes < 10) {
117+
return `Large updates can take 10+ minutes. Please be patient... (${elapsedMinutes} minutes elapsed)`;
118+
} else {
119+
return `Still updating. If this takes longer than 15 minutes, please check server logs... (${elapsedMinutes} minutes elapsed)`;
120+
}
121+
},
105122
revive() {
106-
if (checkHealthInterval) return true;
123+
if (this.checkHealthInterval) return true;
124+
this.healthCheckAttempts = 0;
125+
this.startTime = Date.now();
107126
console.log('Checking server\'s health...')
108-
checkHealthInterval = setInterval(() => {
127+
this.checkHealthInterval = setInterval(() => {
128+
this.healthCheckAttempts++;
129+
const elapsedMinutes = Math.floor((Date.now() - this.startTime) / 60000);
109130
fetch('/api/health')
110131
.then(response => {
111132
if (response.ok) {
112133
this.currentStatus =
113-
'Coolify is back online. Reloading this page (you can manually reload if its not done automatically)...';
114-
if (checkHealthInterval) clearInterval(
115-
checkHealthInterval);
134+
'Coolify is back online. Reloading this page in 5 seconds...';
135+
if (this.checkHealthInterval) {
136+
clearInterval(this.checkHealthInterval);
137+
this.checkHealthInterval = null;
138+
}
116139
setTimeout(() => {
117140
window.location.reload();
118141
}, 5000)
119142
} else {
120-
this.currentStatus =
121-
"Waiting for Coolify to come back from the dead..."
143+
this.currentStatus = this.getReviveStatusMessage(elapsedMinutes, this
144+
.healthCheckAttempts);
122145
}
123146
})
147+
.catch(error => {
148+
console.error('Health check failed:', error);
149+
this.currentStatus = this.getReviveStatusMessage(elapsedMinutes, this
150+
.healthCheckAttempts);
151+
});
124152
}, 2000);
125153
},
126154
upgrade() {
127-
if (checkIfIamDeadInterval || this.$wire.showProgress) return true;
128-
this.currentStatus = 'Pulling new images and updating Coolify.';
129-
checkIfIamDeadInterval = setInterval(() => {
155+
if (this.checkIfIamDeadInterval || this.showProgress) return true;
156+
this.currentStatus = 'Update in progress. Pulling new images and preparing to restart Coolify...';
157+
this.checkIfIamDeadInterval = setInterval(() => {
130158
fetch('/api/health')
131159
.then(response => {
132160
if (response.ok) {
133-
this.currentStatus = "Waiting for the update process..."
134-
} else {
135161
this.currentStatus =
136-
"Update done, restarting Coolify & waiting until it is revived!"
137-
if (checkIfIamDeadInterval) clearInterval(
138-
checkIfIamDeadInterval);
162+
"Update in progress. Pulling new images and preparing to restart Coolify..."
163+
} else {
164+
this.currentStatus = "Coolify is restarting with the new version..."
165+
if (this.checkIfIamDeadInterval) {
166+
clearInterval(this.checkIfIamDeadInterval);
167+
this.checkIfIamDeadInterval = null;
168+
}
139169
this.revive();
140170
}
141171
})
172+
.catch(error => {
173+
console.error('Health check failed:', error);
174+
this.currentStatus = "Coolify is restarting with the new version..."
175+
if (this.checkIfIamDeadInterval) {
176+
clearInterval(this.checkIfIamDeadInterval);
177+
this.checkIfIamDeadInterval = null;
178+
}
179+
this.revive();
180+
});
142181
}, 2000);
143182
}
144183

tests/Unit/CheckForUpdatesJobTest.php

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
->once()
4949
->with(base_path('versions.json'), Mockery::on(function ($json) {
5050
$data = json_decode($json, true);
51+
5152
// Should use cached version (4.0.10), not CDN version (4.0.0)
5253
return $data['coolify']['v4']['version'] === '4.0.10';
5354
}));
@@ -61,7 +62,7 @@
6162
return $this->settings;
6263
});
6364

64-
$job = new CheckForUpdatesJob();
65+
$job = new CheckForUpdatesJob;
6566
$job->handle();
6667
});
6768

@@ -87,6 +88,7 @@
8788
->once()
8889
->with(base_path('versions.json'), Mockery::on(function ($json) {
8990
$data = json_decode($json, true);
91+
9092
// Should use running version (4.0.10), not CDN (4.0.0) or cache (4.0.5)
9193
return $data['coolify']['v4']['version'] === '4.0.10';
9294
}));
@@ -104,7 +106,7 @@
104106
return $this->settings;
105107
});
106108

107-
$job = new CheckForUpdatesJob();
109+
$job = new CheckForUpdatesJob;
108110
$job->handle();
109111
});
110112

@@ -125,7 +127,7 @@
125127
return $this->settings;
126128
});
127129

128-
$job = new CheckForUpdatesJob();
130+
$job = new CheckForUpdatesJob;
129131

130132
// Should not throw even if structure is unexpected
131133
// data_set() handles nested path creation
@@ -159,6 +161,7 @@
159161
expect($data['traefik']['v3.6'])->toBe('3.6.2');
160162
// Sentinel should use CDN version
161163
expect($data['sentinel']['version'])->toBe('1.0.5');
164+
162165
return true;
163166
}));
164167

@@ -178,6 +181,6 @@
178181
return $this->settings;
179182
});
180183

181-
$job = new CheckForUpdatesJob();
184+
$job = new CheckForUpdatesJob;
182185
$job->handle();
183186
});

0 commit comments

Comments
 (0)