Stabilize node refresh maintenance flow
This commit is contained in:
parent
cadb9a5fcc
commit
a1387986ea
|
|
@ -2058,6 +2058,10 @@ private function startNodeRefreshJob(bool $skipMaintenance = false, bool $skipCo
|
||||||
: 'Flusso autonomo avviato: backup, maintenance con pagina 503 personalizzata, sync da Gitea, rebuild applicativo e riapertura nodo.'))
|
: 'Flusso autonomo avviato: backup, maintenance con pagina 503 personalizzata, sync da Gitea, rebuild applicativo e riapertura nodo.'))
|
||||||
->success()
|
->success()
|
||||||
->send();
|
->send();
|
||||||
|
|
||||||
|
if (! $skipMaintenance && ! $skipComposer) {
|
||||||
|
$this->dispatch('supporto-update-enter-maintenance', url: request()->fullUrl(), delay: 1200);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function loadManualSections(): void
|
private function loadManualSections(): void
|
||||||
|
|
|
||||||
|
|
@ -158,6 +158,26 @@ ## Emergenza: pagina Supporto > Modifiche in out-of-memory
|
||||||
|
|
||||||
Per la manutenzione utente finale, il nodo deve servire una `503` dedicata con refresh automatico sulla stessa URL. In questo modo l utente vede solo il messaggio di aggiornamento e rientra da solo alla pagina richiesta quando il deploy termina, senza restare mischiato a pagine parziali o a tracce tecniche.
|
Per la manutenzione utente finale, il nodo deve servire una `503` dedicata con refresh automatico sulla stessa URL. In questo modo l utente vede solo il messaggio di aggiornamento e rientra da solo alla pagina richiesta quando il deploy termina, senza restare mischiato a pagine parziali o a tracce tecniche.
|
||||||
|
|
||||||
|
Se il refresh resta `behind 1` dopo il click, controllare subito `storage/app/support/generated/git-sync-last.json` e l ultimo log in `storage/app/support/update-jobs/*.log`: un caso reale verificato e stato `Permission denied` su `resources/views/errors/.503.blade.php` durante `rsync`.
|
||||||
|
|
||||||
|
Controllo rapido permessi:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ls -ld /var/www/netgescon/resources/views/errors
|
||||||
|
ls -l /var/www/netgescon/resources/views/errors/503.blade.php
|
||||||
|
```
|
||||||
|
|
||||||
|
Correzione minima sul nodo quando il processo web usa il gruppo `www-data`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
chgrp www-data /var/www/netgescon/resources/views/errors
|
||||||
|
chmod 2775 /var/www/netgescon/resources/views/errors
|
||||||
|
chgrp www-data /var/www/netgescon/resources/views/errors/503.blade.php
|
||||||
|
chmod 664 /var/www/netgescon/resources/views/errors/503.blade.php
|
||||||
|
```
|
||||||
|
|
||||||
|
Dopo il riallineamento permessi: rilanciare `php artisan netgescon:git-sync --remote=origin --branch=main` o il pulsante UI e poi `php artisan optimize:clear`.
|
||||||
|
|
||||||
## Rilascio operativo 2026-04-06
|
## Rilascio operativo 2026-04-06
|
||||||
|
|
||||||
Questo e il blocco che puo essere aggiornato adesso con la procedura Git-first senza correzioni manuali extra su staging.
|
Questo e il blocco che puo essere aggiornato adesso con la procedura Git-first senza correzioni manuali extra su staging.
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,14 @@ ### Supporto > Modifiche con `ProgramAclService` assente su nodo staging
|
||||||
- Stato: [U] validato su `/var/www/netgescon` con service realmente assente; `App\Filament\Pages\Supporto\Modifiche::canAccess()` non genera piu eccezioni e ritorna correttamente `true` per un utente amministrativo.
|
- Stato: [U] validato su `/var/www/netgescon` con service realmente assente; `App\Filament\Pages\Supporto\Modifiche::canAccess()` non genera piu eccezioni e ritorna correttamente `true` per un utente amministrativo.
|
||||||
- Prevenzione: nelle pagine di supporto e deploy evitare dipendenze rigide da moduli opzionali o non ancora allineati sul nodo; il pannello di recupero deve sempre avere un percorso di fallback minimale.
|
- Prevenzione: nelle pagine di supporto e deploy evitare dipendenze rigide da moduli opzionali o non ancora allineati sul nodo; il pannello di recupero deve sempre avere un percorso di fallback minimale.
|
||||||
|
|
||||||
|
### Refresh nodo bloccato da permessi deploy su `resources/views/errors`
|
||||||
|
|
||||||
|
- Problema: il launcher aggiornamento nodo restava a `behind 1`, la `503` compariva solo per un attimo e la UI del launcher restava visibile con polling e pulsanti, costringendo a refresh manuali.
|
||||||
|
- Causa tecnica: `netgescon:git-sync` falliva nel passaggio `rsync` verso `/var/www/netgescon` con `Permission denied` su `resources/views/errors/.503.blade.php`; il repository sorgente arrivava al commit remoto ma il checkout applicativo non riceveva i file nuovi.
|
||||||
|
- Fix applicato: permessi riallineati su `/var/www/netgescon/resources/views/errors` e `503.blade.php` al gruppo `www-data`; il launcher ora forza anche una navigazione piena alla stessa URL quando parte il refresh con maintenance, cosi il browser mostra la `503` completa invece di restare nella UI Livewire.
|
||||||
|
- Stato: [U] validato su staging locale; `git-sync-last.json` torna `completed`, commit deploy e remoto risultano allineati (`cadb9a5` nel caso reale) e il nodo torna a `ahead 0 / behind 0`.
|
||||||
|
- Prevenzione: le directory che devono ricevere file nuovi via deploy web devono restare group-writable per il gruppo del processo PHP/web (`www-data` qui); quando una directory viene creata manualmente sul nodo, impostare subito gruppo coerente e bit setgid.
|
||||||
|
|
||||||
### Ripristino bootstrap pannello admin
|
### Ripristino bootstrap pannello admin
|
||||||
|
|
||||||
- Problema: `AdminFilamentPanelProvider.php` era stato corrotto da una modifica incompleta e impediva il bootstrap corretto.
|
- Problema: `AdminFilamentPanelProvider.php` era stato corrotto da una modifica incompleta e impediva il bootstrap corretto.
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,28 @@
|
||||||
<x-filament-panels::page>
|
<x-filament-panels::page>
|
||||||
|
<script>
|
||||||
|
window.addEventListener('supporto-update-enter-maintenance', function (event) {
|
||||||
|
const detail = event.detail || {};
|
||||||
|
const delay = Number(detail.delay || 1200);
|
||||||
|
const targetUrl = detail.url || window.location.href;
|
||||||
|
|
||||||
|
window.setTimeout(function () {
|
||||||
|
window.location.href = targetUrl;
|
||||||
|
}, delay);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
@php
|
@php
|
||||||
$supportUpdateAuthUser = auth()->user();
|
$supportUpdateAuthUser = auth()->user();
|
||||||
$supportCanRunUpdate = $supportUpdateAuthUser && method_exists($supportUpdateAuthUser, 'hasAnyRole') && $supportUpdateAuthUser->hasAnyRole(['super-admin', 'admin', 'amministratore']);
|
$supportCanRunUpdate = $supportUpdateAuthUser && method_exists($supportUpdateAuthUser, 'hasAnyRole') && $supportUpdateAuthUser->hasAnyRole(['super-admin', 'admin', 'amministratore']);
|
||||||
|
$supportUsesDaemon = config('distribution.update_executor', 'local') === 'daemon';
|
||||||
@endphp
|
@endphp
|
||||||
|
|
||||||
<div class="space-y-4 text-xs">
|
<div class="space-y-4 text-xs">
|
||||||
<div class="rounded-xl border border-sky-200 bg-sky-50 p-4">
|
<div class="rounded-xl border border-sky-200 bg-sky-50 p-4">
|
||||||
<div class="flex flex-wrap items-start justify-between gap-3">
|
<div class="flex flex-wrap items-start justify-between gap-3">
|
||||||
<div>
|
<div>
|
||||||
<div class="text-sm font-semibold text-sky-900">Launcher esterno per update e sync Git</div>
|
<div class="text-sm font-semibold text-sky-900">Launcher autonomo aggiornamento nodo</div>
|
||||||
<div class="mt-1 text-[11px] text-sky-800">
|
<div class="mt-1 text-[11px] text-sky-800">
|
||||||
Usa questa pagina per lanciare aggiornamenti senza restare dentro la pagina completa Modifiche mentre Livewire e i file vengono riallineati. Il flusso principale da Gitea ora blocca nuove richieste, crea il backup pre-update, aggiorna DB e ricostruisce l'app prima di riaprire il nodo.
|
Questa pagina espone un solo flusso operativo: aggiornamento autonomo del nodo da browser, senza accesso shell al sistema remoto. @if($supportUsesDaemon) Il pulsante accoda la richiesta a un daemon host Docker che esegue il refresh completo. @else Il job viene eseguito direttamente dall'applicazione. @endif
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-wrap gap-2">
|
<div class="flex flex-wrap gap-2">
|
||||||
|
|
@ -31,8 +43,8 @@
|
||||||
|
|
||||||
<div class="grid gap-4 xl:grid-cols-[1.2fr_0.8fr]">
|
<div class="grid gap-4 xl:grid-cols-[1.2fr_0.8fr]">
|
||||||
<div class="rounded-xl border bg-white p-4">
|
<div class="rounded-xl border bg-white p-4">
|
||||||
<div class="text-sm font-semibold text-slate-900">Refresh nodo da Gitea</div>
|
<div class="text-sm font-semibold text-slate-900">Aggiornamento remoto in sicurezza</div>
|
||||||
<div class="mt-1 text-[11px] text-slate-500">Flusso consigliato per staging e nodi interni: backup, finestra protetta, sync Git, dipendenze, migrate e cache rebuild.</div>
|
<div class="mt-1 text-[11px] text-slate-500">Un solo pulsante, job asincrono e ripartenza automatica del nodo. Il recupero resta applicativo: log supporto, runtime errors e richieste help continuano a restare nel progetto.</div>
|
||||||
|
|
||||||
@if(! $this->ticketAttachmentMetadataReady)
|
@if(! $this->ticketAttachmentMetadataReady)
|
||||||
<div class="mt-3 rounded-lg border border-amber-300 bg-amber-50 p-3 text-[11px] text-amber-900">
|
<div class="mt-3 rounded-lg border border-amber-300 bg-amber-50 p-3 text-[11px] text-amber-900">
|
||||||
|
|
@ -56,20 +68,8 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mt-3 flex flex-wrap gap-2">
|
<div class="mt-3 flex flex-wrap gap-2">
|
||||||
<x-filament::button size="sm" color="success" wire:click="runNodeRefresh" :disabled="!$supportCanRunUpdate">
|
<x-filament::button size="sm" color="success" wire:click="runAutonomousNodeRefresh" :disabled="!$supportCanRunUpdate || $this->updateInProgress">
|
||||||
Aggiorna nodo completo da Gitea
|
Aggiorna nodo automaticamente
|
||||||
</x-filament::button>
|
|
||||||
<x-filament::button size="sm" color="warning" wire:click="runNodeRefresh" :disabled="!$supportCanRunUpdate">
|
|
||||||
Aggiorna staging da Gitea
|
|
||||||
</x-filament::button>
|
|
||||||
<x-filament::button size="sm" color="gray" wire:click="runNodeRefreshFallback" :disabled="!$supportCanRunUpdate">
|
|
||||||
Refresh di riserva senza maintenance
|
|
||||||
</x-filament::button>
|
|
||||||
<x-filament::button size="sm" color="danger" wire:click="runNodeRefreshSkipComposer" :disabled="!$supportCanRunUpdate">
|
|
||||||
Recovery senza composer
|
|
||||||
</x-filament::button>
|
|
||||||
<x-filament::button size="sm" wire:click="runGitSync" :disabled="!$supportCanRunUpdate">
|
|
||||||
Solo sync Git avanzata
|
|
||||||
</x-filament::button>
|
</x-filament::button>
|
||||||
<x-filament::button size="sm" color="info" wire:click="refreshUpdateProgress" :disabled="!$this->updateInProgress">
|
<x-filament::button size="sm" color="info" wire:click="refreshUpdateProgress" :disabled="!$this->updateInProgress">
|
||||||
Aggiorna avanzamento refresh
|
Aggiorna avanzamento refresh
|
||||||
|
|
@ -77,15 +77,31 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mt-3 rounded-lg border border-amber-200 bg-amber-50 p-3 text-[11px] text-amber-900">
|
<div class="mt-3 rounded-lg border border-amber-200 bg-amber-50 p-3 text-[11px] text-amber-900">
|
||||||
Il pulsante <span class="font-semibold">Aggiorna staging da Gitea</span> esegue il refresh completo del nodo: backup pre-update, maintenance mode per bloccare nuove operazioni utente, sync da Gitea, <span class="font-mono">composer install</span>, tentativo di build frontend se disponibile, <span class="font-mono">migrate --force</span>, pulizia cache, rebuild Blade e riapertura automatica del sistema.
|
Il pulsante <span class="font-semibold">Aggiorna nodo automaticamente</span> esegue il refresh completo: backup pre-update solo se riattivato, maintenance mode con pagina 503 personalizzata, sync da Gitea, <span class="font-mono">composer install</span>, build frontend se disponibile, <span class="font-mono">migrate --force</span>, pulizia cache, rebuild Blade e riapertura automatica del sistema.
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mt-3 rounded-lg border border-slate-200 bg-slate-50 p-3 text-[11px] text-slate-600">
|
<div class="mt-3 rounded-lg border border-slate-200 bg-slate-50 p-3 text-[11px] text-slate-600">
|
||||||
Se la macchina remota fallisce su <span class="font-mono">Maintenance mode non attivata</span>, prima allinea il nodo con <span class="font-semibold">Solo sync Git avanzata</span> e poi usa <span class="font-semibold">Refresh di riserva senza maintenance</span>. E un percorso di recupero per nodi dove il blocco accessi Laravel non parte correttamente.
|
Se il job trova un errore, l esito resta tracciato in output completo, log supporto e runtime errors. Questo permette di diagnosticare e correggere il problema dal progetto, senza prendere il controllo del nodo remoto.
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mt-3 rounded-lg border border-rose-200 bg-rose-50 p-3 text-[11px] text-rose-900">
|
@if($supportUsesDaemon)
|
||||||
Se il nodo e gia allineato ma il refresh fallisce su <span class="font-mono">vendor/composer/autoload_classmap.php: Permission denied</span>, usa <span class="font-semibold">Recovery senza composer</span>. Serve solo per chiudere migrate e cache rebuild quando non stai installando nuove dipendenze PHP.
|
<div class="mt-3 rounded-lg border border-sky-200 bg-sky-50 p-3 text-[11px] text-sky-900">
|
||||||
|
Executor attivo: <span class="font-semibold">daemon host Docker</span>. Il pannello accoda la richiesta, poi il runner host esegue <span class="font-mono">docker/update-multisite.sh</span> e aggiorna questo avanzamento senza shell manuale.
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
<div class="mt-3 rounded-lg border border-emerald-200 bg-emerald-50 p-3 text-[11px] text-emerald-900">
|
||||||
|
Backup e continuita: l aggiornamento nasce per lavorare con backup automatico e copie su Drive quando abilitate, cosi il nodo resta semplice da installare in Docker e sicuro da aggiornare anche senza interventi manuali sul sistema.
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mt-3 rounded-lg border border-slate-200 bg-slate-50 p-3 text-[11px] text-slate-700">
|
||||||
|
<div class="font-semibold text-slate-900">Passi pianificati dal launcher</div>
|
||||||
|
<ul class="mt-2 space-y-1 pl-4 list-disc">
|
||||||
|
@foreach($this->updatePlannedSteps as $plannedStep)
|
||||||
|
<li>{{ $plannedStep }}</li>
|
||||||
|
@endforeach
|
||||||
|
<li>Segnalazioni supporto, richieste help e errori runtime restano consultabili dalla suite Supporto dopo il refresh.</li>
|
||||||
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@if($this->updateInProgress)
|
@if($this->updateInProgress)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user