- 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>
9.0 KiB
Fase C — Piano di applicazione (eliminazione pwsh dall'host Linux)
Piano operativo per idea-3-powershell-removal.md. Generato il 2026-06-07. Eseguire i passi in ordine: ogni passo è autonomo, testabile e con rollback banale (i
.ps1non vengono rimossi finché C9 non chiude il burn-in di validazione).
Summary — checklist master
Stato passi (spunta man mano):
- C1 — Scaffolding gruppi CLI
bench/smoke/validate/creds+ test skeleton - C2 —
bench run: porting burn-in concorrenza (Test-CapacityBurnIn+Start-BurnInTest*) - C3 —
bench measure: porting timing fasi (Measure-CIBenchmark) + retire_Common.psm1/_Transport.psm1/_Common.Tests.ps1 - C4 —
smoke run: porting smoke + build E2E (Test-Smoke,Test-*Build-Linux) - C5 —
validate host: equivalente Linux diValidate-HostState - C6 —
creds set(rimpiazzaSet-CIGuestCredential) +validate guest(diag transport) - C7 — Lint CI: risolvere dipendenza
pwshdilint.yml(decisione §4 dell'analisi) - C8 —
setup-host-linux.sh:pwshnon più installato di default (--with-pwshopt-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, noprint(), nosubprocess(..., shell=True), type hints completi,mypy --strict. - Importare solo
backends.load_backend+ transport esistenti (transport/ssh.py,transport/winrm.py). MaiWorkstationVmrunBackend. - Ogni nuovo comando ha test in
tests/python/test_commands_<gruppo>.pycon backend e transport mockati (no VM reali in unit test). - Gate coverage 90% per ogni PR.
ruff+mypy --strictverdi. - 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.pycon@click.group("bench")e i comandi stubrun/measure(firma completa, corporaise NotImplementedErrordietro--dry-runper 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.pyecc.: verificare--helpe registrazione comandi (smoke test CLI).- Done:
python -m ci_orchestrator bench --helpecc. 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.futuressucommands/job.py) o come N subprocess del CLI Python — nienteStart-Job/pwsh/$IsWindows(chiude il bug shimf22b142). - Per ogni round, asserire: tutti i job exit 0; nessuna clone-dir
orfana in
CI_BUILD_VMS; nessunvm-start.lockstale (>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.ps1su 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.ymlse elencava esplicitamente quei path. - Done:
bench measureriproduce 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 runesegue un job no-op (marker file) end-to-end e verifica: exit 0, dir artifact creata, eventojob-successnel 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 linuxe--guest-os windowspassano.
C5 — validate host
Nuovo equivalente Linux (non porting 1:1 di Validate-HostState.ps1).
- Verificare:
vmrunpresente/eseguibile; snapshot template presenti (BaseClean/BaseClean-Linux); keyring file-based leggibile (keyring.get_credential); permessi/var/lib/ci/...; unitact-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 hostesce 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 backendkeyringletto daci_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 sondais_readyingoia 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
pssasu runner Windows / on-demand [consigliata]; (2) isolarepwshnel solo runner di lint; (3) rimuovere PSSA da CI. - Aggiornare
.gitea/workflows/lint.ymldi conseguenza. - Verificare che nessun job che gira su
runs-on: linux-buildinvochi piùshell: pwsh. - Done: pipeline lint verde senza
pwshsu runner Linux.
C8 — setup-host-linux.sh
- Invertire lo step 6: non installare
pwshdi default; aggiungere flag--with-pwshper opt-in (mantenere--skip-pwshcome alias no-op deprecato o rimuoverlo). - Aggiornare l'help e gli esempi d'uso nello script.
- Done:
setup-host-linux.shsu host pulito non installapwsh.
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.
docs/RUNBOOK.md: aggiunta tabella «Phase C — Python equivalents» + nota che i record §6–§13 restano provenance storica; op-note §13 punto 3 aggiornato.CLAUDE.md: nota "host Linux non usa piùpwsh" (constraints PS 5.1 restano per script guest Windows + runner Windows).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 runperiodico + smoke),pwshancora installato. - Burn-in verde ≥1 settimana →
sudo apt-get remove powershellsull'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):
pwshassente 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
C2–C8 sono merge-ati e il burn-in di validazione è verde.
Rischi
- WinRM 4× concorrenza instabile (TODO noto): può far fallire
bench runsu Windows con concorrenza alta — non è regressione del porting. Tarare--concurrencye annotare. - Equivalenza output: validare A/B (
.ps1vs Python) finchépwshè ancora installato (prerequisito §6) prima della disinstallazione in C9.