Files
local-ci-cd-system/plans/A1-closeout.md
T

8.0 KiB
Raw Blame History

Fase A1 — Closeout operativo

Checklist per chiudere lo step A1 di implementation-plan-A-B prima di iniziare A2. Il codice è già committato sul branch feature/python-rewrite-phase-a (commit 9fbe952); manca solo la validazione contro l'ambiente reale.

Stato attuale

  • Codice + 35 unit test (coverage 82.65%) committati
  • ruff clean, mypy --strict clean su 12 file sorgente
  • Job python aggiunto a gitea/workflows/lint.yml
  • PoC wait-ready PASS contro VM reale Windows
  • PoC wait-ready PASS contro VM reale Linux
  • Job python di lint.yml PASS su act_runner

Perché completare A1 prima di A2

A2 riusa WorkstationVmrunBackend, WinRmTransport, SshTransport e KeyringCredentialStore esattamente come sono ora. Se uno di questi ha un bug di integrazione (TLS, encoding, parsing output vmrun list, permessi venv, ecc.), trovarlo dopo A2 costa: 1 fix nei moduli core + retest di tutti i 6 comandi portati in A2. Trovarlo ora costa: 1 fix.

1. PoC wait-ready su VM Windows reale

Obiettivo: validare il path vmrun.is_runningget_ip → WinRM HTTPS con cert self-signed end-to-end.

# 1. Setup venv (una tantum) sull'host CI
python -m venv F:\CI\python\venv
F:\CI\python\venv\Scripts\python.exe -m pip install --upgrade pip
F:\CI\python\venv\Scripts\python.exe -m pip install -e ".[dev]"

# 2. Clone manuale di una VM smoke da template
$vmrun = 'C:\Program Files (x86)\VMware\VMware Workstation\vmrun.exe'
$tpl   = 'F:\CI\Templates\WinBuild2025\WinBuild2025.vmx'
$dst   = 'F:\CI\BuildVMs\smoke-a1\smoke-a1.vmx'
& $vmrun -T ws clone $tpl $dst linked -snapshot=BaseClean -cloneName=smoke-a1
if ($LASTEXITCODE -ne 0) { throw "clone fallito" }
& $vmrun -T ws start $dst nogui
if ($LASTEXITCODE -ne 0) { throw "start fallito" }

# 3. PoC wait-ready
$env:PYTHONIOENCODING = 'utf-8'
F:\CI\python\venv\Scripts\python.exe -m ci_orchestrator wait-ready `
    --vmx $dst --guest-os windows --timeout 300

# 4. Cleanup
& $vmrun -T ws stop $dst hard
& $vmrun -T ws deleteVM $dst

Atteso:

  • Exit code 0
  • Ultima riga stdout: [wait-ready] WinRM ready.
  • Tempo totale tra start VM e WinRM ready: 60180 s

Failure mode più probabili e fix:

Sintomo Causa probabile Fix
is_running resta False per sempre Path mismatch in vmrun list (slash diversi, casing) Aggiungere normalizzazione os.path.normcase in WorkstationVmrunBackend.is_running
get_ip ritorna sempre None VMware Tools non ancora pronti Atteso nei primi 3060 s; se persiste >180 s, problema nel template
WinRM probe failed: ... certificate verify cert_validation=False non basta su TLS handshake Ispezionare cipher; eventualmente pinnare versione pypsrp o passare auth='ntlm' esplicito
KeyError: 'BuildVMGuest' Credenziale non leggibile dall'utente che lancia il PoC Eseguire come l'utente del runner (runas /user:ci-runner ...) o re-store credential nel suo profilo
KeyringCredentialStore ritorna username vuoto Backend keyring usa get_password-only Verificato in test_credentials.py::test_get_falls_back_to_password; in tal caso impostare username separatamente nel target

2. PoC wait-ready su VM Linux reale

$tpl = 'F:\CI\Templates\LinuxBuild2404\LinuxBuild2404.vmx'
$dst = 'F:\CI\BuildVMs\smoke-a1-lnx\smoke-a1-lnx.vmx'
& $vmrun -T ws clone $tpl $dst linked -snapshot=BaseClean-Linux -cloneName=smoke-a1-lnx
& $vmrun -T ws start $dst nogui

$env:CI_SSH_KEY_PATH = 'F:\CI\keys\ci_linux'
F:\CI\python\venv\Scripts\python.exe -m ci_orchestrator wait-ready `
    --vmx $dst --guest-os linux --ssh-user ci_build --timeout 300

& $vmrun -T ws stop $dst hard
& $vmrun -T ws deleteVM $dst

Atteso: ultima riga [wait-ready] SSH ready. entro 60120 s.

Failure mode più probabili:

Sintomo Causa Fix
SSH connection ... timed out DHCP collision (vedi AGENTS.md errore #11) Verificare snapshot BaseClean-Linux con machine-id resettato
paramiko.AuthenticationException Permessi chiave SSH errati (Windows ACL su ci_linux) icacls F:\CI\keys\ci_linux /inheritance:r /grant:r "<utente-runner>:R"
is_ready() False ma SSH manuale OK BatchMode=yes lato ssh.exe non equivalente in paramiko Già coperto: paramiko non chiede prompt; verificare look_for_keys=False settato

3. Job python di lint.yml su act_runner

# Push del branch
git push -u origin feature/python-rewrite-phase-a

Poi su Gitea: aprire una PR contro main (o trigger manuale del workflow). Verificare che il job python completi entro timeout-minutes: 15.

Failure mode più probabili:

Sintomo Causa Fix
python: command not found python non in PATH dell'utente del runner Installare Python 3.11+ machine-wide o aggiornare PATH del servizio
pip install -e .[dev] >15 min al primo run Cache assente, network lento Bumpare timeout-minutes: 30 solo per il primo run; cache stabile dopo
Access denied su F:\CI\python\venv Utente del runner senza scrittura su F:\CI\python icacls F:\CI\python /grant "<utente-runner>:(OI)(CI)F"
Coverage <70% Differenza Python 3.14 (locale) vs 3.11 (CI) Rilanciare con --cov-report=term-missing per identificare branch mancante

4. Definizione di "A1 done"

Spuntabile solo quando tutti e tre i punti sopra sono PASS:

  • PoC Windows: wait-ready exit 0 contro WinBuild2025 reale
  • PoC Linux: wait-ready exit 0 contro LinuxBuild2404 reale
  • CI: workflow lint.yml job python PASS su act_runner

A quel punto:

  1. Aggiornare la checklist master in implementation-plan-A-B spuntando le righe [A1].
  2. Mergeare feature/python-rewrite-phase-a su main (o lasciare il branch live se A2 verrà committato sopra).
  3. Procedere con A2 (script "foglia": Wait-VMReady, Remove-BuildVM, Cleanup-OrphanedBuildVMs, Watch-DiskSpace, Watch-RunnerHealth, Get-CIJobSummary).

5. Workaround se A1 non si può chiudere ora

Se l'hardware/VM template non sono accessibili in questo momento:

  • Non rimuovere alcuno script PS in A2.
  • Marcare A1 come "code-complete, validation pending" in implementation-plan-A-B.
  • Procedere con A2 ma trattare ogni bug scoperto su WorkstationVmrunBackend / WinRmTransport / SshTransport come fix di A1 (commit separato, no nuove feature A2 nello stesso commit).
  • Riservare una sessione dedicata di smoke testing prima di A3 (pipeline di build), perché A3 introduce clone_linked + start reali.