# Fase A — Checklist finale per l'utente La Fase A è **code-complete e pushata** sul branch `feature/python-rewrite-and-linux-migration`. Restano solo le validazioni che richiedono accesso fisico all'host CI con VMware Workstation, snapshot template attivi e act_runner registrato. Questo documento elenca i passi da eseguire in ordine, con checklist e comandi copiabili. Stop a primo errore: ogni passo è un gate per il successivo. > **Tempo stimato totale**: 1–2 ore (escluse build lunghe nel passo 5). --- ## Passo 1 — Aggiornare il venv di produzione sull'host CI Il codice nuovo va installato nel venv che act_runner usa (`F:\CI\python\venv\`). - [x] Aprire PowerShell **come amministratore** sull'host CI. - [x] Posizionarsi nella copia git aggiornata del repo (pull del branch `feature/python-rewrite-and-linux-migration`): ```powershell cd git fetch origin git checkout feature/python-rewrite-and-linux-migration git pull ``` - [x] Installare il package nel venv di produzione (**non editable**): ```powershell & 'F:\CI\python\venv\Scripts\python.exe' -m pip install . ``` > ⚠️ **Non usare `pip install -e .` su questo host.** act_runner gira > come `LocalSystem`. Un install editable scrive un `.pth` verso la > sorgente; se il `cd` era in una dir di lavoro di act_runner > (`F:\CI\RunnerWork\\hostexecutor`, transitoria) o sul drive > utente `N:` (non risolto da LocalSystem), il runner fallisce con > `No module named ci_orchestrator`. L'install regolare copia il > package in `site-packages` su `F:` (accessibile a LocalSystem). > Conseguenza: ogni modifica al codice richiede di ri-eseguire > `pip install .` — è uno step di deploy. Assicurarsi che il `cd` del > passo precedente punti alla copia git reale del repo, non a una dir > sotto `F:\CI\RunnerWork`. - [x] Smoke check rapido che la CLI risponda: ```powershell & 'F:\CI\python\venv\Scripts\python.exe' -m ci_orchestrator --help ``` Atteso: lista degli 11 sub-comandi (`wait-ready`, `vm`, `build`, `artifacts`, `monitor`, `report`, `job`). --- ## Passo 2 — Riavviare act_runner L'act_runner gira come servizio SYSTEM e legge `runner/config.yaml` all'avvio. La modifica di A4 (`PYTHONIOENCODING=utf-8`) ha effetto solo dopo restart. - [x] Trovare il servizio: ```powershell Get-Service | Where-Object { $_.Name -like '*act*runner*' } ``` - [x] Restart (sostituisci `` con quello trovato): ```powershell Restart-Service -Name '' ``` - [x] Verificare che sia partito: ```powershell Get-Service -Name '' ``` Atteso: `Status = Running`. --- ## Passo 3 — Smoke `wait-ready` su VM Windows reale PoC pendente da A1. - [x] Clonare manualmente un template Windows: ```powershell & 'C:\Program Files (x86)\VMware\VMware Workstation\vmrun.exe' ` -T ws clone ` 'F:\CI\Templates\WinBuild2025\WinBuild2025.vmx' ` 'F:\CI\BuildVMs\smoke-win\smoke-win.vmx' ` linked -snapshot=BaseClean -cloneName=smoke-win ``` - [x] Avviare la VM: ```powershell & 'C:\Program Files (x86)\VMware\VMware Workstation\vmrun.exe' ` -T ws start 'F:\CI\BuildVMs\smoke-win\smoke-win.vmx' nogui ``` - [x] Eseguire `wait-ready`: ```powershell & 'F:\CI\python\venv\Scripts\python.exe' -m ci_orchestrator wait-ready ` --vmx 'F:\CI\BuildVMs\smoke-win\smoke-win.vmx' ` --guest-os windows --timeout 180 ``` Atteso: exit code `0` entro 3 minuti. - [x] Cleanup VM di smoke: ```powershell & 'F:\CI\python\venv\Scripts\python.exe' -m ci_orchestrator vm remove ` --vmx 'F:\CI\BuildVMs\smoke-win\smoke-win.vmx' --force ``` --- ## Passo 4 — Smoke `wait-ready` su VM Linux reale Stesso schema, template Linux. PoC pendente da A1. - [x] Clonare: ```powershell & 'C:\Program Files (x86)\VMware\VMware Workstation\vmrun.exe' ` -T ws clone ` 'F:\CI\Templates\LinuxBuild2404\LinuxBuild2404.vmx' ` 'F:\CI\BuildVMs\smoke-linux\smoke-linux.vmx' ` linked -snapshot=BaseClean-Linux -cloneName=smoke-linux ``` - [x] Start + wait-ready: ```powershell & 'C:\Program Files (x86)\VMware\VMware Workstation\vmrun.exe' ` -T ws start 'F:\CI\BuildVMs\smoke-linux\smoke-linux.vmx' nogui & 'F:\CI\python\venv\Scripts\python.exe' -m ci_orchestrator wait-ready ` --vmx 'F:\CI\BuildVMs\smoke-linux\smoke-linux.vmx' ` --guest-os linux --timeout 180 ``` Atteso: exit code `0`. > **Prerequisito scoperto**: `F:\CI\config.toml` deve esistere con `ssh_key_path` > impostato — altrimenti SSH fallisce con `No authentication methods available`. > Creato durante questa validazione; vedi HOST-SETUP.md step 6. - [x] Cleanup: ```powershell & 'F:\CI\python\venv\Scripts\python.exe' -m ci_orchestrator vm remove ` --vmx 'F:\CI\BuildVMs\smoke-linux\smoke-linux.vmx' --force ``` --- ## Passo 5 — Smoke end-to-end pipeline (`job`) Valida A3+A4 insieme: clone → wait → build → collect → cleanup. - [x] Lanciare un job sul template Windows con uno script trivial: ```powershell & 'F:\CI\python\venv\Scripts\python.exe' -m ci_orchestrator job ` --template-path 'F:\CI\Templates\WinBuild2025\WinBuild2025.vmx' ` --snapshot-name BaseClean ` --job-id smoke-job-win ` --repo-url 'http://10.10.20.11:3100/Simone/your-repo.git' ` --branch main ` --build-command 'echo hello > artifact.txt' ` --guest-artifact-source 'artifact.txt' ` --artifact-base-dir 'F:\CI\Artifacts\smoke-job-win' ``` Atteso: exit code `0`, file `F:\CI\Artifacts\smoke-job-win\artifact.txt` presente, VM smoke-job-win **non** più esistente in `F:\CI\BuildVMs\` (cleanup garantito). - [x] Ripetere su Linux: ```powershell & 'F:\CI\python\venv\Scripts\python.exe' -m ci_orchestrator job ` --template-path 'F:\CI\Templates\LinuxBuild2404\LinuxBuild2404.vmx' ` --snapshot-name BaseClean-Linux ` --guest-os linux ` --job-id smoke-job-linux ` --repo-url 'http://10.10.20.11:3100/Simone/your-repo.git' ` --branch main ` --build-command 'echo hello > artifact.txt' ` --guest-artifact-source 'artifact.txt' ` --artifact-base-dir 'F:\CI\Artifacts\smoke-job-linux' ``` Atteso: exit code `0`, `F:\CI\Artifacts\smoke-job-linux\smoke-job-linux\artifact.txt` presente. - [x] Verificare assenza VM orfane: ```powershell & 'F:\CI\python\venv\Scripts\python.exe' -m ci_orchestrator vm cleanup --what-if ``` Atteso: nessun candidato. --- ## Passo 6 — Workflow Gitea end-to-end Validazione di A4 lato runner reale. - [x] Aprire la UI Gitea, repo `local-ci-cd-system`, branch `feature/python-rewrite-and-linux-migration`. - [x] Triggerare manualmente i 3 workflow (Actions → Run workflow): - [x] `lint.yml` → atteso PASS - [x] `self-test.yml` → PASS — validati **entrambi i transport** (in-guest clone default + host-side clone+zip) su Win e Linux: | Job | Transport | Esito | | ---------------------------- | ----------------------- | ----------- | | smoke-windows | in-guest git clone | SUCCESS 26s | | smoke-linux | in-guest git clone | SUCCESS 51s | | smoke-windows-hostclone | host-side clone + zip | SUCCESS 28s | | smoke-linux-hostclone | host-side clone + zip | SUCCESS 46s | Note: artifact github-free (no upload-artifact; file raw su `F:\CI\Artifacts\`); `use-git-clone`/`submodules` default ON. - [x] `build-ns7zip.yml` matrix Win+Linux → PASS (target repo `Simone/nsis-plugin-ns7zip`, in-guest clone, `--dist`): | Job | Esito | | ------------------ | --------------------------------------- | | build (windows) | SUCCESS — DLL in dist/, artifact host | | build (linux) | SUCCESS — 8 vCPU/8 GB, wall ~121s | | release (tag push) | SUCCESS — release Gitea + 2 asset upload | Note: `release` validato con tag throwaway `v0.0.0-phaseA-test` (poi rimosso); usa il token Actions automatico (Default Token Permissions = Permissive) + REST API Gitea, legge gli artifact host-side (no download-artifact). Linux perf: vCPU-starvation a 4 vCPU risolta con guest-cpu=8 (≈ Windows VM ~120s); gap col Windows nativo MSVC (~30s) è inerente MinGW, fuori scope CI. > Tutti i workflow PASS — nessun fallimento da triagare. (Procedura > storica: in caso di fallimento, scaricare i log del run e aprire una > voce in `TODO.md` con sha + output errore.) --- ## Passo 7 — Burn-in capacità (4 job concorrenti) Validazione finale di A5 (definizione di "fatto Fase A"). - [x] Burn-in via `scripts/Start-BurnInTest.ps1` (wrapper lab che hardcoda repo `burnin-dummy` + `BuildCommand` = `build.ps1`; `Test-CapacityBurnIn.ps1` diretto senza `-BuildCommand` usa il default dotnet → fallisce su repo non-.NET): ```powershell .\scripts\Start-BurnInTest.ps1 ``` - [x] Esito (4 job concorrenti × 3 round): | Round | Pass | Fail | Elapsed | Status | | ----- | ---- | ---- | ------- | ------ | | 1 | 4 | 0 | 76s | PASS | | 2 | 4 | 0 | 88s | PASS | | 3 | 4 | 0 | 73s | PASS | Total 12/12 PASS — **OVERALL: PASS**. Cleanup VM + lock OK ogni round (0 orfani). A5 / Passo 7 validato. --- ## Passo 8 — Benchmark wall-clock Confronto Python vs PowerShell. Pendenza A4. - [x] Eseguito `.\scripts\Measure-CIBenchmark.ps1` (4 iter): | Iter | Clone | Start | IP | WinRM | Destroy | Boot tot | | ---- | ----- | ----- | ----- | ----- | ------- | -------- | | 1 | 0.63 | 1.75 | 66.57 | 0.01 | 4.81 | 68.96 | | 2 | 0.63 | 1.89 | 20.21 | 0.01 | 6.39 | 22.74 | | 3 | 0.62 | 1.72 | 85.07 | 0.01 | 4.50 | 87.42 | | 4 | 0.61 | 1.72 | 60.97 | 0.01 | 4.20 | 63.31 | Nessun errore, destroy OK (~4-6s), 0 orfani. Clone/start/WinRM trascurabili; **fase IP (20-85s) = costo dominante e variabile** (detect IP guest via VMware Tools / ci-report-ip) — noto, non bloccante. Prerequisito scoperto: lo shim `Remove-BuildVM.ps1` inoltrava `-ErrorAction` come `--error-action` (destroy falliva -> orfana); risolto per tutti gli shim blind-loop (commit `fix(shims): skip PowerShell common params`). - [ ] (Opzionale) Confronto col baseline pre-Python: nessun baseline PS affidabile registrato; metriche infra appese a `F:\CI\Logs\benchmark.jsonl` per trend futuri. Non bloccante. --- ## Passo 9 — Merge della Fase A in `main` Solo dopo che i passi 3–7 sono tutti `[x]` PASS. - [ ] Aprire PR su Gitea: `feature/python-rewrite-and-linux-migration` → `main`. - [ ] Verificare diff atteso: ~20 file Python nuovi sotto `src/ci_orchestrator/`, ~10 shim PS in `scripts/`, doc in `plans/A*-closeout.md`, AGENTS.md/ARCHITECTURE.md/README.md aggiornati. - [ ] Self-review della PR: nessun secret, nessun path hardcodato fuori da `config.py`, nessun `.venv/` committato. - [ ] Merge (squash sconsigliato — preserva la storia per-fase). - [ ] Tag release: `git tag v2.0.0-phaseA` (o convenzione preferita). --- ## Tracciamento globale | Passo | Descrizione | Stato | | ----- | ----------------------------------------- | ----- | | 1 | Aggiorna venv di produzione | [x] | | 2 | Restart act_runner | [x] | | 3 | Smoke `wait-ready` Windows | [x] | | 4 | Smoke `wait-ready` Linux | [x] | | 5 | Smoke `job` end-to-end (Win + Linux) | [x] | | 6 | Workflow Gitea (lint + self-test + build) | [ ] | | 7 | Burn-in 4 job × 10 round | [ ] | | 8 | Benchmark wall-clock | [ ] | | 9 | Merge PR e tag release | [ ] | Quando tutti i passi sono `[x]`, la Fase A è **definitivamente chiusa** e si può aprire la Fase B (porting su host Linux).