mirror of
https://github.com/tiennm99/coolify.git
synced 2026-04-17 17:21:04 +00:00
Merge pull request #6837 from coollabsio/andrasbacsai/custom-webhooks
feat: add custom webhook notification support
This commit is contained in:
@@ -185,4 +185,30 @@ class DeploymentFailed extends CustomEmailNotification
|
||||
color: SlackMessage::errorColor()
|
||||
);
|
||||
}
|
||||
|
||||
public function toWebhook(): array
|
||||
{
|
||||
$data = [
|
||||
'success' => false,
|
||||
'message' => 'Deployment failed',
|
||||
'event' => 'deployment_failed',
|
||||
'application_name' => $this->application_name,
|
||||
'application_uuid' => $this->application->uuid,
|
||||
'deployment_uuid' => $this->deployment_uuid,
|
||||
'deployment_url' => $this->deployment_url,
|
||||
'project' => data_get($this->application, 'environment.project.name'),
|
||||
'environment' => $this->environment_name,
|
||||
];
|
||||
|
||||
if ($this->preview) {
|
||||
$data['pull_request_id'] = $this->preview->pull_request_id;
|
||||
$data['preview_fqdn'] = $this->preview->fqdn;
|
||||
}
|
||||
|
||||
if ($this->fqdn) {
|
||||
$data['fqdn'] = $this->fqdn;
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -205,4 +205,30 @@ class DeploymentSuccess extends CustomEmailNotification
|
||||
color: SlackMessage::successColor()
|
||||
);
|
||||
}
|
||||
|
||||
public function toWebhook(): array
|
||||
{
|
||||
$data = [
|
||||
'success' => true,
|
||||
'message' => 'New version successfully deployed',
|
||||
'event' => 'deployment_success',
|
||||
'application_name' => $this->application_name,
|
||||
'application_uuid' => $this->application->uuid,
|
||||
'deployment_uuid' => $this->deployment_uuid,
|
||||
'deployment_url' => $this->deployment_url,
|
||||
'project' => data_get($this->application, 'environment.project.name'),
|
||||
'environment' => $this->environment_name,
|
||||
];
|
||||
|
||||
if ($this->preview) {
|
||||
$data['pull_request_id'] = $this->preview->pull_request_id;
|
||||
$data['preview_fqdn'] = $this->preview->fqdn;
|
||||
}
|
||||
|
||||
if ($this->fqdn) {
|
||||
$data['fqdn'] = $this->fqdn;
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,4 +113,19 @@ class StatusChanged extends CustomEmailNotification
|
||||
color: SlackMessage::errorColor()
|
||||
);
|
||||
}
|
||||
|
||||
public function toWebhook(): array
|
||||
{
|
||||
return [
|
||||
'success' => false,
|
||||
'message' => 'Application stopped',
|
||||
'event' => 'status_changed',
|
||||
'application_name' => $this->resource_name,
|
||||
'application_uuid' => $this->resource->uuid,
|
||||
'url' => $this->resource_url,
|
||||
'project' => data_get($this->resource, 'environment.project.name'),
|
||||
'environment' => $this->environment_name,
|
||||
'fqdn' => $this->fqdn,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
37
app/Notifications/Channels/WebhookChannel.php
Normal file
37
app/Notifications/Channels/WebhookChannel.php
Normal file
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace App\Notifications\Channels;
|
||||
|
||||
use App\Jobs\SendWebhookJob;
|
||||
use Illuminate\Notifications\Notification;
|
||||
|
||||
class WebhookChannel
|
||||
{
|
||||
/**
|
||||
* Send the given notification.
|
||||
*/
|
||||
public function send($notifiable, Notification $notification): void
|
||||
{
|
||||
$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);
|
||||
}
|
||||
}
|
||||
@@ -102,4 +102,22 @@ class ContainerRestarted extends CustomEmailNotification
|
||||
color: SlackMessage::warningColor()
|
||||
);
|
||||
}
|
||||
|
||||
public function toWebhook(): array
|
||||
{
|
||||
$data = [
|
||||
'success' => true,
|
||||
'message' => 'Resource restarted automatically',
|
||||
'event' => 'container_restarted',
|
||||
'container_name' => $this->name,
|
||||
'server_name' => $this->server->name,
|
||||
'server_uuid' => $this->server->uuid,
|
||||
];
|
||||
|
||||
if ($this->url) {
|
||||
$data['url'] = $this->url;
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,4 +102,22 @@ class ContainerStopped extends CustomEmailNotification
|
||||
color: SlackMessage::errorColor()
|
||||
);
|
||||
}
|
||||
|
||||
public function toWebhook(): array
|
||||
{
|
||||
$data = [
|
||||
'success' => false,
|
||||
'message' => 'Resource stopped unexpectedly',
|
||||
'event' => 'container_stopped',
|
||||
'container_name' => $this->name,
|
||||
'server_name' => $this->server->name,
|
||||
'server_uuid' => $this->server->uuid,
|
||||
];
|
||||
|
||||
if ($this->url) {
|
||||
$data['url'] = $this->url;
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,4 +88,21 @@ class BackupFailed extends CustomEmailNotification
|
||||
color: SlackMessage::errorColor()
|
||||
);
|
||||
}
|
||||
|
||||
public function toWebhook(): array
|
||||
{
|
||||
$url = base_url().'/project/'.data_get($this->database, 'environment.project.uuid').'/environment/'.data_get($this->database, 'environment.uuid').'/database/'.$this->database->uuid;
|
||||
|
||||
return [
|
||||
'success' => false,
|
||||
'message' => 'Database backup failed',
|
||||
'event' => 'backup_failed',
|
||||
'database_name' => $this->name,
|
||||
'database_uuid' => $this->database->uuid,
|
||||
'database_type' => $this->database_name,
|
||||
'frequency' => $this->frequency,
|
||||
'error_output' => $this->output,
|
||||
'url' => $url,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,4 +85,20 @@ class BackupSuccess extends CustomEmailNotification
|
||||
color: SlackMessage::successColor()
|
||||
);
|
||||
}
|
||||
|
||||
public function toWebhook(): array
|
||||
{
|
||||
$url = base_url().'/project/'.data_get($this->database, 'environment.project.uuid').'/environment/'.data_get($this->database, 'environment.uuid').'/database/'.$this->database->uuid;
|
||||
|
||||
return [
|
||||
'success' => true,
|
||||
'message' => 'Database backup successful',
|
||||
'event' => 'backup_success',
|
||||
'database_name' => $this->name,
|
||||
'database_uuid' => $this->database->uuid,
|
||||
'database_type' => $this->database_name,
|
||||
'frequency' => $this->frequency,
|
||||
'url' => $url,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,4 +113,27 @@ class BackupSuccessWithS3Warning extends CustomEmailNotification
|
||||
color: SlackMessage::warningColor()
|
||||
);
|
||||
}
|
||||
|
||||
public function toWebhook(): array
|
||||
{
|
||||
$url = base_url().'/project/'.data_get($this->database, 'environment.project.uuid').'/environment/'.data_get($this->database, 'environment.uuid').'/database/'.$this->database->uuid;
|
||||
|
||||
$data = [
|
||||
'success' => true,
|
||||
'message' => 'Database backup succeeded locally, S3 upload failed',
|
||||
'event' => 'backup_success_with_s3_warning',
|
||||
'database_name' => $this->name,
|
||||
'database_uuid' => $this->database->uuid,
|
||||
'database_type' => $this->database_name,
|
||||
'frequency' => $this->frequency,
|
||||
's3_error' => $this->s3_error,
|
||||
'url' => $url,
|
||||
];
|
||||
|
||||
if ($this->s3_storage_url) {
|
||||
$data['s3_storage_url'] = $this->s3_storage_url;
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -114,4 +114,28 @@ class TaskFailed extends CustomEmailNotification
|
||||
color: SlackMessage::errorColor()
|
||||
);
|
||||
}
|
||||
|
||||
public function toWebhook(): array
|
||||
{
|
||||
$data = [
|
||||
'success' => false,
|
||||
'message' => 'Scheduled task failed',
|
||||
'event' => 'task_failed',
|
||||
'task_name' => $this->task->name,
|
||||
'task_uuid' => $this->task->uuid,
|
||||
'output' => $this->output,
|
||||
];
|
||||
|
||||
if ($this->task->application) {
|
||||
$data['application_uuid'] = $this->task->application->uuid;
|
||||
} elseif ($this->task->service) {
|
||||
$data['service_uuid'] = $this->task->service->uuid;
|
||||
}
|
||||
|
||||
if ($this->url) {
|
||||
$data['url'] = $this->url;
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,4 +105,28 @@ class TaskSuccess extends CustomEmailNotification
|
||||
color: SlackMessage::successColor()
|
||||
);
|
||||
}
|
||||
|
||||
public function toWebhook(): array
|
||||
{
|
||||
$data = [
|
||||
'success' => true,
|
||||
'message' => 'Scheduled task succeeded',
|
||||
'event' => 'task_success',
|
||||
'task_name' => $this->task->name,
|
||||
'task_uuid' => $this->task->uuid,
|
||||
'output' => $this->output,
|
||||
];
|
||||
|
||||
if ($this->task->application) {
|
||||
$data['application_uuid'] = $this->task->application->uuid;
|
||||
} elseif ($this->task->service) {
|
||||
$data['service_uuid'] = $this->task->service->uuid;
|
||||
}
|
||||
|
||||
if ($this->url) {
|
||||
$data['url'] = $this->url;
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,4 +66,19 @@ class DockerCleanupFailed extends CustomEmailNotification
|
||||
color: SlackMessage::errorColor()
|
||||
);
|
||||
}
|
||||
|
||||
public function toWebhook(): array
|
||||
{
|
||||
$url = base_url().'/server/'.$this->server->uuid;
|
||||
|
||||
return [
|
||||
'success' => false,
|
||||
'message' => 'Docker cleanup job failed',
|
||||
'event' => 'docker_cleanup_failed',
|
||||
'server_name' => $this->server->name,
|
||||
'server_uuid' => $this->server->uuid,
|
||||
'error_message' => $this->message,
|
||||
'url' => $url,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,4 +66,19 @@ class DockerCleanupSuccess extends CustomEmailNotification
|
||||
color: SlackMessage::successColor()
|
||||
);
|
||||
}
|
||||
|
||||
public function toWebhook(): array
|
||||
{
|
||||
$url = base_url().'/server/'.$this->server->uuid;
|
||||
|
||||
return [
|
||||
'success' => true,
|
||||
'message' => 'Docker cleanup job succeeded',
|
||||
'event' => 'docker_cleanup_success',
|
||||
'server_name' => $this->server->name,
|
||||
'server_uuid' => $this->server->uuid,
|
||||
'cleanup_message' => $this->message,
|
||||
'url' => $url,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,4 +88,18 @@ class HighDiskUsage extends CustomEmailNotification
|
||||
color: SlackMessage::errorColor()
|
||||
);
|
||||
}
|
||||
|
||||
public function toWebhook(): array
|
||||
{
|
||||
return [
|
||||
'success' => false,
|
||||
'message' => 'High disk usage detected',
|
||||
'event' => 'high_disk_usage',
|
||||
'server_name' => $this->server->name,
|
||||
'server_uuid' => $this->server->uuid,
|
||||
'disk_usage' => $this->disk_usage,
|
||||
'threshold' => $this->server_disk_usage_notification_threshold,
|
||||
'url' => base_url().'/server/'.$this->server->uuid,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,4 +74,18 @@ class Reachable extends CustomEmailNotification
|
||||
color: SlackMessage::successColor()
|
||||
);
|
||||
}
|
||||
|
||||
public function toWebhook(): array
|
||||
{
|
||||
$url = base_url().'/server/'.$this->server->uuid;
|
||||
|
||||
return [
|
||||
'success' => true,
|
||||
'message' => 'Server revived',
|
||||
'event' => 'server_reachable',
|
||||
'server_name' => $this->server->name,
|
||||
'server_uuid' => $this->server->uuid,
|
||||
'url' => $url,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -345,4 +345,47 @@ class ServerPatchCheck extends CustomEmailNotification
|
||||
color: SlackMessage::errorColor()
|
||||
);
|
||||
}
|
||||
|
||||
public function toWebhook(): array
|
||||
{
|
||||
// Handle error case
|
||||
if (isset($this->patchData['error'])) {
|
||||
return [
|
||||
'success' => false,
|
||||
'message' => 'Failed to check patches',
|
||||
'event' => 'server_patch_check_error',
|
||||
'server_name' => $this->server->name,
|
||||
'server_uuid' => $this->server->uuid,
|
||||
'os_id' => $this->patchData['osId'] ?? 'unknown',
|
||||
'package_manager' => $this->patchData['package_manager'] ?? 'unknown',
|
||||
'error' => $this->patchData['error'],
|
||||
'url' => $this->serverUrl,
|
||||
];
|
||||
}
|
||||
|
||||
$totalUpdates = $this->patchData['total_updates'] ?? 0;
|
||||
$updates = $this->patchData['updates'] ?? [];
|
||||
|
||||
// Check for critical packages
|
||||
$criticalPackages = collect($updates)->filter(function ($update) {
|
||||
return str_contains(strtolower($update['package']), 'docker') ||
|
||||
str_contains(strtolower($update['package']), 'kernel') ||
|
||||
str_contains(strtolower($update['package']), 'openssh') ||
|
||||
str_contains(strtolower($update['package']), 'ssl');
|
||||
});
|
||||
|
||||
return [
|
||||
'success' => false,
|
||||
'message' => 'Server patches available',
|
||||
'event' => 'server_patch_check',
|
||||
'server_name' => $this->server->name,
|
||||
'server_uuid' => $this->server->uuid,
|
||||
'total_updates' => $totalUpdates,
|
||||
'os_id' => $this->patchData['osId'] ?? 'unknown',
|
||||
'package_manager' => $this->patchData['package_manager'] ?? 'unknown',
|
||||
'updates' => $updates,
|
||||
'critical_packages_count' => $criticalPackages->count(),
|
||||
'url' => $this->serverUrl,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,4 +82,18 @@ class Unreachable extends CustomEmailNotification
|
||||
color: SlackMessage::errorColor()
|
||||
);
|
||||
}
|
||||
|
||||
public function toWebhook(): array
|
||||
{
|
||||
$url = base_url().'/server/'.$this->server->uuid;
|
||||
|
||||
return [
|
||||
'success' => false,
|
||||
'message' => 'Server unreachable',
|
||||
'event' => 'server_unreachable',
|
||||
'server_name' => $this->server->name,
|
||||
'server_uuid' => $this->server->uuid,
|
||||
'url' => $url,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ use App\Notifications\Channels\EmailChannel;
|
||||
use App\Notifications\Channels\PushoverChannel;
|
||||
use App\Notifications\Channels\SlackChannel;
|
||||
use App\Notifications\Channels\TelegramChannel;
|
||||
use App\Notifications\Channels\WebhookChannel;
|
||||
use App\Notifications\Dto\DiscordMessage;
|
||||
use App\Notifications\Dto\PushoverMessage;
|
||||
use App\Notifications\Dto\SlackMessage;
|
||||
@@ -36,6 +37,7 @@ class Test extends Notification implements ShouldQueue
|
||||
'telegram' => [TelegramChannel::class],
|
||||
'slack' => [SlackChannel::class],
|
||||
'pushover' => [PushoverChannel::class],
|
||||
'webhook' => [WebhookChannel::class],
|
||||
default => [],
|
||||
};
|
||||
} else {
|
||||
@@ -110,4 +112,14 @@ class Test extends Notification implements ShouldQueue
|
||||
description: 'This is a test Slack notification from Coolify.'
|
||||
);
|
||||
}
|
||||
|
||||
public function toWebhook(): array
|
||||
{
|
||||
return [
|
||||
'success' => true,
|
||||
'message' => 'This is a test webhook notification from Coolify.',
|
||||
'event' => 'test',
|
||||
'url' => base_url(),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user