Skip to content

2. UI + dry run

Omisen edited this page Jul 26, 2026 · 3 revisions

L'interfaccia guidata che veste il motore, e il --dry-run funzionale. Vive in src/prompt.rs (input con inquire), src/progress.rs (progresso con indicatif), e nel flusso di src/main.rs.

È una fase di vestizione, non di logica: non tocca il rollback, non cambia gli step. Il valore sta tutto nel disaccoppiamento — se la UI è un guscio attorno a un motore che non la conosce, la puoi cambiare (o aggiungerne un'altra) senza toccare l'installazione e il rollback.


Il principio: UI disaccoppiata

Da CLAUDE.md: lo stesso installer gira interattivo o non-interattivo con un solo flusso.

  • Gli step non sanno nulla della UI: non importano inquire/indicatif, non stampano prompt. Leggono dal Context e loggano via tracing.
  • La raccolta input avviene prima del motore, in prompt.rs, e popola il Context. Il motore riceve un Context già risolto e non sa se i valori vengono da inquire, da --config o dai default.
  • Il progresso è un observer del motore ([ProgressReporter]), non parte degli step.

La prova che è fatto bene: tutti i test delle Fasi 0–10 restano verdi senza modifiche. La firma di execute non è cambiata (execute delega a execute_with_reporter con un NoopReporter), il trait Step non è stato toccato. Un vestito, non un corpo riscritto.

Un test strutturale verifica il disaccoppiamento: nessuno step importa inquire/indicatif, e il motore non usa indicatif:: (dipende solo dall'astrazione).


Parte 1 — Input con inquire

prompt.rs reimplementa la raccolta input dietro lo stesso confine della Fase 1: la logica di cascata resta in config; cambia solo il come si chiede.

Campo Widget
Versione Select (16.0/17.0/18.0/19.0)
Utente OS, DB name, porta, install-subdir Text con validazione inline (riusa i validatori di config)
Password admin Password mascherata → entra nel Secret, mai loggata
Nginx, conferma finale Confirm

Si prompta solo per i campi non passati da CLI: la priorità resta CLI > env > interattivo > default. In assenza di TTY, main bypassa i prompt e usa CLI → env → default: inquire non blocca mai senza terminale.


Parte 2 — Progresso con indicatif

Il motore notifica un'astrazione, non indicatif:

trait ProgressReporter {
    fn step_start(&self, name, index, total);
    fn step_done(&self, name);
    fn step_failed(&self, name);
    fn rollback_start(&self, total);   // il rollback è visibile: l'utente capisce che sta annullando
    fn undo_start(&self, name);
    fn undo_done(&self, name);
}
Impl Uso
IndicatifReporter TTY interattivo: spinner + barra [pos/len] con lo step corrente
LogReporter no-TTY / output su file: solo tracing
NoopReporter silenzioso (default di execute)

Il reporter è passato a execute_with_reporter, non al trait Step: gli step restano ignari.


Parte 3 — --dry-run funzionale (G2)

dry_run_plan mostra il piano completo senza mutare:

per ogni step:  snapshot (read-only)  →  run in dry-run (LOGGA l'intenzione, non muta)
                nessuna persistenza · nessun rollback
  • Ogni step, in dry-run, distingue "agirebbe" da "no-op (preexisting)" in base al proprio snapshot (es. "creerei la directory" vs "già presente, skip").
  • Uno snapshot non disponibile non interrompe il piano: viene segnalato e si prosegue.
  • In dry-run main salta i preflight che richiedono root: è una preview senza sudo, utile allo stagista per capire cosa succederà e al dev per validare un .env prima di lanciarlo davvero.

Test: in dry-run il motore non chiama alcuna operazione mutante del SystemOps e non scrive lo stato.


Note di design

  • execute invariato → compatibilità totale coi test precedenti. Aggiunto execute_with_reporter (e rollback_with_reporter); il trait Step non è cambiato.
  • Selezione automatica del reporter in main: TTY + installazione reale → indicatif; altrimenti log.
  • La password non è mai loggata: Password mascherato in input, Secret per lo storage.
  • Dopo questa fase resta solo la Fase 12: test di rollback end-to-end + hardening finale.

Clone this wiki locally