d2d.emegrendeles.hu/resources/views/filament/pages/deployment-package.blade.php
E98Developer 7ad9c6fea8 ADD Deployment csomagoló phase2 csomag előállítása (mappa, manifest, törlendők, verziójelölő)
A kijelölt tartományból elkészül a feltölthető mappa: deploy_<target>_<időbélyeg>, benne
a fájlok eredeti relatív útvonalon, hogy a feltöltés mappa-összeolvasztás legyen.

- GitRepository::archiveTo(): git archive --format=zip + ZipArchive kicsomagolás, ~100
  fájlonként darabolva a parancssor-limit miatt. A tartalom a git objektumtárból jön, nem a
  working tree-ből: így nem szivárog ki commitolatlan módosítás, és a .gitattributes eol=lf
  miatt LF sorvéggel kerül a Linux célgépre. Üres pathspec esetén nem hívunk gitet, mert az
  a TELJES fát csomagolná.
- DeploymentPackageBuilder: _MANIFEST.json/.txt (sha1 + méret fájlonként), _TORLENDO.txt a
  törölt és az átnevezett fájlok régi útvonalával, _TEENDOK.md a diffből származó lépésekkel
  (migrate, composer install, asset-figyelmeztetés, verzió-ellenőrzés), és public/
  deploy-version.json a kirakott commit hashével.
- A git archive által kihagyott fájlok (pl. .gitattributes export-ignore) külön "missing"
  listára kerülnek - csendben hiányzó fájl a manuális deploynál a legrosszabb hiba.
- Felületen fájlonkénti kézi kivétel, megerősítéses csomagolás gomb, eredmény-kártya.
- DeploymentGuard::ensureEnvironmentAllowed(): a builder felhasználó nélkül is ellenőrzi az
  env kapcsolót és a stage whitelistet, így konzolról indítva sem fut le egy szerveren.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-16 07:09:05 +02:00

287 lines
17 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

