Skip to content

Commit

Permalink
Merge branch 'pelican-dev:main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
thibaultjunin authored Dec 24, 2024
2 parents 94ce119 + 00644c2 commit d9e9541
Show file tree
Hide file tree
Showing 10 changed files with 669 additions and 3 deletions.
43 changes: 43 additions & 0 deletions app/Checks/NodeVersionsCheck.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php

namespace App\Checks;

use App\Models\Node;
use App\Services\Helpers\SoftwareVersionService;
use Spatie\Health\Checks\Check;
use Spatie\Health\Checks\Result;
use Spatie\Health\Enums\Status;

class NodeVersionsCheck extends Check
{
public function __construct(private SoftwareVersionService $versionService) {}

public function run(): Result
{
$all = Node::query()->count();

if ($all === 0) {
$result = Result::make()->notificationMessage('No Nodes created')->shortSummary('No Nodes');
$result->status = Status::skipped();

return $result;
}

$latestVersion = $this->versionService->latestWingsVersion();

$outdated = Node::query()->get()
->filter(fn (Node $node) => !isset($node->systemInformation()['exception']) && $node->systemInformation()['version'] !== $latestVersion)
->count();

$result = Result::make()
->meta([
'all' => $all,
'outdated' => $outdated,
])
->shortSummary($outdated === 0 ? 'All up-to-date' : "{$outdated}/{$all} outdated");

return $outdated === 0
? $result->ok('All Nodes are up-to-date.')
: $result->failed(':outdated/:all Nodes are outdated.');
}
}
31 changes: 31 additions & 0 deletions app/Checks/PanelVersionCheck.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

namespace App\Checks;

use App\Services\Helpers\SoftwareVersionService;
use Spatie\Health\Checks\Check;
use Spatie\Health\Checks\Result;

class PanelVersionCheck extends Check
{
public function __construct(private SoftwareVersionService $versionService) {}

public function run(): Result
{
$isLatest = $this->versionService->isLatestPanel();
$currentVersion = $this->versionService->currentPanelVersion();
$latestVersion = $this->versionService->latestPanelVersion();

$result = Result::make()
->meta([
'isLatest' => $isLatest,
'currentVersion' => $currentVersion,
'latestVersion' => $latestVersion,
])
->shortSummary($isLatest ? 'up-to-date' : 'outdated');

return $isLatest
? $result->ok('Panel is up-to-date.')
: $result->failed('Installed version is `:currentVersion` but latest is `:latestVersion`.');
}
}
16 changes: 16 additions & 0 deletions app/Checks/UsedDiskSpaceCheck.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

namespace App\Checks;

use Spatie\Health\Checks\Checks\UsedDiskSpaceCheck as BaseCheck;

class UsedDiskSpaceCheck extends BaseCheck
{
protected function getDiskUsagePercentage(): int
{
$freeSpace = disk_free_space($this->filesystemName ?? '/');
$totalSpace = disk_total_space($this->filesystemName ?? '/');

return 100 - ($freeSpace * 100 / $totalSpace);
}
}
5 changes: 5 additions & 0 deletions app/Console/Kernel.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Database\Console\PruneCommand;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
use Spatie\Health\Commands\RunHealthChecksCommand;
use Spatie\Health\Commands\ScheduleCheckHeartbeatCommand;

class Kernel extends ConsoleKernel
{
Expand Down Expand Up @@ -53,5 +55,8 @@ protected function schedule(Schedule $schedule): void
if (config('panel.webhook.prune_days')) {
$schedule->command(PruneCommand::class, ['--model' => [Webhook::class]])->daily();
}

$schedule->command(ScheduleCheckHeartbeatCommand::class)->everyMinute();
$schedule->command(RunHealthChecksCommand::class)->everyFiveMinutes();
}
}
120 changes: 120 additions & 0 deletions app/Filament/Admin/Pages/Health.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
<?php

namespace App\Filament\Admin\Pages;

use Carbon\Carbon;
use Filament\Actions\Action;
use Filament\Notifications\Notification;
use Filament\Pages\Page;
use Illuminate\Support\Facades\Artisan;
use Spatie\Health\Commands\RunHealthChecksCommand;
use Spatie\Health\ResultStores\ResultStore;

