docs: record Phase C cutover; close $IsWindows shim bug (Phase C9)

- CLAUDE.md: Linux host no longer runs pwsh; PS 5.1 constraints scoped to
  Windows guests + Windows runner.
- RUNBOOK: add "Phase C — Python equivalents" table; §6-§13 benchmark records
  kept as historical provenance.
- TODO §3.7: close $IsWindows shim bug (resolved-by-replacement — bench run
  bypasses the shim).
- plans: mark C1-C8 done + docs C9; flag operational cutover/uninstall pending.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-07 20:15:10 +02:00
parent d23ce1939e
commit 962a69d287
5 changed files with 373 additions and 68 deletions
+185
View File
@@ -0,0 +1,185 @@
# Fase C — Piano di applicazione (eliminazione `pwsh` dall'host Linux)
> Piano operativo per [idea-3-powershell-removal.md](idea-3-powershell-removal.md).
> Generato il 2026-06-07. Eseguire i passi **in ordine**: ogni passo è
> autonomo, testabile e con rollback banale (i `.ps1` non vengono rimossi
> finché C9 non chiude il burn-in di validazione).
---
## Summary — checklist master
Stato passi (spunta man mano):
- [x] **C1** — Scaffolding gruppi CLI `bench` / `smoke` / `validate` / `creds` + test skeleton
- [x] **C2**`bench run`: porting burn-in concorrenza (`Test-CapacityBurnIn` + `Start-BurnInTest*`)
- [x] **C3**`bench measure`: porting timing fasi (`Measure-CIBenchmark`) + retire `_Common.psm1`/`_Transport.psm1`/`_Common.Tests.ps1`
- [x] **C4**`smoke run`: porting smoke + build E2E (`Test-Smoke`, `Test-*Build-Linux`)
- [x] **C5**`validate host`: equivalente Linux di `Validate-HostState`
- [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)
**Definition of done globale**: tutti i criteri del §7 dell'analisi
verificati; `pwsh` rimosso dall'host Linux; pytest verde ≥90%.
---
## Convenzioni trasversali (valgono per ogni passo)
- Codice nuovo solo in `src/ci_orchestrator/`. `click.echo`, no `print()`,
no `subprocess(..., shell=True)`, type hints completi, `mypy --strict`.
- Importare **solo** `backends.load_backend` + transport esistenti
(`transport/ssh.py`, `transport/winrm.py`). Mai `WorkstationVmrunBackend`.
- Ogni nuovo comando ha test in `tests/python/test_commands_<gruppo>.py`
con backend e transport mockati (no VM reali in unit test).
- Gate coverage 90% per ogni PR. `ruff` + `mypy --strict` verdi.
- Un passo = una PR. Non toccare il branch WinRM e SSH nello stesso commit
(gotcha CLAUDE.md): se un comando ha entrambi i rami, separarli o
isolare dietro `if guest_os == "linux"`.
---
## C1 — Scaffolding
**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
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
registrazione comandi (smoke test CLI).
- **Done**: `python -m ci_orchestrator bench --help` ecc. funzionano;
pytest verde.
## C2 — `bench run` (burn-in concorrenza)
**Sostituisce**: `Test-CapacityBurnIn.ps1`, `Start-BurnInTest.ps1`,
`Start-BurnInTest-Linux.ps1`.
- [ ] 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
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
(`ping`/`sleep ~30s`) come negli wrapper.
- [ ] 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
**Sostituisce**: `Measure-CIBenchmark.ps1` (+ `_Common.psm1`,
`_Transport.psm1`, `tests/_Common.Tests.ps1`).
- [ ] 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`,
`tests/_Common.Tests.ps1` (nessun altro consumatore — verificato).
- [ ] Aggiornare `lint.yml` se elencava esplicitamente quei path.
- **Done**: `bench measure` riproduce le metriche; moduli PS rimossi;
pytest verde.
## C4 — `smoke run`
**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:
exit 0, dir artifact creata, evento `job-success` nel JSONL.
- [ ] `--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.
- **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
(`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.
- **Done**: `validate host` esce 0 su host configurato.
## C6 — `creds set` + `validate guest`
**Sostituisce**: `Set-CIGuestCredential.ps1` (host Linux) e
`Test-CIGuestWinRM.ps1` (parte diagnostica host-side).
- [ ] `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 +
comando banale, riporta causa esplicita su fallimento (la sonda
`is_ready` ingoia gli errori — vedi gotcha).
- [ ] Test: scrittura/lettura credenziale (keyring mockato); diag con
transport mockato (connect ok / auth fail / connect fail).
- **Done**: credenziali settabili e transport diagnosticabile senza `pwsh`.
## C7 — Lint CI (decisione `pwsh`)
**Risolve dipendenza #5**. Applicare l'opzione scelta nel §4 dell'analisi.
- [ ] 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
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
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.
- **Done**: `setup-host-linux.sh` su host pulito non installa `pwsh`.
## C9 — Docs, cutover, burn-in, disinstallazione
Parte **docs** completata in codice (2026-06-07). Parte **operativa** (cutover
+ burn-in di validazione + disinstallazione) resta da eseguire sull'host reale.
- [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 C1C8 mergeabile, suite verde ≥90%.
- **Done (operativo, pendente)**: `pwsh` assente dall'host dopo burn-in verde.
---
## Ordine consigliato e parallelizzabilità
`C1` prima di tutto. `C2``C6` indipendenti tra loro (parallelizzabili in
PR separate, ognuna sopra C1). `C3` deve precedere la rimozione dei moduli
`.psm1`. `C7` e `C8` indipendenti dai porting. `C9` ultimo, dopo che
C2C8 sono merge-ati e il burn-in di validazione è verde.
## Rischi
- **WinRM 4× concorrenza instabile** (TODO noto): può far fallire `bench run`
su Windows con concorrenza alta — non è regressione del porting. Tarare
`--concurrency` e annotare.
- **Equivalenza output**: validare A/B (`.ps1` vs Python) finché `pwsh` è
ancora installato (prerequisito §6) prima della disinstallazione in C9.