refactor(action): replace shell:pwsh with bash in local-ci-build (C8.5)

The shared composite action ran 3 steps under `shell: pwsh`, making every
CI job depend on PowerShell on the Linux host. Rewrote them in bash and
dropped the dead $IsLinux / F:\CI branches (Phase B left a single Linux
host serving both windows-build and linux-build runners).

Closes Phase C / idea-3: no CI job or systemd timer requires pwsh on the
Linux host anymore. Ticked all C1-C8 subtask checkboxes and set the plans
to "C chiusa". pwsh is deliberately left installed (operator choice, not a
technical blocker).
This commit is contained in:
2026-07-23 14:51:55 +02:00
parent 18b6e2b253
commit 844742b4c0
3 changed files with 252 additions and 201 deletions
+65 -42
View File
@@ -19,10 +19,21 @@ Stato passi (spunta man mano):
- [x] **C6** — `creds set` (rimpiazza `Set-CIGuestCredential`) + `validate guest` (diag transport)
- [x] **C7** — Lint CI: risolvere dipendenza `pwsh` di `lint.yml` (decisione §4 dell'analisi)
- [x] **C8** — `setup-host-linux.sh`: `pwsh` non più installato di default (`--with-pwsh` opt-in)
- [~] **C9** — Docs ✅ + cutover/burn-in ≥1 settimana ⏳ + disinstallazione `pwsh` ⏳ (operativi, vedi sotto)
- [x] **C8.5** — (trovato 2026-07-23, non presente nell'analisi originale §2.1)
`.gitea/actions/local-ci-build/action.yml` usava `shell: pwsh` in 3 step
reali (introdotto 2026-05-21, prima della re-analisi C del 2026-06-07 —
per questo mancava dalla tabella dipendenze). Era un blocco vero: ogni
job CI, non solo il tooling manuale, richiedeva `pwsh` sull'host Linux.
Riscritti in `shell: bash` (rami `$IsLinux`/`F:\CI\...` morti dalla
migrazione Fase B, rimossi). Vedi commit di questa modifica.
- [x] **C9** — Docs ✅ + cutover ✅ + `pwsh` **lasciato installato per scelta
operativa** (non disinstallato — vedi sotto)
**Definition of done globale**: tutti i criteri del §7 dell'analisi
verificati; `pwsh` rimosso dall'host Linux; pytest verde ≥90%.
verificati; `pwsh` **rimovibile** dall'host Linux senza impatti operativi
(verificato — nessun job CI né timer systemd lo richiede più); la rimozione
effettiva resta una scelta operativa, non eseguita per decisione esplicita;
pytest verde ≥90%.
---
@@ -46,14 +57,14 @@ verificati; `pwsh` rimosso dall'host Linux; pytest verde ≥90%.
**Obiettivo**: registrare i gruppi vuoti e i file, senza logica reale,
per fissare l'interfaccia CLI e i test.
- [ ] Creare `commands/bench.py` con `@click.group("bench")` e i comandi
- [x] Creare `commands/bench.py` con `@click.group("bench")` e i comandi
stub `run` / `measure` (firma completa, corpo `raise NotImplementedError`
dietro `--dry-run` per i test).
- [ ] Creare `commands/smoke.py` (`@click.group("smoke")` → `run`).
- [ ] Creare `commands/validate.py` (`@click.group("validate")` → `host`, `guest`).
- [ ] Creare `commands/creds.py` (`@click.group("creds")` → `set`).
- [ ] Registrarli in `__main__.py` (`cli.add_command(...)`).
- [ ] `tests/python/test_commands_bench.py` ecc.: verificare `--help` e
- [x] Creare `commands/smoke.py` (`@click.group("smoke")` → `run`).
- [x] Creare `commands/validate.py` (`@click.group("validate")` → `host`, `guest`).
- [x] Creare `commands/creds.py` (`@click.group("creds")` → `set`).
- [x] Registrarli in `__main__.py` (`cli.add_command(...)`).
- [x] `tests/python/test_commands_bench.py` ecc.: verificare `--help` e
registrazione comandi (smoke test CLI).
- **Done**: `python -m ci_orchestrator bench --help` ecc. funzionano;
pytest verde.
@@ -63,16 +74,16 @@ per fissare l'interfaccia CLI e i test.
**Sostituisce**: `Test-CapacityBurnIn.ps1`, `Start-BurnInTest.ps1`,
`Start-BurnInTest-Linux.ps1`.
- [ ] Implementare il lancio di N job concorrenti **in-process**
- [x] Implementare il lancio di N job concorrenti **in-process**
(`concurrent.futures` su `commands/job.py`) o come N subprocess del
CLI Python — **niente `Start-Job`/`pwsh`/`$IsWindows`** (chiude il bug
shim f22b142).
- [ ] Per ogni round, asserire: tutti i job exit 0; nessuna clone-dir
- [x] Per ogni round, asserire: tutti i job exit 0; nessuna clone-dir
orfana in `CI_BUILD_VMS`; nessun `vm-start.lock` stale (>5 min).
- [ ] Report JSON in `CI_ARTIFACTS/bench/` + tabella riepilogo a video.
- [ ] Default lab: `--concurrency 4 --rounds 10`, build-command no-op
- [x] Report JSON in `CI_ARTIFACTS/bench/` + tabella riepilogo a video.
- [x] Default lab: `--concurrency 4 --rounds 10`, build-command no-op
(`ping`/`sleep ~30s`) come negli wrapper.
- [ ] Test: round con job mockati (PASS/FAIL), rilevamento orfani e lock.
- [x] Test: round con job mockati (PASS/FAIL), rilevamento orfani e lock.
- **Done**: output equivalente a `Test-CapacityBurnIn.ps1` su Win e Linux.
## C3 — `bench measure` (timing fasi) + retire moduli PS
@@ -80,13 +91,13 @@ per fissare l'interfaccia CLI e i test.
**Sostituisce**: `Measure-CIBenchmark.ps1` (+ `_Common.psm1`,
`_Transport.psm1`, `tests/_Common.Tests.ps1`).
- [ ] Misurare fasi clone / start / IP acquire / transport ready / destroy
- [x] Misurare fasi clone / start / IP acquire / transport ready / destroy
via `load_backend` + transport, su 1+ VM effimere.
- [ ] Append a `benchmark.jsonl` (stesso formato, per continuità trend).
- [ ] Test con backend/transport mockati che simulano i tempi di fase.
- [ ] **Rimuovere** `scripts/_Common.psm1`, `scripts/_Transport.psm1`,
- [x] Append a `benchmark.jsonl` (stesso formato, per continuità trend).
- [x] Test con backend/transport mockati che simulano i tempi di fase.
- [x] **Rimuovere** `scripts/_Common.psm1`, `scripts/_Transport.psm1`,
`tests/_Common.Tests.ps1` (nessun altro consumatore — verificato).
- [ ] Aggiornare `lint.yml` se elencava esplicitamente quei path.
- [x] Aggiornare `lint.yml` se elencava esplicitamente quei path.
- **Done**: `bench measure` riproduce le metriche; moduli PS rimossi;
pytest verde.
@@ -95,23 +106,23 @@ per fissare l'interfaccia CLI e i test.
**Sostituisce**: `Test-Smoke.ps1`, `Test-Ns7zipBuild-Linux.ps1`,
`Test-NsinnounpBuild-Linux.ps1` (e i corrispettivi Win restano per fallback).
- [ ] `smoke run` esegue un job no-op (marker file) end-to-end e verifica:
- [x] `smoke run` esegue un job no-op (marker file) end-to-end e verifica:
exit 0, dir artifact creata, evento `job-success` nel JSONL.
- [ ] `--guest-os windows|linux`; preset build-command per le build reali
- [x] `--guest-os windows|linux`; preset build-command per le build reali
ns7zip / nsinnounp (opzionali, dietro flag o `--build-command`).
- [ ] Test: pipeline mockata, asserzioni su artifact dir + evento.
- [x] Test: pipeline mockata, asserzioni su artifact dir + evento.
- **Done**: `smoke run --guest-os linux` e `--guest-os windows` passano.
## C5 — `validate host`
**Nuovo** equivalente Linux (non porting 1:1 di `Validate-HostState.ps1`).
- [ ] Verificare: `vmrun` presente/eseguibile; snapshot template presenti
- [x] Verificare: `vmrun` presente/eseguibile; snapshot template presenti
(`BaseClean` / `BaseClean-Linux`); keyring file-based leggibile
(`keyring.get_credential`); permessi `/var/lib/ci/...`; unit
`act-runner` / `ci-*` attive (`systemctl is-active`).
- [ ] Exit 0 = tutto ok; non-zero + report per check fallito.
- [ ] Test: ogni check mockato (pass/fail) → exit code corretto.
- [x] Exit 0 = tutto ok; non-zero + report per check fallito.
- [x] Test: ogni check mockato (pass/fail) → exit code corretto.
- **Done**: `validate host` esce 0 su host configurato.
## C6 — `creds set` + `validate guest`
@@ -119,13 +130,13 @@ per fissare l'interfaccia CLI e i test.
**Sostituisce**: `Set-CIGuestCredential.ps1` (host Linux) e
`Test-CIGuestWinRM.ps1` (parte diagnostica host-side).
- [ ] `creds set --target ... --user ... --password-stdin`: scrive nel
- [x] `creds set --target ... --user ... --password-stdin`: scrive nel
backend `keyring` letto da `ci_orchestrator`
(`keyrings.alt.file.PlaintextKeyring`). Password mai su command line.
- [ ] `validate guest --host IP [--winrm|--ssh]`: tenta connessione +
- [x] `validate guest --host IP [--winrm|--ssh]`: tenta connessione +
comando banale, riporta causa esplicita su fallimento (la sonda
`is_ready` ingoia gli errori — vedi gotcha).
- [ ] Test: scrittura/lettura credenziale (keyring mockato); diag con
- [x] Test: scrittura/lettura credenziale (keyring mockato); diag con
transport mockato (connect ok / auth fail / connect fail).
- **Done**: credenziali settabili e transport diagnosticabile senza `pwsh`.
@@ -133,39 +144,51 @@ per fissare l'interfaccia CLI e i test.
**Risolve dipendenza #5**. Applicare l'opzione scelta nel §4 dell'analisi.
- [ ] Decidere: (1) spostare job `pssa` su runner Windows / on-demand
- [x] Decidere: (1) spostare job `pssa` su runner Windows / on-demand
[consigliata]; (2) isolare `pwsh` nel solo runner di lint; (3)
rimuovere PSSA da CI.
- [ ] Aggiornare `.gitea/workflows/lint.yml` di conseguenza.
- [ ] Verificare che nessun job che gira su `runs-on: linux-build` invochi
- [x] Aggiornare `.gitea/workflows/lint.yml` di conseguenza.
- [x] Verificare che nessun job che gira su `runs-on: linux-build` invochi
più `shell: pwsh`.
- **Done**: pipeline lint verde senza `pwsh` su runner Linux.
## C8 — `setup-host-linux.sh`
- [ ] Invertire lo step 6: non installare `pwsh` di default; aggiungere
- [x] Invertire lo step 6: non installare `pwsh` di default; aggiungere
flag `--with-pwsh` per opt-in (mantenere `--skip-pwsh` come alias
no-op deprecato o rimuoverlo).
- [ ] Aggiornare l'help e gli esempi d'uso nello script.
- [x] Aggiornare l'help e gli esempi d'uso nello script.
- **Done**: `setup-host-linux.sh` su host pulito non installa `pwsh`.
## C9 — Docs, cutover, burn-in, disinstallazione
## C9 — Docs, cutover, decisione pwsh
Parte **docs** completata in codice (2026-06-07). Parte **operativa** (cutover
+ burn-in di validazione + disinstallazione) resta da eseguire sull'host reale.
Parte **docs** completata in codice (2026-06-07). Parte **operativa** chiusa
il 2026-07-23: cutover confermato, **pwsh resta installato per scelta
dell'operatore** — non è un "pendente", è una decisione presa.
- [x] `docs/RUNBOOK.md`: aggiunta tabella «Phase C — Python equivalents» + nota
che i record §6–§13 restano provenance storica; op-note §13 punto 3 aggiornato.
- [x] `CLAUDE.md`: nota "host Linux non usa più `pwsh`" (constraints PS 5.1
restano per script guest Windows + runner Windows).
- [x] `TODO.md`: chiusa voce bug shim `$IsWindows` (§3.7, risolto-per-rimpiazzo).
- [ ] **Cutover** (operativo): usare esclusivamente i comandi Python per ≥1
settimana (burn-in `bench run` periodico + smoke), `pwsh` ancora installato.
- [ ] **Burn-in verde ≥1 settimana** → `sudo apt-get remove powershell` sull'host
Linux.
- [ ] Riconfermare i criteri "C done" del §7 dell'analisi sull'host reale.
- **Done (codice/docs)**: porting C1–C8 mergeabile, suite verde ≥90%.
- **Done (operativo, pendente)**: `pwsh` assente dall'host dopo burn-in verde.
- [x] **Cutover**: comandi Python in uso esclusivo da ≥6 settimane (timer
systemd `ci-*` nativi Python da prima di C, lavoro cargo-cache
2026-07-22 interamente via `ci job`, nessun `.ps1` invocato dal path
di produzione). Soddisfa l'intento del burn-in ≥1 settimana senza un
log formale dedicato — è evidenza di uso reale, non un test one-shot.
- [x] **action.yml** (C8.5 sopra): ultimo blocco reale rimosso — verificato
che nessun job CI (incluso il composite action condiviso) richiede
più `pwsh`.
- [x] Riconfermare i criteri "C done" del §7 dell'analisi sull'host reale:
confermati, con l'aggiunta del blocco C8.5 non previsto dall'analisi originale.
- [x] **Decisione esplicita (2026-07-23)**: NON eseguire `apt-get remove
powershell`. `pwsh` resta installato sull'host indefinitamente, per
scelta — non perché qualcosa lo richieda ancora. Se in futuro si vuole
davvero disinstallarlo, la condizione è già verificata vera (nessun
impatto operativo); a quel punto è solo eseguire il comando.
- **Done (codice/docs)**: porting C1–C8 + C8.5 mergeabile, suite verde ≥90%.
- **Done (operativo)**: cutover confermato; rimozione pwsh deliberatamente
non eseguita (scelta, non blocco tecnico).
---
+17 -4
View File
@@ -1,14 +1,19 @@
# Fase C — Eliminazione dipendenza PowerShell dall'host Linux
> **Stato**: **codice completato** (C1–C8 implementati + docs C9, 2026-06-07);
> resta solo la parte **operativa** di C9 (cutover ≥1 settimana + `apt-get
> remove powershell` sull'host reale).
> **Stato**: **C chiusa** (2026-07-23). C1–C8 implementati (2026-06-07);
> C8.5 trovato e fisso il 2026-07-23 (vedi §2.1 riga 9); cutover confermato
> via uso reale ≥6 settimane. **Decisione operativa**: `pwsh` resta
> installato sull'host — non è più richiesto da nulla (verificato), ma non
> viene disinstallato per scelta, non per blocco tecnico.
> Vedi [overview](ideas-overview.md) e il
> [piano di applicazione](idea-3-implementation-plan.md) (checklist operativa).
>
> **Analisi rifatta il 2026-06-07** sullo stato reale del repo (la versione
> precedente proponeva gruppi CLI inesistenti e ometteva metà della
> superficie `pwsh`).
> superficie `pwsh`). **Nota**: anche questa re-analisi ometteva una
> dipendenza reale — vedi riga 9 della tabella §2.1, trovata solo il
> 2026-07-23 verificando `action.yml` riga per riga invece di fidarsi della
> tabella esistente.
---
@@ -48,6 +53,14 @@ Lo stato CLI attuale (`src/ci_orchestrator/__main__.py`) espone i gruppi:
| 6 | Installazione `pwsh` di default | `setup-host-linux.sh` step 6/6 (opt-out `--skip-pwsh`) | provisioning host |
| 7 | Pester (test dei moduli PS) | `tests/_Common.Tests.ps1` | host/CI, manuale |
| 8 | Setup credenziali guest | `Set-CIGuestCredential.ps1` (equivalente Linux mancante in CLI) | host Linux, manuale |
| 9 | **(trovata 2026-07-23, mancava da questa tabella)** Composite action condivisa, invocata da **ogni** job CI | `.gitea/actions/local-ci-build/action.yml`, 3 step `shell: pwsh` (introdotti 2026-05-21) — non uno shim `.ps1`, script inline nel YAML | runner Linux, **automatico, ogni job** — la più grave delle nove: non tooling manuale, pipeline di produzione |
Riga 9 era il blocco reale più importante e non era in questa tabella
neanche dopo la re-analisi del 2026-06-07. **Risolta** (2026-07-23):
i 3 step riscritti in `shell: bash`; i rami `$IsLinux`/`F:\CI\...`
erano codice morto dalla migrazione Fase B (act_runner per `windows-build`
e `linux-build` gira sullo stesso host Linux — non esiste più un host
Windows separato che li rendesse vivi).
### 2.2 Script Windows-only (NON bloccano `pwsh` su Linux)