0d6486b19b
Moves all A/B closeouts, checklists, idea docs, and implementation plans to plans/archived/2026-05-23/. Both phases are production-stable. Active plans remaining in plans/: - idea-3-powershell-removal.md (Phase C — in progress) - idea-3-esxi-support.md (Phase D — future) - ideas-overview.md (roadmap reference) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
350 lines
12 KiB
Markdown
350 lines
12 KiB
Markdown
# 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 <path-locale-repo>
|
||
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\<hash>\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 `<NomeServizio>` con quello trovato):
|
||
|
||
```powershell
|
||
Restart-Service -Name '<NomeServizio>'
|
||
```
|
||
|
||
- [x] Verificare che sia partito:
|
||
|
||
```powershell
|
||
Get-Service -Name '<NomeServizio>'
|
||
```
|
||
|
||
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\<job>`); `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`).
|
||
|
||
- [x] Confronto col baseline pre-Python — **SALTATO** (deciso): 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.
|
||
|
||
- [x] Self-review pre-merge: diff `main...feature` 108 file
|
||
(+12597/-3128), nessun secret/.venv/.env per nome. Solo 5 file
|
||
rimossi su feature = cleanup intenzionale (vecchio `gitea/`
|
||
action+lint → `.gitea/`; Pester test degli script PS rimpiazzati).
|
||
- [x] Merge `feature → main` con `--no-ff` (storia per-fase
|
||
preservata; conflitto rename/delete `build-nsInnoUnp.yml` →
|
||
`build-ns7zip.yml` risolto a favore di feature). Albero `main`
|
||
risultante == `feature` (Phase A esatto). Commit merge `2aa12bb`,
|
||
pushato a `origin/main`.
|
||
- [x] Tag release `v2.0.0-phaseA` creato (annotato su `b4ca7f3`) e
|
||
pushato a `origin`. Il push (`v*`) triggera `build-ns7zip.yml`
|
||
matrix + release = validazione finale end-to-end di `main`.
|
||
Cleanup: cancellare dalla UI Gitea la release auto-pubblicata
|
||
`v2.0.0-phaseA` (contiene binari ns7zip — quirk wiring del job
|
||
release), tenendo il **tag** come marker Phase A.
|
||
|
||
---
|
||
|
||
## 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) | [x] |
|
||
| 7 | Burn-in 4 job concorrenti × 3 round | [x] |
|
||
| 8 | Benchmark wall-clock | [x] |
|
||
| 9 | Merge in `main` + tag `v2.0.0-phaseA` | [x] |
|
||
|
||
**Fase A definitivamente chiusa** (Passi 1-9 tutti `[x]`). Pronta la
|
||
Fase B (porting su host Linux). Cleanup residuo non bloccante:
|
||
cancellare dalla UI Gitea le release di test `v0.0.0-phaseA-test` e
|
||
l'auto-pubblicata `v2.0.0-phaseA` (i **tag** restano).
|