Merge remote-tracking branch 'origin/next' into v5-parallel-inertia-react

This commit is contained in:
Andras Bacsai committed 2026-07-06 23:19:55 +02:00
commit a2fc08a7b3
36 files changed
+305 -966

No files matched your search

@@ -143,8 +143,6 @@ class StartDatabaseProxy
)
);
ray("Database proxy for {$database->name} disabled due to non-transient error: {$e->getMessage()}");
return;
}
-21
View File
@@ -26,22 +26,14 @@ class DeleteServer
);
}
ray($server ? 'Deleting server from Coolify' : 'Server already deleted from Coolify, skipping Coolify deletion');
// If server is already deleted from Coolify, skip this part
if (! $server) {
return; // Server already force deleted from Coolify
}
ray('force deleting server from Coolify', ['server_id' => $server->id]);
try {
$server->forceDelete();
} catch (\Throwable $e) {
ray('Failed to force delete server from Coolify', [
'error' => $e->getMessage(),
'server_id' => $server->id,
]);
logger()->error('Failed to force delete server from Coolify', [
'error' => $e->getMessage(),
'server_id' => $server->id,
@@ -66,10 +58,6 @@ class DeleteServer
}
if (! $token) {
ray('No Hetzner token found for team, skipping Hetzner deletion', [
'team_id' => $teamId,
'hetzner_server_id' => $hetznerServerId,
]);
return;
}
@@ -77,16 +65,7 @@ class DeleteServer
$hetznerService = new HetznerService($token->token);
$hetznerService->deleteServer($hetznerServerId);
ray('Deleted server from Hetzner', [
'hetzner_server_id' => $hetznerServerId,
'team_id' => $teamId,
]);
} catch (\Throwable $e) {
ray('Failed to delete server from Hetzner', [
'error' => $e->getMessage(),
'hetzner_server_id' => $hetznerServerId,
'team_id' => $teamId,
]);
// Log the error but don't prevent the server from being deleted from Coolify
logger()->error('Failed to delete server from Hetzner', [
@@ -3609,7 +3609,7 @@ class ApplicationsController extends Controller
'team_id' => $teamId,
'application_uuid' => $application->uuid,
'application_name' => $application->name,
'deployment_uuid' => $deployment_uuid->toString(),
'deployment_uuid' => $deployment_uuid,
'force_rebuild' => $force,
'instant_deploy' => $instant_deploy,
]);
@@ -3617,7 +3617,7 @@ class ApplicationsController extends Controller
return response()->json(
[
'message' => 'Deployment request queued.',
'deployment_uuid' => $deployment_uuid->toString(),
'deployment_uuid' => $deployment_uuid,
],
200
);
@@ -3803,13 +3803,13 @@ class ApplicationsController extends Controller
'team_id' => $teamId,
'application_uuid' => $application->uuid,
'application_name' => $application->name,
'deployment_uuid' => $deployment_uuid->toString(),
'deployment_uuid' => $deployment_uuid,
]);
return response()->json(
[
'message' => 'Restart request queued.',
'deployment_uuid' => $deployment_uuid->toString(),
'deployment_uuid' => $deployment_uuid,
],
);
}
@@ -425,7 +425,7 @@ class DeployController extends Controller
}
['message' => $return_message, 'deployment_uuid' => $deployment_uuid] = $result;
if ($deployment_uuid) {
$deployments->push(['message' => $return_message, 'resource_uuid' => $uuid, 'deployment_uuid' => $deployment_uuid->toString()]);
$deployments->push(['message' => $return_message, 'resource_uuid' => $uuid, 'deployment_uuid' => $deployment_uuid]);
} else {
$deployments->push(['message' => $return_message, 'resource_uuid' => $uuid]);
}
@@ -471,7 +471,7 @@ class DeployController extends Controller
}
['message' => $return_message, 'deployment_uuid' => $deployment_uuid] = $result;
if ($deployment_uuid) {
$deployments->push(['resource_uuid' => $resource->uuid, 'deployment_uuid' => $deployment_uuid->toString()]);
$deployments->push(['resource_uuid' => $resource->uuid, 'deployment_uuid' => $deployment_uuid]);
}
$message = $message->merge($return_message);
}
@@ -529,7 +529,7 @@ class DeployController extends Controller
'resource_type' => 'application',
'application_uuid' => $resource->uuid,
'application_name' => $resource->name,
'deployment_uuid' => $deployment_uuid?->toString(),
'deployment_uuid' => $deployment_uuid,
'force_rebuild' => $force,
'pull_request_id' => $pr,
]);
+1 -1
View File
@@ -162,7 +162,7 @@ class Bitbucket extends Controller
'mode' => 'manual',
'application_uuid' => $application->uuid,
'application_name' => $application->name,
'deployment_uuid' => $deployment_uuid->toString(),
'deployment_uuid' => $deployment_uuid,
'commit' => $commit,
'repository' => $full_name ?? null,
]);
+1 -1
View File
@@ -148,7 +148,7 @@ class Gitea extends Controller
'mode' => 'manual',
'application_uuid' => $application->uuid,
'application_name' => $application->name,
'deployment_uuid' => $deployment_uuid->toString(),
'deployment_uuid' => $deployment_uuid,
'commit' => data_get($payload, 'after'),
'repository' => $full_name ?? null,
]);
+1 -1
View File
@@ -190,7 +190,7 @@ class Gitlab extends Controller
'mode' => 'manual',
'application_uuid' => $application->uuid,
'application_name' => $application->name,
'deployment_uuid' => $deployment_uuid->toString(),
'deployment_uuid' => $deployment_uuid,
'commit' => data_get($payload, 'after'),
'repository' => $full_name ?? null,
]);
+1 -16
View File
@@ -57,13 +57,6 @@ class SendWebhookJob implements ShouldBeEncrypted, ShouldQueue
return;
}
if (isDev()) {
ray('Sending webhook notification', [
'url' => $this->webhookUrl,
'payload' => $this->payload,
]);
}
try {
$httpOptions = SafeWebhookUrl::httpClientOptions($this->webhookUrl);
} catch (\RuntimeException $e) {
@@ -75,14 +68,6 @@ class SendWebhookJob implements ShouldBeEncrypted, ShouldQueue
return;
}
$response = Http::withOptions($httpOptions)->post($this->webhookUrl, $this->payload);
if (isDev()) {
ray('Webhook response', [
'status' => $response->status(),
'body' => $response->body(),
'successful' => $response->successful(),
]);
}
Http::withOptions($httpOptions)->post($this->webhookUrl, $this->payload);
}
}
-1
View File
@@ -179,7 +179,6 @@ class ServerConnectionCheckJob implements ShouldBeEncrypted, ShouldQueue
$this->server->update(['hetzner_server_status' => $status]);
$this->server->hetzner_server_status = $status;
if ($status === 'off') {
ray('Server is powered off, marking as unreachable');
throw new \Exception('Server is powered off');
}
}
-2
View File
@@ -251,7 +251,6 @@ class GlobalSearch extends Component
$cacheKey = self::getCacheKey(auth()->user()->currentTeam()->id);
$this->allSearchableItems = Cache::remember($cacheKey, 300, function () {
ray()->showQueries();
$items = collect();
$team = auth()->user()->currentTeam();
@@ -530,7 +529,6 @@ class GlobalSearch extends Component
'search_text' => strtolower($server->name.' '.$server->ip.' '.$server->description.' server servers'),
];
});
ray($servers);
// Get all projects
$projects = Project::ownedByCurrentTeam()
->withCount(['environments', 'applications', 'services'])
-14
View File
@@ -168,13 +168,6 @@ class Webhook extends Component
$this->syncData(true);
refreshSession();
if (isDev()) {
ray('Webhook settings saved', [
'webhook_enabled' => $this->settings->webhook_enabled,
'webhook_url' => $this->settings->webhook_url,
]);
}
$this->dispatch('success', 'Settings saved.');
}
@@ -183,13 +176,6 @@ class Webhook extends Component
try {
$this->authorize('sendTest', $this->settings);
if (isDev()) {
ray('Sending test webhook notification', [
'team_id' => $this->team->id,
'webhook_url' => $this->settings->webhook_url,
]);
}
$this->team->notify(new Test(channel: 'webhook'));
$this->dispatch('success', 'Test notification sent.');
} catch (\Throwable $e) {
-1
View File
@@ -90,7 +90,6 @@ class Logs extends Component
}
} catch (\Exception $e) {
// Log error but don't fail the entire operation
ray("Error loading containers for server {$server->name}: ".$e->getMessage());
return [];
}
+1 -1
View File
@@ -356,7 +356,7 @@ class EnvironmentVariable extends BaseModel
private function set_environment_variables(?string $environment_variable = null): ?string
{
if (is_null($environment_variable) && $environment_variable === '') {
if (is_null($environment_variable)) {
return null;
}
$environment_variable = trim($environment_variable);
-1
View File
@@ -366,7 +366,6 @@ class LocalFileVolume extends BaseModel
return false;
} catch (\Throwable $e) {
ray($e->getMessage(), 'Error checking read-only volume');
return false;
}
-1
View File
@@ -187,7 +187,6 @@ class LocalPersistentVolume extends BaseModel
return false;
} catch (\Throwable $e) {
ray($e->getMessage(), 'Error checking read-only persistent volume');
return false;
}
-2
View File
@@ -1523,7 +1523,6 @@ $schema://$host {
public function generateCaCertificate()
{
try {
ray('Generating CA certificate for server', $this->id);
SslHelper::generateSslCertificate(
commonName: 'Coolify CA Certificate',
serverId: $this->id,
@@ -1531,7 +1530,6 @@ $schema://$host {
validityDays: 10 * 365
);
$caCertificate = $this->sslCertificates()->where('is_ca_certificate', true)->first();
ray('CA certificate generated', $caCertificate);
if ($caCertificate) {
$certificateContent = $caCertificate->ssl_certificate;
$caCertPath = config('constants.coolify.base_config_path').'/ssl/';
-1
View File
@@ -1583,7 +1583,6 @@ class Service extends BaseModel
$envs->push('SERVICE_NAME_'.str($serviceName)->replace('-', '_')->replace('.', '_')->upper().'='.$serviceName);
}
} catch (\Exception $e) {
ray($e->getMessage());
}
}
@@ -15,23 +15,11 @@ class WebhookChannel
$webhookSettings = $notifiable->webhookNotificationSettings;
if (! $webhookSettings || ! $webhookSettings->isEnabled() || ! $webhookSettings->webhook_url) {
if (isDev()) {
ray('Webhook notification skipped - not enabled or no URL configured');
}
return;
}
$payload = $notification->toWebhook();
if (isDev()) {
ray('Dispatching webhook notification', [
'notification' => get_class($notification),
'url' => $webhookSettings->webhook_url,
'payload' => $payload,
]);
}
SendWebhookJob::dispatch($payload, $webhookSettings->webhook_url);
}
}
@@ -17,8 +17,6 @@ class HetznerDeletionFailed extends CustomEmailNotification
public function via(object $notifiable): array
{
ray('hello');
ray($notifiable);
return $notifiable->getEnabledChannels('hetzner_deletion_failed');
}
+2 -9
View File
@@ -3,6 +3,7 @@
namespace App\Services;
use App\Exceptions\RateLimitException;
use Illuminate\Http\Client\RequestException;
use Illuminate\Support\Facades\Http;
class HetznerService
@@ -24,7 +25,7 @@ class HetznerService
->timeout(30)
->retry(3, function (int $attempt, \Exception $exception) {
// Handle rate limiting (429 Too Many Requests)
if ($exception instanceof \Illuminate\Http\Client\RequestException) {
if ($exception instanceof RequestException) {
$response = $exception->response;
if ($response && $response->status() === 429) {
@@ -129,17 +130,9 @@ class HetznerService
public function createServer(array $params): array
{
ray('Hetzner createServer request', [
'endpoint' => '/servers',
'params' => $params,
]);
$response = $this->request('post', '/servers', $params);
ray('Hetzner createServer response', [
'response' => $response,
]);
return $response['server'] ?? [];
}
+12 -12
View File
@@ -3,6 +3,11 @@
namespace App\Traits;
use App\Livewire\GlobalSearch;
use App\Models\Application;
use App\Models\Environment;
use App\Models\Project;
use App\Models\Server;
use App\Models\Service;
use Illuminate\Database\Eloquent\Model;
trait ClearsGlobalSearchCache
@@ -20,7 +25,6 @@ trait ClearsGlobalSearchCache
}
} catch (\Throwable $e) {
// Silently fail cache clearing - don't break the save operation
ray('Failed to clear global search cache on saving: '.$e->getMessage());
}
});
@@ -33,7 +37,6 @@ trait ClearsGlobalSearchCache
}
} catch (\Throwable $e) {
// Silently fail cache clearing - don't break the create operation
ray('Failed to clear global search cache on creation: '.$e->getMessage());
}
});
@@ -46,7 +49,6 @@ trait ClearsGlobalSearchCache
}
} catch (\Throwable $e) {
// Silently fail cache clearing - don't break the delete operation
ray('Failed to clear global search cache on deletion: '.$e->getMessage());
}
});
}
@@ -58,14 +60,14 @@ trait ClearsGlobalSearchCache
$searchableFields = ['name', 'description'];
// Add model-specific searchable fields
if ($this instanceof \App\Models\Application) {
if ($this instanceof Application) {
$searchableFields[] = 'fqdn';
$searchableFields[] = 'docker_compose_domains';
} elseif ($this instanceof \App\Models\Server) {
} elseif ($this instanceof Server) {
$searchableFields[] = 'ip';
} elseif ($this instanceof \App\Models\Service) {
} elseif ($this instanceof Service) {
// Services don't have direct fqdn, but name and description are covered
} elseif ($this instanceof \App\Models\Project || $this instanceof \App\Models\Environment) {
} elseif ($this instanceof Project || $this instanceof Environment) {
// Projects and environments only have name and description as searchable
}
// Database models only have name and description as searchable
@@ -81,7 +83,6 @@ trait ClearsGlobalSearchCache
return false;
} catch (\Throwable $e) {
// If checking changes fails, assume changes exist to be safe
ray('Failed to check searchable changes: '.$e->getMessage());
return true;
}
@@ -91,18 +92,18 @@ trait ClearsGlobalSearchCache
{
try {
// For Project models (has direct team_id)
if ($this instanceof \App\Models\Project) {
if ($this instanceof Project) {
return $this->team_id ?? null;
}
// For Environment models (get team_id through project)
if ($this instanceof \App\Models\Environment) {
if ($this instanceof Environment) {
return $this->project?->team_id;
}
// For database models, team is accessed through environment.project.team
if (method_exists($this, 'team')) {
if ($this instanceof \App\Models\Server) {
if ($this instanceof Server) {
$team = $this->team;
} else {
$team = $this->team();
@@ -120,7 +121,6 @@ trait ClearsGlobalSearchCache
return null;
} catch (\Throwable $e) {
// If we can't determine team ID, return null
ray('Failed to get team ID for cache: '.$e->getMessage());
return null;
}
-1
View File
@@ -82,7 +82,6 @@ trait SshRetryable
$lastErrorMessage = '';
// Randomly fail the command with a key exchange error for testing
// if (random_int(1, 10) === 1) { // 10% chance to fail
// ray('SSH key exchange failed: kex_exchange_identification: read: Connection reset by peer');
// throw new \RuntimeException('SSH key exchange failed: kex_exchange_identification: read: Connection reset by peer');
// }
for ($attempt = 0; $attempt < $maxRetries; $attempt++) {