Files
local-ci-cd-system/plans/idea-3-implementation-plan.md
T
Simone 844742b4c0 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).
2026-07-23 14:51:55 +02:00

10 KiB
Raw Blame History

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 .ps1 non 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 di Validate-HostState
  • C6 — creds set (rimpiazza Set-CIGuestCredential) + validate guest (diag transport)
  • C7 — Lint CI: risolvere dipendenza pwsh di lint.yml (decisione §4 dell'analisi)
  • C8 — setup-host-linux.sh: pwsh non più installato di default (--with-pwsh opt-in)
  • 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.
  • 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 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%.


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, decisione pwsh

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.

  • 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: 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.
  • action.yml (C8.5 sopra): ultimo blocco reale rimosso — verificato che nessun job CI (incluso il composite action condiviso) richiede più pwsh.
  • 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.
  • 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).

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 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.