docs(handover): release workflow + hot-reload PHP + disciplina commit (attivita primaria)
Aggiunto da AgileHub-side (VIGILE) su autorizzazione esplicita utente, dopo che la
sessione NIS2 ha scoperto sul campo 2 lezioni critiche:
1. opcache.validate_timestamps=Off -> ogni edit .php richiede kill -USR2 1 nel
container FPM (bind-mount non basta a servire il nuovo bytecode)
2. modifiche non committate vengono revertate dal cron ticket-agent (caso reale:
commit d5d83bb ha revertato index.php di una Feature 1 WIP)
- Nuovo doc docs/INCOMING_FROM_AGILEHUB_2026_05_30_release_workflow_hot_reload.md
- Sezione ATTIVITA PRIMARIA inserita in CLAUDE.md subito dopo lo standard timezone
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.7
parent
4924075142
commit
f8f78b5ece
@@ -0,0 +1,135 @@
|
||||
# OUTGOING → NIS2 — Workflow di rilascio + hot-reload PHP (2026-05-30)
|
||||
|
||||
> **Da**: AgileHub-side (VIGILE)
|
||||
> **A**: sessione Claude `nis2-agile-devenv` (e qualsiasi sessione futura che lavora su NIS2)
|
||||
> **Trigger**: l'utente ha segnalato che NIS2 non aveva sistematizzato due lezioni critiche scoperte sul campo (hot-reload PHP + disciplina commit). Codifico qui il pattern così non si reimpara da zero.
|
||||
|
||||
---
|
||||
|
||||
## TL;DR — Le 2 regole d'oro
|
||||
|
||||
1. **Ogni modifica PHP richiede `kill -USR2 1` nel container.** Il bind-mount NON basta: `opcache.validate_timestamps=Off` in produzione → senza USR2 il vecchio bytecode resta in cache, gli utenti vedono ancora la versione precedente.
|
||||
2. **Committa SUBITO ogni modifica funzionante.** Le modifiche non committate sono a rischio: il cron `ticket-agent` o altri agenti possono rebasare/revertare il working tree (è successo: commit `d5d83bb` ha revertato `index.php` di una Feature non ancora committata).
|
||||
|
||||
---
|
||||
|
||||
## 1. Hot-reload PHP — il pattern operativo
|
||||
|
||||
NIS2 (e tutti i prodotti PHP della suite con PHP-FPM + opcache) gira con `opcache.validate_timestamps=Off` per performance. Conseguenza: **opcache non rilegge i file da disco**, anche se il bind-mount li ha già aggiornati. Dopo ogni edit di `.php`:
|
||||
|
||||
```bash
|
||||
docker exec <container-nis2-fpm> kill -USR2 1
|
||||
```
|
||||
|
||||
Cosa fa USR2 su FPM: **graceful reload** dei workers (zero downtime, request in volo finiscono, i nuovi workers leggono il bytecode fresco). NON serve riavviare il container, NON serve `docker compose restart`.
|
||||
|
||||
**Pattern per ogni modifica PHP:**
|
||||
|
||||
```
|
||||
1. edit file.php (sul bind-mount /var/www/nis2-agile/...)
|
||||
2. docker exec <nis2-fpm> kill -USR2 1
|
||||
3. smoke: curl https://nis2.agile.software/<endpoint> → conferma la nuova versione risponde
|
||||
4. commit + push (vedi §2)
|
||||
```
|
||||
|
||||
Se non sei sicuro del nome esatto del container FPM:
|
||||
```bash
|
||||
docker ps --format '{{.Names}}' | grep -iE 'nis2.*(fpm|app|web|php)'
|
||||
```
|
||||
|
||||
**Eccezioni** (file che NON richiedono USR2):
|
||||
- File statici (CSS, JS, immagini, HTML puro) → serviti da nginx/apache, niente cache PHP.
|
||||
- File JSON/template letti a runtime senza require/include (es. config JSON parsato con `json_decode`).
|
||||
- `version.json` (il polling client lo rilegge ad ogni richiesta).
|
||||
|
||||
In dubbio → fai USR2, costa ~10ms.
|
||||
|
||||
---
|
||||
|
||||
## 2. Disciplina commit — non lasciare modifiche scoperte
|
||||
|
||||
**Regola**: appena una modifica funziona (smoke verde dopo USR2), **commit immediato** anche se è una WIP. Niente sit-on di feature funzionanti nel working tree.
|
||||
|
||||
**Perché**: il cron `ticket-agent-cron.sh` ogni 2 minuti può:
|
||||
- Prendere un ticket OPEN, lanciare `claude -p` nel container → l'agent modifica file, committa, potenzialmente rebase/revert se trova conflitti.
|
||||
- Altri processi (sync, sso-password-sync, ecc.) possono toccare il working tree.
|
||||
|
||||
Lo conferma il caso reale di ieri: commit `d5d83bb` (agent automatico) ha revertato `index.php` di una Feature 1 NON ancora committata. Persa la modifica → rifatta da zero.
|
||||
|
||||
**Mitigazione**:
|
||||
- Commit dopo OGNI step funzionante (`git add <file> && git commit -m "[FEAT] descrizione"`).
|
||||
- Per work-in-progress di più step → branch dedicato (`git checkout -b feat/<nome>` poi merge in main quando completo).
|
||||
- **Heads-up al cron**: se stai lavorando attivamente, crea il semaforo manuale per evitare che il cron parta:
|
||||
```bash
|
||||
echo "USER=cristiano STARTED=$(date -Iseconds)" > /tmp/agent-working.lock
|
||||
# ... lavori ...
|
||||
rm /tmp/agent-working.lock
|
||||
```
|
||||
Il cron salta i container con `/tmp/agent-working.lock` attivo.
|
||||
|
||||
---
|
||||
|
||||
## 3. Git push se la credential-cache è vuota (post-reboot o container fresco)
|
||||
|
||||
Il container NIS2 oggi è **legacy** (non ancora migrato al vault credential helper come `trpg-agile`). Quindi:
|
||||
- `git push` chiede il PAT Gitea via `git credential-cache` (in-memory).
|
||||
- Dopo un reboot/restart del container → cache vuota → push bloccato.
|
||||
|
||||
**Workaround immediato senza git-login interattivo**: chiedi a VIGILE/AgileHub-side di pushare dall'host (l'host ha già l'helper vault). Pattern usato il 29/5:
|
||||
```
|
||||
"Vigile, NIS2 ha N commit su main da pushare, fallo tu dall'host"
|
||||
→ ssh host: cd /var/www/nis2-agile && git -c safe.directory=. push origin main
|
||||
→ chown -R git:git .git (ripristina ownership)
|
||||
```
|
||||
Funziona perché `/var/www/nis2-agile` (host) = `/projects/nis2-agile` (container) = stesso bind-mount → i commit fatti nel container sono visibili all'host.
|
||||
|
||||
**Fix definitivo** (richiede ricreate container NIS2): migrazione vault helper, pattern `trpg-agile`. Da fare quando arriva una finestra di manutenzione.
|
||||
|
||||
---
|
||||
|
||||
## 4. Workflow di rilascio NIS2 — versione semplificata
|
||||
|
||||
NIS2 è **L1 master-shared** (single-instance, `nis2.agile.software`), NON L2 partial-SaaS come TRPG. Quindi **il workflow è molto più semplice di TRPG**:
|
||||
|
||||
| | TRPG (L2 partial-SaaS) | NIS2 (L1 master-shared) |
|
||||
|---|---|---|
|
||||
| Frontend | bind-mount master → propaga istantaneo a N tenant | bind-mount → 1 sola istanza, istantaneo |
|
||||
| Backend | container `trpg-data` per ogni tenant + plan TSSP + agent | nessun container per-tenant, è il container master |
|
||||
| Plan in `hub_upgrade_plans` | sì (TSSP pipeline) | **no** — NIS2 non è sulla TSSP |
|
||||
| Build immagine + push registry | sì (per Cat 2) | **no** |
|
||||
| Bump `version.json` | sì | **sì** (per il polling client di auto-refresh) |
|
||||
| Commit + push Gitea | sì | **sì** |
|
||||
| Tag git `vX.Y.Z` | sì | **sì** (igienico, anche se non strettamente necessario) |
|
||||
|
||||
**Workflow operativo NIS2 per una release**:
|
||||
```
|
||||
1. Edit codice (PHP + asset)
|
||||
2. kill -USR2 1 sul container FPM (per i file .php)
|
||||
3. Smoke test: curl/browse → verifica funziona
|
||||
4. Bump app/version.json (versione + build_id + changelog)
|
||||
5. git add . && git commit -m "[FEAT|FIX|DOCS] descrizione"
|
||||
6. git tag vX.Y.Z (opzionale ma consigliato)
|
||||
7. git push origin main --tags (via host se cache token vuota)
|
||||
```
|
||||
|
||||
**NON serve**: rebuild immagine Docker, plan in `hub_upgrade_plans`, agent run, retag registry. Quelli sono pattern TRPG per gestire la propagazione a N tenant. NIS2 = 1 istanza, l'edit live è già la propagazione.
|
||||
|
||||
---
|
||||
|
||||
## 5. Riferimenti
|
||||
|
||||
- **Standard ticket cross-suite**: `nexus-ticket-ms` (porta 4213), routing rules, AI auto-resolve + AWAITING_USER_CONFIRMATION (vedi `docs/ARCHITETTURA_SISTEMA_TICKET.md`).
|
||||
- **Pattern TRPG L2 partial-SaaS** (per capire la differenza): `memory/reference_trpg_l2_partial_saas_frontend_bindmount.md`.
|
||||
- **Standard email cross-suite** (se NIS2 manda mail): `email-automation-ms` only, vedi `docs/STANDARD_EMAIL_RELAY.md`.
|
||||
- **Vault per credenziali NIS2**: `tier1__nis2-app__anthropic`, `tier1__nis2-app__voyage` (già presenti).
|
||||
- **Helper credenziali Gitea**: oggi NIS2 NON è migrato. Fix futuro = pattern `trpg-agile` in CLAUDE.md AgileServices §"GIT PUSH: Vault-Backed Credential Helper".
|
||||
|
||||
---
|
||||
|
||||
## 6. Cosa aggiungere al CLAUDE.md di NIS2
|
||||
|
||||
Quando hai una finestra, aggiungi al **vostro** CLAUDE.md (in `/var/www/nis2-agile/CLAUDE.md` o equivalente) una sezione "**Hot-reload + Release workflow**" con il riassunto delle §1, §2, §4. Così ogni nuova sessione Claude su NIS2 le ha in contesto al boot, senza doverle riscoprire.
|
||||
|
||||
---
|
||||
|
||||
**Fine documento.** Dubbi/feedback → rispondi con un `INCOMING_FROM_NIS2_...` doc nello stesso pattern, o pingami in chat tramite l'utente.
|
||||
Reference in New Issue
Block a user