@php
// A fázis 1 felülete csak olvas: a git történetet listázza és a kijelölt tartomány
// diffjét mutatja. A számított property-ket egy helyen kérjük le, hogy a hibabanner
// (gitError) már a renderelés elején beállított állapotot lássa.
$commits = $this->commits;
$changeSet = $this->changeSet;
$highlighted = $this->highlightedHashes;
$target = $this->target();
$statusStyles = [
'A' => ['label' => 'új', 'class' => 'bg-emerald-100 text-emerald-800 dark:bg-emerald-900 dark:text-emerald-200'],
'M' => ['label' => 'módosult', 'class' => 'bg-amber-100 text-amber-800 dark:bg-amber-900 dark:text-amber-200'],
'D' => ['label' => 'törölt', 'class' => 'bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-200'],
'R' => ['label' => 'átnevezett', 'class' => 'bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-blue-200'],
'C' => ['label' => 'másolt', 'class' => 'bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-blue-200'],
];
$warningStyles = [
'danger' => 'border-red-300 bg-red-50 text-red-900 dark:border-red-800 dark:bg-red-950 dark:text-red-200',
'warning' => 'border-amber-300 bg-amber-50 text-amber-900 dark:border-amber-800 dark:bg-amber-950 dark:text-amber-200',
'info' => 'border-gray-300 bg-gray-50 text-gray-800 dark:border-gray-700 dark:bg-gray-900 dark:text-gray-300',
];
$cardClass = 'p-6 bg-white border border-gray-200 rounded-lg shadow dark:bg-gray-800 dark:border-gray-700';
$buttonClass = 'px-2 py-1 text-xs font-semibold rounded border transition';
@endphp
<x-filament-panels::page>
<div class="space-y-6">
<div class="{{ $cardClass }}">
<h5 class="mb-2 text-2xl font-bold tracking-tight text-gray-900 dark:text-white">Deployment csomagoló</h5>
<p class="font-normal text-gray-700 dark:text-gray-400">
Válaszd ki a célkörnyezetet, majd két commitot: a köztük változott fájlok kerülnek majd a csomagba
(a kezdő commit kizárva, a záró beleértve).
</p>
<p class="mt-2 text-sm text-gray-500 dark:text-gray-400">
A csomag ide készül: <code>{{ config('deployment.output_path') }}</code>
</p>
</div>
@if ($this->lastPackage)
<div class="p-4 border rounded-lg {{ $this->lastPackage['counts']['missing'] > 0 ? $warningStyles['warning'] : 'border-emerald-300 bg-emerald-50 text-emerald-900 dark:border-emerald-800 dark:bg-emerald-950 dark:text-emerald-200' }}">
<p class="font-semibold">Elkészült: {{ $this->lastPackage['name'] }}</p>
<p class="mt-1 text-sm">
{{ $this->lastPackage['counts']['copied'] }} fájl másolva,
{{ $this->lastPackage['counts']['deleted'] }} törlendő,
{{ $this->lastPackage['counts']['skipped'] }} kézzel kivéve.
</p>
<p class="mt-2 text-xs font-mono break-all">{{ $this->lastPackage['path'] }}</p>
@if ($this->lastPackage['counts']['missing'] > 0)
<p class="mt-2 text-sm font-semibold">
Figyelem: {{ $this->lastPackage['counts']['missing'] }} fájl nem került a csomagba,
a listájuk a _MANIFEST.txt végén van.
</p>
@endif
<p class="mt-2 text-sm">
A lépéseket a csomagban lévő <code>_TEENDOK.md</code> tartalmazza.
</p>
</div>
@endif
@if ($this->gitError)
<div class="p-4 border rounded-lg {{ $warningStyles['danger'] }}">
<p class="font-semibold">Git hiba</p>
<p class="mt-1 text-sm">{{ $this->gitError }}</p>
</div>
@elseif (! $this->isRepositoryAvailable())
<div class="p-4 border rounded-lg {{ $warningStyles['danger'] }}">
<p class="font-semibold">Nem érhető el git repó</p>
<p class="mt-1 text-sm">
A(z) <code>{{ config('deployment.repo_path') }}</code> útvonalon nincs git working copy,
vagy a git parancs nem található.
</p>
</div>
@endif
<div class="{{ $cardClass }}">
{{ $this->form }}
</div>
<div class="{{ $cardClass }}">
<div class="flex flex-wrap items-center justify-between gap-4">
<div class="flex flex-wrap items-center gap-3 text-sm">
<span class="text-gray-500 dark:text-gray-400">Tartomány:</span>
@if ($this->fromCommit)
<code class="px-2 py-1 rounded bg-gray-100 dark:bg-gray-900">{{ substr($this->fromCommit, 0, 7) }}</code>
@else
<span class="text-gray-400">nincs kezdő commit</span>
@endif
<span class="text-gray-400"></span>
@if ($this->toCommit)
<code class="px-2 py-1 rounded bg-gray-100 dark:bg-gray-900">{{ substr($this->toCommit, 0, 7) }}</code>
@else
<span class="text-gray-400">nincs záró commit</span>
@endif
@if ($changeSet)
<span class="text-gray-500 dark:text-gray-400">
· {{ $changeSet['counts']['copied'] }} másolandó
@if ($changeSet['counts']['deleted'] > 0)
, {{ $changeSet['counts']['deleted'] }} törlendő
@endif
</span>
@endif
</div>
<div class="flex items-center gap-2">
<button type="button" wire:click="swapRange"
class="{{ $buttonClass }} border-gray-300 text-gray-700 hover:bg-gray-100 dark:border-gray-600 dark:text-gray-200 dark:hover:bg-gray-700">
Csere
</button>
<button type="button" wire:click="clearRange"
class="{{ $buttonClass }} border-gray-300 text-gray-700 hover:bg-gray-100 dark:border-gray-600 dark:text-gray-200 dark:hover:bg-gray-700">
Törlés
</button>
</div>
</div>
@if ($target)
<p class="mt-3 text-sm text-gray-500 dark:text-gray-400">
Cél: <strong>{{ $target['label'] }}</strong> a fájlok ide kerülnek majd feltöltésre:
<code>{{ $target['remote_path'] }}</code>
</p>
@endif
</div>
<div class="{{ $cardClass }}">
<h6 class="mb-4 text-lg font-semibold text-gray-900 dark:text-white">
Commitok
<span class="ml-1 text-sm font-normal text-gray-500 dark:text-gray-400">({{ count($commits) }} db)</span>
</h6>
@if ($commits === [])
<p class="text-sm text-gray-500 dark:text-gray-400">Nincs megjeleníthető commit.</p>
@else
<div class="overflow-x-auto">
<table class="w-full text-sm text-left">
<thead class="text-xs uppercase text-gray-600 border-b border-gray-200 dark:text-gray-300 dark:border-gray-700">
<tr>
<th class="py-2 pr-4">Kijelölés</th>
<th class="py-2 pr-4">Hash</th>
<th class="py-2 pr-4">Dátum</th>
<th class="py-2 pr-4">Szerző</th>
<th class="py-2 pr-4">Üzenet</th>
<th class="py-2 text-right">Fájl</th>
</tr>
</thead>
<tbody>
@foreach ($commits as $commit)
@php
$isFrom = $this->fromCommit === $commit['hash'];
$isTo = $this->toCommit === $commit['hash'];
$inRange = in_array($commit['hash'], $highlighted, true);
@endphp
<tr wire:key="commit-{{ $commit['hash'] }}"
class="border-b border-gray-100 dark:border-gray-700 {{ $inRange ? 'bg-primary-50 dark:bg-gray-900' : '' }}">
<td class="py-2 pr-4 whitespace-nowrap">
<button type="button" wire:click="selectFrom('{{ $commit['hash'] }}')"
class="{{ $buttonClass }} {{ $isFrom ? 'border-primary-600 bg-primary-600 text-white' : 'border-gray-300 text-gray-700 hover:bg-gray-100 dark:border-gray-600 dark:text-gray-200 dark:hover:bg-gray-700' }}">
Kezdő
</button>
<button type="button" wire:click="selectTo('{{ $commit['hash'] }}')"
class="{{ $buttonClass }} ml-1 {{ $isTo ? 'border-primary-600 bg-primary-600 text-white' : 'border-gray-300 text-gray-700 hover:bg-gray-100 dark:border-gray-600 dark:text-gray-200 dark:hover:bg-gray-700' }}">
Záró
</button>
</td>
<td class="py-2 pr-4 font-mono text-xs whitespace-nowrap">{{ $commit['short'] }}</td>
<td class="py-2 pr-4 whitespace-nowrap text-gray-600 dark:text-gray-300">
{{ \Illuminate\Support\Carbon::parse($commit['date'])->format('Y.m.d H:i') }}
</td>
<td class="py-2 pr-4 whitespace-nowrap text-gray-600 dark:text-gray-300">{{ $commit['author'] }}</td>
<td class="py-2 pr-4 text-gray-800 dark:text-gray-100">{{ $commit['subject'] }}</td>
<td class="py-2 text-right text-gray-500 dark:text-gray-400">{{ $commit['file_count'] ?? '' }}</td>
</tr>
@endforeach
</tbody>
</table>
</div>
@endif
</div>
@if ($changeSet)
<div class="{{ $cardClass }}">
<h6 class="mb-4 text-lg font-semibold text-gray-900 dark:text-white">
Változott fájlok
<span class="ml-1 text-sm font-normal text-gray-500 dark:text-gray-400">
({{ $changeSet['counts']['total'] }} db)
</span>
</h6>
@foreach ($changeSet['warnings'] as $warning)
<div class="p-4 mb-3 border rounded-lg {{ $warningStyles[$warning['level']] ?? $warningStyles['info'] }}">
<p class="font-semibold">{{ $warning['title'] }}</p>
<p class="mt-1 text-sm">{{ $warning['body'] }}</p>
</div>
@endforeach
@if ($changeSet['files'] !== [])
<div class="overflow-x-auto">
<table class="w-full text-sm text-left">
<thead class="text-xs uppercase text-gray-600 border-b border-gray-200 dark:text-gray-300 dark:border-gray-700">
<tr>
<th class="py-2 pr-4">Csomagba</th>
<th class="py-2 pr-4">Állapot</th>
<th class="py-2 pr-4">Útvonal</th>
<th class="py-2">Művelet</th>
</tr>
</thead>
<tbody>
@foreach ($changeSet['files'] as $file)
@php
$style = $statusStyles[$file['status']] ?? ['label' => $file['status'], 'class' => 'bg-gray-100 text-gray-800 dark:bg-gray-700 dark:text-gray-200'];
$isSkipped = in_array($file['path'], $this->skippedPaths, true);
@endphp
<tr wire:key="file-{{ $loop->index }}" class="border-b border-gray-100 dark:border-gray-700 {{ $file['excluded'] || $isSkipped ? 'opacity-50' : '' }}">
<td class="py-2 pr-4 whitespace-nowrap">
@if ($file['action'] === 'copy')
<input type="checkbox"
wire:click="toggleFile(@js($file['path']))"
@checked(! $isSkipped)
class="rounded border-gray-300 dark:border-gray-600">
@else
<span class="text-gray-300 dark:text-gray-600"></span>
@endif
</td>
<td class="py-2 pr-4 whitespace-nowrap">
<span class="px-2 py-0.5 text-xs font-semibold rounded {{ $style['class'] }}">
{{ $file['status'] }} · {{ $style['label'] }}
</span>
</td>
<td class="py-2 pr-4 font-mono text-xs break-all text-gray-800 dark:text-gray-100">
{{ $file['path'] }}
@if ($file['old_path'])
<span class="block text-gray-400"> {{ $file['old_path'] }}</span>
@endif
</td>
<td class="py-2 whitespace-nowrap text-gray-600 dark:text-gray-300">
@switch($file['action'])
@case('copy') {{ $isSkipped ? 'kézzel kivéve' : 'másolandó' }} @break
@case('delete') törlendő a célgépen @break
@default kihagyva (kizárási lista)
@endswitch
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
@endif
@php
$packageCount = count(array_diff($changeSet['copied'], $this->skippedPaths));
@endphp
<div class="flex flex-wrap items-center justify-between gap-4 pt-4 mt-4 border-t border-gray-200 dark:border-gray-700">
<p class="text-sm text-gray-600 dark:text-gray-300">
A csomagba <strong>{{ $packageCount }}</strong> fájl kerül
@if ($changeSet['counts']['deleted'] > 0)
, és {{ $changeSet['counts']['deleted'] }} fájl a törlendők listájára
@endif
@if ($target)
· cél: <strong>{{ $target['label'] }}</strong>
@endif
</p>
<button type="button"
wire:click="createPackage"
wire:confirm="Elkészítjük a csomagot: {{ $packageCount }} fájl{{ $target ? ' a(z) '.$target['label'].' környezethez' : '' }}. Folytatod?"
wire:loading.attr="disabled"
@disabled($packageCount === 0 && $changeSet['counts']['deleted'] === 0)
class="px-4 py-2 text-sm font-semibold text-white rounded bg-primary-600 hover:bg-primary-500 disabled:opacity-50 disabled:cursor-not-allowed">
<span wire:loading.remove wire:target="createPackage">Csomag készítése</span>
<span wire:loading wire:target="createPackage">Csomagolás…</span>
</button>
</div>
</div>
@endif
</div>
</x-filament-panels::page>