diff --git a/app/Filament/Pages/DeploymentPackage.php b/app/Filament/Pages/DeploymentPackage.php index ed10f0f..9cca7c4 100644 --- a/app/Filament/Pages/DeploymentPackage.php +++ b/app/Filament/Pages/DeploymentPackage.php @@ -17,6 +17,7 @@ use Filament\Schemas\Components\Grid; use Filament\Schemas\Schema; use Illuminate\Support\Collection; +use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\Http; use Livewire\Attributes\Computed; use RuntimeException; @@ -87,6 +88,7 @@ public function mount(): void ]); $this->preloadFromCommit($target); + $this->fetchAllLiveVersions(); } /** @@ -307,7 +309,7 @@ public function markDeployed(int $id): void * Szándékosan gombra fut és nem minden rendereléskor: így nem indul kimenő kérés * magától, és nem lassítja az oldalt, ha egy környezet nem válaszol. */ - public function fetchLiveVersion(string $targetKey): void + public function fetchLiveVersion(string $targetKey, bool $force = false): void { app(DeploymentGuard::class)->ensureAllowed(auth()->user()); @@ -317,15 +319,67 @@ public function fetchLiveVersion(string $targetKey): void return; } - try { - $response = Http::connectTimeout(3)->timeout(5)->get('https://'.$target['domain'].'/deploy-version.json'); + $cacheKey = 'deployment.live-version.'.$targetKey; - $this->liveVersions[$targetKey] = $response->successful() - ? ['ok' => true, 'data' => $response->json()] - : ['ok' => false, 'error' => 'HTTP '.$response->status()]; - } catch (Throwable $exception) { - $this->liveVersions[$targetKey] = ['ok' => false, 'error' => $exception->getMessage()]; + if ($force) { + Cache::forget($cacheKey); } + + // Rövid cache: az oldal minden Livewire körben újrarenderel, kérésenkénti + // HTTP hívás nélkül. A hibás választ is cache-eljük, hogy egy nem válaszoló + // környezet ne lassítsa minden kattintásnál a felületet. + $this->liveVersions[$targetKey] = Cache::remember($cacheKey, now()->addMinute(), function () use ($target): array { + try { + $response = Http::connectTimeout(2)->timeout(3)->get('https://'.$target['domain'].'/deploy-version.json'); + + return $response->successful() + ? ['ok' => true, 'data' => $response->json()] + : ['ok' => false, 'error' => 'HTTP '.$response->status()]; + } catch (Throwable $exception) { + return ['ok' => false, 'error' => $exception->getMessage()]; + } + }); + } + + /** + * Minden környezet állapotának lekérése (oldalbetöltéskor fut). + */ + public function fetchAllLiveVersions(bool $force = false): void + { + foreach (array_keys(app(DeploymentTargets::class)->all()) as $targetKey) { + $this->fetchLiveVersion($targetKey, $force); + } + } + + /** + * Melyik commiton áll melyik környezet - a commitlista megjelöléséhez. + * + * Elsődlegesen a szerverről lekérdezett élő állapotot használjuk; ha az nem + * elérhető, a naplóban kirakottként megjelölt csomagot. + * + * @return array> + */ + #[Computed] + public function commitMarkers(): array + { + $markers = []; + + foreach ($this->environmentStatuses() as $status) { + $liveCommit = ($status['live']['ok'] ?? false) ? ($status['live']['data']['commit'] ?? null) : null; + $commit = $liveCommit ?: $status['package']?->to_commit; + + if (! $commit) { + continue; + } + + $markers[$commit][] = [ + 'key' => $status['target']['key'], + 'label' => $status['target']['label'], + 'live' => (bool) $liveCommit, + ]; + } + + return $markers; } /** diff --git a/config/deployment.php b/config/deployment.php index 718ab5f..aa42de5 100644 --- a/config/deployment.php +++ b/config/deployment.php @@ -110,19 +110,24 @@ | */ + /* + | A sorrend számít: az első az alapértelmezett célkörnyezet a felületen + | (DeploymentTargets::defaultKey()). A d2d azért van elöl, mert azt frissítjük + | sűrűbben, tehát a gyakoribb eset legyen az alapértelmezés. + */ 'targets' => [ - 'e2e' => [ - 'label' => 'e2e — t2t éles', - 'domain' => 'e2e.emegrendeles.hu', - 'remote_path' => '/delirest/test.t2t.emegrendeles.hu/app/', - 'expected_branch' => 'main', - ], 'd2d' => [ 'label' => 'd2d — fejlesztői', 'domain' => 'd2d.emegrendeles.hu', 'remote_path' => '/delirest/d2d.emegrendeles.hu/app/', 'expected_branch' => 'test', ], + 'e2e' => [ + 'label' => 'e2e — t2t éles', + 'domain' => 'e2e.emegrendeles.hu', + 'remote_path' => '/delirest/test.t2t.emegrendeles.hu/app/', + 'expected_branch' => 'main', + ], ], ]; diff --git a/resources/views/filament/pages/deployment-package.blade.php b/resources/views/filament/pages/deployment-package.blade.php index 5e62c27..ce00104 100644 --- a/resources/views/filament/pages/deployment-package.blade.php +++ b/resources/views/filament/pages/deployment-package.blade.php @@ -27,9 +27,29 @@ ]; $cardClass = 'p-6 bg-white border border-gray-200 rounded-lg shadow dark:bg-gray-800 dark:border-gray-700'; + $commitMarkers = $this->commitMarkers; @endphp + {{-- + Saját stílus, nem Tailwind utility: egy új blade-ben használt osztály csak + npm run build után kerül a bundle-be (a md:grid-cols-2 pl. jelenleg nincs benne), + így a kétoszlopos elrendezés build nélkül is működik. + --}} + +
@@ -44,59 +64,47 @@
-
Környezetek állapota
+
+
Környezetek állapota
+ + Frissítés + +
-
+
@foreach ($environments as $environment) -
-
-
-

{{ $environment['target']['label'] }}

-

{{ $environment['target']['remote_path'] }}

-
- - Élő állapot - +
+
+ {{ $environment['target']['label'] }} + + @if ($environment['live'] && $environment['live']['ok']) + + élő: {{ substr($environment['live']['data']['commit'] ?? '?', 0, 7) }} + + @elseif ($environment['live']) + élő: nem elérhető + @endif
-
+
@if ($environment['package']) -

- Utoljára kirakva: - {{ substr($environment['package']->to_commit, 0, 7) }} - · {{ $environment['package']->deployed_at?->format('Y.m.d H:i') }} -

+ napló: {{ substr($environment['package']->to_commit, 0, 7) }} + · + {{ $environment['package']->deployed_at?->format('Y.m.d H:i') }} @if ($environment['behind'] !== null) -

- Lemaradás a kiválasztott branchhez képest: - {{ $environment['behind'] }} commit -

+ · + {{ $environment['behind'] }} commit lemaradás @endif @else -

Még nincs kirakottként megjelölt csomag.

- @endif - - @if ($environment['live']) - @if ($environment['live']['ok']) -

- A szerver szerint: - {{ substr($environment['live']['data']['commit'] ?? '?', 0, 7) }} - @if (($environment['live']['data']['packaged_at'] ?? null)) - · {{ \Illuminate\Support\Carbon::parse($environment['live']['data']['packaged_at'])->format('Y.m.d H:i') }} - @endif -

- @else -

Élő állapot nem lekérdezhető: {{ $environment['live']['error'] }}

- @endif - @endif - - @if ($environment['mismatch']) -

- A szerveren futó commit eltér a naplózottól — elmaradt vagy félbemaradt feltöltés. -

+ Még nincs kirakottként megjelölt csomag. @endif
+ + @if ($environment['mismatch']) +

+ A szerveren futó commit eltér a naplózottól — elmaradt vagy félbemaradt feltöltés. +

+ @endif
@endforeach
@@ -188,10 +196,14 @@
-
+
Commitok ({{ count($commits) }} db)
+

+ A hash melletti jelölés mutatja, melyik környezet áll azon a commiton — + zöld: a szervertől lekérdezve, szürke: a napló szerint. +

@if ($commits === [])

Nincs megjeleníthető commit.

@@ -229,7 +241,18 @@ class="border-b border-gray-100 dark:border-gray-700 {{ $inRange ? 'bg-primary-5
- {{ $commit['short'] }} + +
+ {{ $commit['short'] }} + + {{-- Melyik környezet áll ezen a commiton (élő állapot, vagy napló szerint). --}} + @foreach ($commitMarkers[$commit['hash']] ?? [] as $marker) + + {{ $marker['key'] }} + + @endforeach +
+ {{ \Illuminate\Support\Carbon::parse($commit['date'])->format('Y.m.d H:i') }} diff --git a/tests/Feature/DeploymentPackageTest.php b/tests/Feature/DeploymentPackageTest.php index f0e28b9..ad49006 100644 --- a/tests/Feature/DeploymentPackageTest.php +++ b/tests/Feature/DeploymentPackageTest.php @@ -11,14 +11,22 @@ use App\Services\Deployment\GitRepository; use App\Services\FeatureFlagRegistrar; use Illuminate\Foundation\Testing\RefreshDatabase; +use Illuminate\Http\Client\Factory; use Illuminate\Support\Facades\Config; use Illuminate\Support\Facades\File; +use Illuminate\Support\Facades\Http; use Livewire\Livewire; use Symfony\Component\Process\Process; use Tests\TestCase; uses(TestCase::class, RefreshDatabase::class); +// Az oldal betöltéskor lekérdezi a környezetek deploy-version.json-ját - a tesztek +// nem indíthatnak valódi kimenő kérést. +beforeEach(function () { + Http::fake(); +}); + /** * Fejlesztői gépet szimuláló környezet: az .env kapcsoló és a stage whitelist rendben. */ @@ -418,8 +426,9 @@ function deploymentCleanup(string $path): void $package = $component->get('lastPackage'); + // Alapértelmezett célkörnyezet a d2d: azt frissítjük sűrűbben. expect($package)->not->toBeNull() - ->and($package['name'])->toStartWith('deploy_e2e_') + ->and($package['name'])->toStartWith('deploy_d2d_') ->and(File::isDirectory($package['path']))->toBeTrue() ->and($package['skipped'])->toBe(['app/Elso.php']); @@ -441,7 +450,7 @@ function deploymentCleanup(string $path): void $record = DeploymentPackageRecord::query()->latest('id')->first(); expect($record)->not->toBeNull() - ->and($record->target)->toBe('e2e') + ->and($record->target)->toBe('d2d') ->and($record->to_commit)->toBe($third) ->and($record->deployed_at)->toBeNull() ->and(File::exists($record->zip_path))->toBeTrue(); @@ -460,9 +469,10 @@ function deploymentCleanup(string $path): void $this->actingAs(deploymentDeveloper()); + // Az alapértelmezett célkörnyezetre készül, hogy a második oldalbetöltés is ezt töltse elő. $record = DeploymentPackageRecord::create([ - 'name' => 'deploy_e2e_teszt', - 'target' => 'e2e', + 'name' => 'deploy_d2d_teszt', + 'target' => 'd2d', 'branch' => 'main', 'from_commit' => $first, 'to_commit' => $second, @@ -524,6 +534,31 @@ function deploymentCleanup(string $path): void deploymentCleanup($repository['path']); }); +test('az oldal alapból a d2d környezetet ajánlja és betöltéskor lekérdezi az élő állapotot', function () { + deploymentAllowEnvironment(); + $repository = deploymentTestRepository(); + [, , $third] = $repository['commits']; + + // A beforeEach-ben regisztrált catch-all stub minden URL-re illeszkedik, és a + // Http factory az ELSŐ találatot adja vissza - ezért itt új factory kell, különben + // az üres törzsű alapértelmezett válasz nyerne a konkrét stub helyett. + Http::swap(new Factory); + Http::fake([ + '*deploy-version.json' => Http::response(['target' => 'd2d', 'commit' => $third, 'branch' => 'main']), + ]); + + $this->actingAs(deploymentDeveloper()); + + $component = Livewire::test(DeploymentPackage::class); + + expect($component->get('data')['target'])->toBe('d2d') + // A lekérdezés gomb nélkül, magától megtörténik. + ->and($component->get('liveVersions')['d2d']['ok'])->toBeTrue() + ->and($component->get('liveVersions')['d2d']['data']['commit'])->toBe($third); + + deploymentCleanup($repository['path']); +}); + test('az oldal nem fogad el kamu commit azonosítót', function () { deploymentAllowEnvironment(); $repository = deploymentTestRepository();