Add notification for deployment completion (#445)

* Add notification for deployment completion

Add notification for deployment completion status.

* Create `DeploymentCompleted` notification class in `app/Notifications/DeploymentCompleted.php` to handle deployment completion notifications.
* Update `app/Actions/Site/Deploy.php` to send `DeploymentCompleted` notification using `Notifier` when a deployment completes or fails.
* Import `Notifier` and `DeploymentCompleted` classes in `app/Actions/Site/Deploy.php`.

---

For more details, open the [Copilot Workspace session](https://copilot-workspace.githubnext.com/vitodeploy/vito?shareId=XXXX-XXXX-XXXX-XXXX).

* Format with pint

* Add tests

* Pint format

* Delete tests/Feature/Notifications/DeploymentCompletedTest.php

* Delete tests/Unit/Notifications/DeploymentCompletedTest.php

* 🍻🍻

* tests

---------

Co-authored-by: Saeed Vaziry <61919774+saeedvaziry@users.noreply.github.com>
Co-authored-by: Saeed Vaziry <mr.saeedvaziry@gmail.com>
This commit is contained in:
Pierluigi Cau (PG) 2025-01-30 02:29:51 +08:00 committed by GitHub
parent 7b723bcba5
commit d702b95e0c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 65 additions and 4 deletions

View File

@ -5,9 +5,11 @@
use App\Enums\DeploymentStatus; use App\Enums\DeploymentStatus;
use App\Exceptions\DeploymentScriptIsEmptyException; use App\Exceptions\DeploymentScriptIsEmptyException;
use App\Exceptions\SSHError; use App\Exceptions\SSHError;
use App\Facades\Notifier;
use App\Models\Deployment; use App\Models\Deployment;
use App\Models\ServerLog; use App\Models\ServerLog;
use App\Models\Site; use App\Models\Site;
use App\Notifications\DeploymentCompleted;
class Deploy class Deploy
{ {
@ -53,9 +55,11 @@ public function run(Site $site): Deployment
); );
$deployment->status = DeploymentStatus::FINISHED; $deployment->status = DeploymentStatus::FINISHED;
$deployment->save(); $deployment->save();
})->catch(function () use ($deployment) { Notifier::send($site, new DeploymentCompleted($deployment, $site));
})->catch(function () use ($deployment, $site) {
$deployment->status = DeploymentStatus::FAILED; $deployment->status = DeploymentStatus::FAILED;
$deployment->save(); $deployment->save();
Notifier::send($site, new DeploymentCompleted($deployment, $site));
})->onConnection('ssh'); })->onConnection('ssh');
return $deployment; return $deployment;

View File

@ -0,0 +1,50 @@
<?php
namespace App\Notifications;
use App\Models\Deployment;
use App\Models\Site;
use Illuminate\Notifications\Messages\MailMessage;
class DeploymentCompleted extends AbstractNotification
{
protected Deployment $deployment;
protected Site $site;
public function __construct(Deployment $deployment, Site $site)
{
$this->deployment = $deployment;
$this->site = $site;
}
public function rawText(): string
{
return __('Deployment for site [:site] has completed with status: :status', [
'site' => $this->site->domain,
'status' => $this->deployment->status,
]);
}
public function toEmail(object $notifiable): MailMessage
{
return (new MailMessage)
->subject(__('Deployment Completed'))
->line('Deployment for site ['.$this->site->domain.'] has completed with status: '.$this->deployment->status);
}
public function toSlack(object $notifiable): string
{
return $this->rawText();
}
public function toDiscord(object $notifiable): string
{
return $this->rawText();
}
public function toTelegram(object $notifiable): string
{
return $this->rawText();
}
}

View File

@ -5,10 +5,12 @@
use App\Enums\DeploymentStatus; use App\Enums\DeploymentStatus;
use App\Facades\SSH; use App\Facades\SSH;
use App\Models\GitHook; use App\Models\GitHook;
use App\Notifications\DeploymentCompleted;
use App\Web\Pages\Servers\Sites\View; use App\Web\Pages\Servers\Sites\View;
use App\Web\Pages\Servers\Sites\Widgets\DeploymentsList; use App\Web\Pages\Servers\Sites\Widgets\DeploymentsList;
use Illuminate\Foundation\Testing\RefreshDatabase; use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Http; use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Notification;
use Livewire\Livewire; use Livewire\Livewire;
use Tests\TestCase; use Tests\TestCase;
@ -65,6 +67,7 @@ public function test_deploy(): void
], ],
]), ]),
]); ]);
Notification::fake();
$this->site->deploymentScript->update([ $this->site->deploymentScript->update([
'content' => 'git pull', 'content' => 'git pull',
@ -88,6 +91,8 @@ public function test_deploy(): void
SSH::assertExecutedContains('cd /home/vito/'.$this->site->domain); SSH::assertExecutedContains('cd /home/vito/'.$this->site->domain);
SSH::assertExecutedContains('git pull'); SSH::assertExecutedContains('git pull');
Notification::assertSentTo($this->notificationChannel, DeploymentCompleted::class);
$this->get( $this->get(
View::getUrl([ View::getUrl([
'server' => $this->server, 'server' => $this->server,

View File

@ -3,10 +3,10 @@
namespace Tests; namespace Tests;
use App\Enums\Database; use App\Enums\Database;
use App\Enums\NotificationChannel;
use App\Enums\ServiceStatus; use App\Enums\ServiceStatus;
use App\Enums\UserRole; use App\Enums\UserRole;
use App\Enums\Webserver; use App\Enums\Webserver;
use App\Models\NotificationChannel;
use App\Models\Server; use App\Models\Server;
use App\Models\Site; use App\Models\Site;
use App\Models\SourceControl; use App\Models\SourceControl;
@ -24,6 +24,8 @@ abstract class TestCase extends BaseTestCase
protected Site $site; protected Site $site;
protected NotificationChannel $notificationChannel;
public const EXPECT_SUCCESS = true; public const EXPECT_SUCCESS = true;
public const EXPECT_FAILURE = false; public const EXPECT_FAILURE = false;
@ -40,8 +42,8 @@ protected function setUp(): void
]); ]);
$this->user->createDefaultProject(); $this->user->createDefaultProject();
\App\Models\NotificationChannel::factory()->create([ $this->notificationChannel = NotificationChannel::factory()->create([
'provider' => NotificationChannel::EMAIL, 'provider' => \App\Enums\NotificationChannel::EMAIL,
'connected' => true, 'connected' => true,
'data' => [ 'data' => [
'email' => 'user@example.com', 'email' => 'user@example.com',