class Health extends Page
{
protected static ?string $navigationIcon = 'tabler-heart';

protected static ?string $navigationGroup = 'Advanced';

protected static string $view = 'filament.pages.health';

// @phpstan-ignore-next-line
protected $listeners = [
'refresh-component' => '$refresh',
];

protected function getActions(): array
{
return [
Action::make('refresh')
->button()
->action('refresh'),
];
}

protected function getViewData(): array
{
// @phpstan-ignore-next-line
$checkResults = app(ResultStore::class)->latestResults();

if ($checkResults === null) {
Artisan::call(RunHealthChecksCommand::class);

$this->dispatch('refresh-component');
}

return [
'lastRanAt' => new Carbon($checkResults?->finishedAt),
'checkResults' => $checkResults,
];
}

public function refresh(): void
{
Artisan::call(RunHealthChecksCommand::class);

$this->dispatch('refresh-component');

Notification::make()
->title('Health check results refreshed')
->success()
->send();
}

public static function getNavigationBadge(): ?string
{
// @phpstan-ignore-next-line
$results = app(ResultStore::class)->latestResults();

if ($results === null) {
return null;
}

$results = json_decode($results->toJson(), true);

$failed = array_reduce($results['checkResults'], function ($numFailed, $result) {
return $numFailed + ($result['status'] === 'failed' ? 1 : 0);
}, 0);

return $failed === 0 ? null : (string) $failed;
}

public static function getNavigationBadgeColor(): string
{
return self::getNavigationBadge() > null ? 'danger' : '';
}

public static function getNavigationBadgeTooltip(): ?string
{
// @phpstan-ignore-next-line
$results = app(ResultStore::class)->latestResults();

if ($results === null) {
return null;
}

$results = json_decode($results->toJson(), true);

$failedNames = array_reduce($results['checkResults'], function ($carry, $result) {
if ($result['status'] === 'failed') {
$carry[] = $result['name'];
}

return $carry;
}, []);

return 'Failed: ' . implode(', ', $failedNames);
}

public static function getNavigationIcon(): string
{
// @phpstan-ignore-next-line
$results = app(ResultStore::class)->latestResults();

if ($results === null) {
return 'tabler-heart-question';
}

return $results->containsFailingCheck() ? 'tabler-heart-exclamation' : 'tabler-heart-check';
}
}
23 changes: 23 additions & 0 deletions app/Providers/AppServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

namespace App\Providers;

use App\Checks\NodeVersionsCheck;
use App\Checks\PanelVersionCheck;
use App\Checks\UsedDiskSpaceCheck;
use App\Filament\Server\Pages\Console;
use App\Models;
use App\Models\ApiKey;
Expand All @@ -26,6 +29,12 @@
use Illuminate\Support\Str;
use Laravel\Sanctum\Sanctum;
use SocialiteProviders\Manager\SocialiteWasCalled;
use Spatie\Health\Checks\Checks\CacheCheck;
use Spatie\Health\Checks\Checks\DatabaseCheck;
use Spatie\Health\Checks\Checks\DebugModeCheck;
use Spatie\Health\Checks\Checks\EnvironmentCheck;
use Spatie\Health\Checks\Checks\ScheduleCheck;
use Spatie\Health\Facades\Health;

class AppServiceProvider extends ServiceProvider
{
Expand Down Expand Up @@ -103,6 +112,20 @@ public function boot(Application $app, SoftwareVersionService $versionService):
scopes: Console::class,
);

// Don't run any health checks during tests
if (!$app->runningUnitTests()) {
Health::checks([
DebugModeCheck::new()->if($app->isProduction()),
EnvironmentCheck::new(),
CacheCheck::new(),
DatabaseCheck::new(),
ScheduleCheck::new(),
UsedDiskSpaceCheck::new(),
PanelVersionCheck::new(),
NodeVersionsCheck::new(),
]);
}

Gate::before(function (User $user, $ability) {
return $user->isRootAdmin() ? true : null;
});
Expand Down
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
"socialiteproviders/discord": "^4.2",
"socialiteproviders/steam": "^4.2",
"spatie/laravel-fractal": "^6.2",
"spatie/laravel-health": "^1.30",
"spatie/laravel-permission": "^6.9",
"spatie/laravel-query-builder": "^5.8.1",
"spatie/temporary-directory": "^2.2",
Expand Down Expand Up @@ -92,4 +93,4 @@
},
"minimum-stability": "stable",
"prefer-stable": true
}
}
Loading

0 comments on commit d9e9541

Please sign in to comment.