Add update lookup and telemetry, Add version and build to app config

This commit is contained in:
Constantin Graf
2024-10-04 21:59:02 +02:00
committed by Gregor Vostrak
parent f147fb9725
commit 2372ee0622
31 changed files with 1195 additions and 680 deletions

View File

@@ -0,0 +1,46 @@
<?php
declare(strict_types=1);
namespace App\Console\Commands\SelfHost;
use App\Service\ApiService;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Cache;
class SelfHostCheckForUpdateCommand extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'self-host:check-for-update';
/**
* The console command description.
*
* @var string
*/
protected $description = '';
/**
* Execute the console command.
*/
public function handle(): int
{
$apiService = app(ApiService::class);
$latestVersion = $apiService->checkForUpdate();
if ($latestVersion === null) {
$this->error('Failed to check for update, check the logs for more information.');
return self::FAILURE;
}
// Note: Cache for 13 hours, because the command runs twice daily (every 12 hours).
Cache::put('latest_version', $latestVersion, 60 * 60 * 12);
return self::SUCCESS;
}
}

View File

@@ -0,0 +1,44 @@
<?php
declare(strict_types=1);
namespace App\Console\Commands\SelfHost;
use App\Service\ApiService;
use Illuminate\Console\Command;
class SelfHostTelemetryCommand extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'self-host:telemetry';
/**
* The console command description.
*
* @var string
*/
protected $description = '';
/**
* Execute the console command.
*/
public function handle(): int
{
$apiService = app(ApiService::class);
$success = $apiService->telemetry();
if (! $success) {
$this->error('Failed to send telemetry data, check the logs for more information.');
return self::FAILURE;
}
return self::SUCCESS;
}
}

View File

@@ -17,6 +17,14 @@ class Kernel extends ConsoleKernel
$schedule->command('time-entry:send-still-running-mails')
->when(fn (): bool => config('scheduling.tasks.time_entry_send_still_running_mails'))
->everyTenMinutes();
$schedule->command('self-hosting:check-for-update')
->when(fn (): bool => config('scheduling.tasks.self_hosting_check_for_update'))
->twiceDaily();
$schedule->command('self-hosting:telemetry')
->when(fn (): bool => config('scheduling.tasks.self_hosting_telemetry'))
->twiceDaily();
}
/**

View File

@@ -0,0 +1,34 @@
<?php
declare(strict_types=1);
namespace App\Filament\Widgets;
use Filament\Widgets\Widget;
use Illuminate\Support\Facades\Cache;
class ServerOverview extends Widget
{
protected static string $view = 'filament.widgets.server-overview';
/**
* @return array<string, mixed>
*/
protected function getViewData(): array
{
$currentVersion = Cache::get('latest_version', null);
$needsUpdate = false;
if ($currentVersion !== null && version_compare($currentVersion, config('app.version')) > 0) {
$needsUpdate = true;
}
return [
'version' => config('app.version'),
'build' => config('app.build'),
'environment' => config('app.env'),
'currentVersion' => $currentVersion,
'needsUpdate' => $needsUpdate,
];
}
}

View File

@@ -5,6 +5,7 @@ declare(strict_types=1);
namespace App\Providers\Filament;
use App\Filament\Widgets\ActiveUserOverview;
use App\Filament\Widgets\ServerOverview;
use App\Filament\Widgets\TimeEntriesCreated;
use App\Filament\Widgets\TimeEntriesImported;
use App\Filament\Widgets\UserRegistrations;
@@ -44,11 +45,13 @@ class AdminPanelProvider extends PanelProvider
])
->discoverWidgets(in: app_path('Filament/Widgets'), for: 'App\\Filament\\Widgets')
->widgets([
ServerOverview::class,
ActiveUserOverview::class,
UserRegistrations::class,
TimeEntriesCreated::class,
TimeEntriesImported::class,
])
->viteTheme('resources/css/filament/admin/theme.css')
->plugins([
EnvironmentIndicatorPlugin::make()
->color(fn () => match (App::environment()) {

View File

@@ -0,0 +1,93 @@
<?php
declare(strict_types=1);
namespace App\Service;
use App\Models\Audit;
use App\Models\Client;
use App\Models\Organization;
use App\Models\Project;
use App\Models\ProjectMember;
use App\Models\Task;
use App\Models\TimeEntry;
use App\Models\User;
use Exception;
use Illuminate\Support\Facades\Http;
use Log;
class ApiService
{
private const string API_URL = 'https://app.solidtime.io/api';
public function checkForUpdate(): ?string
{
try {
$response = Http::asJson()
->timeout(3)
->connectTimeout(2)
->post(self::API_URL.'/check-for-update', [
'version' => config('app.version'),
'build' => config('app.build'),
'url' => config('app.url'),
]);
if ($response->status() === 200 && isset($response->json()['version']) && is_string($response->json()['version'])) {
return $response->json()['version'];
} else {
Log::warning('Failed to check for update', [
'status' => $response->status(),
'body' => $response->body(),
]);
return null;
}
} catch (\Throwable $e) {
Log::warning('Failed to check for update', [
'message' => $e->getMessage(),
]);
return null;
}
}
public function telemetry(): bool
{
try {
$response = Http::asJson()
->timeout(3)
->connectTimeout(2)
->post(self::API_URL.'/telemetry', [
'version' => config('app.version'),
'build' => config('app.build'),
'url' => config('app.url'),
// telemetry data
'user_count' => User::count(),
'organization_count' => Organization::count(),
'audit_count' => Audit::count(),
'project_count' => Project::count(),
'project_member_count' => ProjectMember::count(),
'client_count' => Client::count(),
'task_count' => Task::count(),
'time_entry_count' => TimeEntry::count(),
]);
if ($response->status() === 200) {
return true;
} else {
Log::warning('Failed send telemetry data', [
'status' => $response->status(),
'body' => $response->body(),
]);
return false;
}
} catch (Exception $e) {
Log::warning('Failed send telemetry data', [
'message' => $e->getMessage(),
]);
return false;
}
}
}