8.0 KiB
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
ruffclean,mypy --strictclean su 12 file sorgente- Job
pythonaggiunto a.gitea/workflows/lint.yml - Job
pythondilint.ymlPASS su act_runner (commit8586ff8) - PoC
wait-readyPASS contro VM reale Windows - PoC
wait-readyPASS contro VM reale Linux
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_running → get_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: 60–180 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 30–60 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 60–120 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-readyexit 0 controWinBuild2025reale - PoC Linux:
wait-readyexit 0 controLinuxBuild2404reale - CI: workflow
lint.ymljobpythonPASS su act_runner
A quel punto:
- Aggiornare la checklist master in implementation-plan-A-B
spuntando le righe
[A1]. - Mergeare
feature/python-rewrite-phase-asumain(o lasciare il branch live se A2 verrà committato sopra). - 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/SshTransportcome 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+startreali.