fix: build notification and deployment log links from the instance url (#11623)

This commit is contained in:
🏔️ Peak
2026-09-04 15:20:03 +02:00
committed by GitHub
11 changed files with 88 additions and 119 deletions
+2 -6
View File
@@ -2362,12 +2362,8 @@ class ApplicationDeploymentJob implements ShouldBeEncrypted, ShouldQueue
destination: $destination,
no_questions_asked: true,
);
$this->application_deployment_queue->addLogEntry("Deployment to {$server->name}. Logs: ".route('project.application.deployment.show', [
'project_uuid' => data_get($this->application, 'environment.project.uuid'),
'application_uuid' => data_get($this->application, 'uuid'),
'deployment_uuid' => $deployment_uuid,
'environment_uuid' => data_get($this->application, 'environment.uuid'),
]));
$deployment_url = base_url().'/project/'.data_get($this->application, 'environment.project.uuid').'/environment/'.data_get($this->application, 'environment.uuid').'/application/'.data_get($this->application, 'uuid')."/deployment/{$deployment_uuid}";
$this->application_deployment_queue->addLogEntry("Deployment to {$server->name}. Logs: {$deployment_url}");
}
}
+4 -1
View File
@@ -66,7 +66,10 @@ class RegenerateSslCertJob implements ShouldBeEncrypted, ShouldQueue
caCert: $caCert->ssl_certificate,
caKey: $caCert->ssl_private_key,
);
$regenerated->push($certificate);
$resource = $certificate->database;
if ($resource) {
$regenerated->push($resource);
}
} catch (\Exception $e) {
Log::error('Failed to regenerate SSL certificate: '.$e->getMessage());
}
-26
View File
@@ -621,32 +621,6 @@ class Application extends BaseModel
&& $this->restart_limit_reached === true;
}
public function taskLink($task_uuid)
{
if (data_get($this, 'environment.project.uuid')) {
$route = route('project.application.scheduled-tasks', [
'project_uuid' => data_get($this, 'environment.project.uuid'),
'environment_uuid' => data_get($this, 'environment.uuid'),
'application_uuid' => data_get($this, 'uuid'),
'task_uuid' => $task_uuid,
]);
$settings = instanceSettings();
if (data_get($settings, 'fqdn')) {
$url = Url::fromString($route);
$url = $url->withPort(null);
$fqdn = data_get($settings, 'fqdn');
$fqdn = str_replace(['http://', 'https://'], '', $fqdn);
$url = $url->withHost($fqdn);
return $url->__toString();
}
return $route;
}
return null;
}
public function settings()
{
return $this->hasOne(ApplicationSetting::class);
-27
View File
@@ -15,7 +15,6 @@ use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Storage;
use OpenApi\Attributes as OA;
use Spatie\Activitylog\Models\Activity;
use Spatie\Url\Url;
use Symfony\Component\Yaml\Yaml;
#[OA\Schema(
@@ -1463,32 +1462,6 @@ class Service extends BaseModel
return null;
}
public function taskLink($task_uuid)
{
if (data_get($this, 'environment.project.uuid')) {
$route = route('project.service.scheduled-tasks', [
'project_uuid' => data_get($this, 'environment.project.uuid'),
'environment_uuid' => data_get($this, 'environment.uuid'),
'service_uuid' => data_get($this, 'uuid'),
'task_uuid' => $task_uuid,
]);
$settings = InstanceSettings::get();
if (data_get($settings, 'fqdn')) {
$url = Url::fromString($route);
$url = $url->withPort(null);
$fqdn = data_get($settings, 'fqdn');
$fqdn = str_replace(['http://', 'https://'], '', $fqdn);
$url = $url->withHost($fqdn);
return $url->__toString();
}
return $route;
}
return null;
}
public function documentation()
{
$services = get_service_templates();
@@ -21,7 +21,7 @@ class ApiTokenExpiringNotification extends CustomEmailNotification
$this->onQueue('high');
$this->tokenName = $token->name;
$this->expiresAt = $token->expires_at?->format('Y-m-d H:i:s') ?? '';
$this->manageUrl = route('security.api-tokens');
$this->manageUrl = base_url().'/security/api-tokens';
}
public function via(object $notifiable): array
@@ -2,8 +2,11 @@
namespace App\Notifications\Application;
use App\Models\Application;
use App\Models\ApplicationPreview;
use App\Models\BaseModel;
use App\Models\ServiceApplication;
use App\Models\ServiceDatabase;
use App\Notifications\CustomEmailNotification;
use App\Notifications\Dto\DiscordMessage;
use App\Notifications\Dto\PushoverMessage;
@@ -49,14 +52,19 @@ class RestartLimitReached extends CustomEmailNotification
if (str($this->fqdn)->explode(',')->count() > 1) {
$this->fqdn = str($this->fqdn)->explode(',')->first();
}
$service = data_get($resource, 'service');
$this->resource_url = match (true) {
method_exists($this->resource, 'link') => $this->resource->link(),
$resource instanceof ApplicationPreview => $resource->application->link(),
is_object($service) && method_exists($service, 'link') => $service->link(),
default => null,
$this->resource_url = $this->resolveResourceUrl($resource);
}
private function resolveResourceUrl(BaseModel $resource): string
{
[$type, $uuid] = match (true) {
$resource instanceof Application => ['application', $resource->uuid],
$resource instanceof ApplicationPreview => ['application', $resource->application->uuid],
$resource instanceof ServiceApplication, $resource instanceof ServiceDatabase => ['service', $resource->service->uuid],
default => ['database', $resource->uuid],
};
$this->resource_url ??= base_url()."/project/{$this->project_uuid}/environment/{$this->environment_uuid}";
return base_url()."/project/{$this->project_uuid}/environment/{$this->environment_uuid}/{$type}/{$uuid}";
}
public function via(object $notifiable): array
@@ -2,6 +2,7 @@
namespace App\Notifications\ScheduledTask;
use App\Models\Application;
use App\Models\ScheduledTask;
use App\Notifications\CustomEmailNotification;
use App\Notifications\Dto\DiscordMessage;
@@ -16,10 +17,10 @@ class TaskFailed extends CustomEmailNotification
public function __construct(public ScheduledTask $task, public string $output)
{
$this->onQueue('high');
if ($task->application) {
$this->url = $task->application->taskLink($task->uuid);
} elseif ($task->service) {
$this->url = $task->service->taskLink($task->uuid);
$resource = $task->application ?? $task->service;
if ($resource) {
$type = $resource instanceof Application ? 'application' : 'service';
$this->url = base_url().'/project/'.data_get($resource, 'environment.project.uuid').'/environment/'.data_get($resource, 'environment.uuid')."/{$type}/{$resource->uuid}/tasks/{$task->uuid}";
}
}
@@ -2,6 +2,7 @@
namespace App\Notifications\ScheduledTask;
use App\Models\Application;
use App\Models\ScheduledTask;
use App\Notifications\CustomEmailNotification;
use App\Notifications\Dto\DiscordMessage;
@@ -16,10 +17,10 @@ class TaskSuccess extends CustomEmailNotification
public function __construct(public ScheduledTask $task, public string $output)
{
$this->onQueue('high');
if ($task->application) {
$this->url = $task->application->taskLink($task->uuid);
} elseif ($task->service) {
$this->url = $task->service->taskLink($task->uuid);
$resource = $task->application ?? $task->service;
if ($resource) {
$type = $resource instanceof Application ? 'application' : 'service';
$this->url = base_url().'/project/'.data_get($resource, 'environment.project.uuid').'/environment/'.data_get($resource, 'environment.uuid')."/{$type}/{$resource->uuid}/tasks/{$task->uuid}";
}
}
@@ -7,7 +7,6 @@ use App\Notifications\Dto\PushoverMessage;
use App\Notifications\Dto\SlackMessage;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Support\Collection;
use Spatie\Url\Url;
class SslExpirationNotification extends CustomEmailNotification
{
@@ -19,39 +18,9 @@ class SslExpirationNotification extends CustomEmailNotification
{
$this->onQueue('high');
$this->resources = collect($resources);
// Collect URLs for each resource
$this->resources->each(function ($resource) {
if (data_get($resource, 'environment.project.uuid')) {
$routeName = match ($resource->type()) {
'application' => 'project.application.configuration',
'database' => 'project.database.configuration',
'service' => 'project.service.configuration',
default => null
};
if ($routeName) {
$route = route($routeName, [
'project_uuid' => data_get($resource, 'environment.project.uuid'),
'environment_uuid' => data_get($resource, 'environment.uuid'),
$resource->type().'_uuid' => data_get($resource, 'uuid'),
]);
$settings = instanceSettings();
if (data_get($settings, 'fqdn')) {
$url = Url::fromString($route);
$url = $url->withPort(null);
$fqdn = data_get($settings, 'fqdn');
$fqdn = str_replace(['http://', 'https://'], '', $fqdn);
$url = $url->withHost($fqdn);
$this->urls[$resource->name] = $url->__toString();
} else {
$this->urls[$resource->name] = $route;
}
}
}
});
$this->urls = $this->resources->mapWithKeys(fn ($resource) => [
$resource->name => base_url().'/project/'.data_get($resource, 'environment.project.uuid').'/environment/'.data_get($resource, 'environment.uuid')."/database/{$resource->uuid}",
])->all();
}
public function via(object $notifiable): array