diff --git a/FIX-TODO.md b/FIX-TODO.md deleted file mode 100644 index 87ca992..0000000 --- a/FIX-TODO.md +++ /dev/null @@ -1,61 +0,0 @@ -# FIX-TODO — Local CI/CD System - - - - -Lista di fix prioritizzati emersi dalla review. Tutti i P0/P1/P2 sono stati applicati. - ---- - -## P0 — Bug funzionali ✅ - -- [x] **Shallow clone vs checkout commit specifico** — `scripts/Invoke-CIJob.ps1` - Fix: `--depth 1` saltato quando `$Commit` è valorizzato; clone completo + checkout. - -- [x] **Falso negativo size artifact** — `scripts/Get-BuildArtifacts.ps1` - Fix: validazione su `.Length -eq 0` (raw byte), non su KB arrotondati. - -- [x] **`actions/upload-artifact@v3` deprecato** — `gitea/workflows/build-nsis.yml` - Fix: aggiornato a `@v4`. - -## P0 — Sicurezza ✅ - -- [x] **Password CI hardcoded committata** — rimossa da tutti i file: - `Setup-Host.ps1`, `template/Prepare-TemplateSetup.ps1`, - `template/Setup-TemplateVM.ps1`, `README.md`, `TODO.md`. - Ora: prompt `Read-Host -AsSecureString` se non passata a runtime. - -- [x] **Password in argv (`net user`)** — `template/Setup-TemplateVM.ps1` - Fix: `New-LocalUser` con `ConvertTo-SecureString` locale (nessun argomento esposto). - -- [x] **`WSMan AllowUnencrypted` modificato senza restore** — `template/Prepare-TemplateSetup.ps1` - Fix: salva stato precedente, ripristina in `finally`. - -## P1 — Doc obsolete ✅ - -- [x] `Setup-TemplateVM.ps1`: blocco NETWORK REQUIREMENT e istruzioni finali aggiornati (VMnet8 NAT permanente, no VMnet11). -- [x] `Setup-TemplateVM.ps1:205`: commento firewall aggiornato (VMnet8 NAT, non VMnet11). -- [x] `scripts/Invoke-CIJob.ps1:193`: commento Phase 1 aggiornato (NAT, motivo zip = no PAT in VM). -- [x] `docs/BEST-PRACTICES.md` Step 8: riscritto come "Network Topology Verification" (NAT OK, non host-only). -- [x] `docs/ARCHITECTURE.md:119`: rimosso "Git" dalla toolchain (non installato di default). -- [x] `docs/ARCHITECTURE.md:194`: riformulato (NAT per pip/nuget, zip per no-PAT in VM). - -## P1 — Bug minori ✅ - -- [x] `scripts/Invoke-RemoteBuild.ps1`: primo `New-Item` sprecato rimosso. -- [x] `scripts/Wait-VMReady.ps1`: `$elapsed` dead code rimosso; try/catch su native command semplificato. -- [x] `template/Setup-TemplateVM.ps1`: `MaxMemoryPerShellMB` settato una volta sola (rimosso `winrm set` duplicato). -- [x] `runner/Install-Runner.ps1`: nota deprecazione aggiunta — usare `Setup-Host.ps1`. - -## P2 — Operativo ✅ - -- [x] `scripts/Cleanup-OrphanedBuildVMs.ps1` creato — con `-WhatIf`, soglia `-MaxAgeHours`, hard stop + deleteVM + rimozione dir. -- [x] `scripts/Get-BuildArtifacts.ps1 -IncludeLogs`: aggiunto `-Recurse` per catturare log in subdir. -- [x] `gitea/workflows/lint.yml` creato — PSScriptAnalyzer su push/PR che toccano file `.ps1`. - -## Rimasto aperto (fuori scope di questo fix) - -- [ ] `-UseGitClone` in-VM: PAT injection, git in template, e2e-010. Vedi `TODO.md` sezione "In-VM Git Clone". -- [ ] Verifica SHA256 installer (Python, VS BuildTools, dotnet-install.ps1) — richiede parametri hash per versione. -- [ ] Validazione IP ottetti 0-255 in `Invoke-CIJob.ps1` (ValidatePattern attuale accetta 999.x.x.x). -- [ ] Scheduled task per `Cleanup-OrphanedBuildVMs.ps1` — da creare manualmente o via `Setup-Host.ps1`. diff --git a/TODO.md b/TODO.md index f7ef95b..c38c5d9 100644 --- a/TODO.md +++ b/TODO.md @@ -1,133 +1,53 @@ # TODO — Local CI/CD System - + -## Setup & Infrastructure +## Completato (storico) -- [x] **Gitea Server** — già in esecuzione su `http://10.10.20.11:3100` (e `https://gitea.emulab.it`) - - [x] Runner registration token ottenuto e usato - - [x] Create at least one test repository with `.gitea/workflows/build.yml` - (`Simone/nsis-plugin-nsinnounp` — testato e2e, workflow in `gitea/workflows/build-nsis.yml`) - - [x] Gitea Actions abilitato (runner registrato con successo) +- Sistema operativo: Gitea Actions + act_runner + ephemeral VMware VMs su VMnet8 NAT +- Template VM (Windows Server 2025), snapshot `BaseClean`, credenziali in Credential Manager +- e2e-009 SUCCESS — `nsis-plugin-nsinnounp` build OK, artifact 1632 KB, VM cleanup automatico +- Fix v1.0: shallow clone + unshallow fallback, artifact size check (raw bytes), hardcoded password + rimossa da tutti i file, WSMan AllowUnencrypted restore in `finally`, `upload-artifact@v3` → `@v4` +- `scripts/Cleanup-OrphanedBuildVMs.ps1` creato (WhatIf, MaxAgeHours, hard stop + deleteVM + dir removal) +- `gitea/workflows/lint.yml` creato — PSScriptAnalyzer su push/PR che toccano `.ps1` +- `vmrun deleteVM` fix: poll `vmrun list` fino a lock rilasciato + retry 3× con backoff 0/3/6s -- [x] **act_runner** — installato e registrato sull'host Windows - - [x] Binario `gitea-runner v1.0.2` scaricato in `F:\CI\act_runner\act_runner.exe` - - [x] Registrato con Gitea (`http://10.10.20.11:3100`) — runner ID 1, nome `local-windows-runner` - - [x] `config.yaml` copiato in `F:\CI\act_runner\config.yaml` con label `windows-build:host` - - [x] Installato come servizio Windows via NSSM — stato: **Running**, StartType: Automatic - - [x] Verificare che il runner appaia "Online" nell'UI Gitea Admin → Actions → Runners - - [x] Confermare riavvio automatico dopo reboot host +--- -- [x] **Directory CI** create su `F:\CI\` - - [x] `F:\CI\BuildVMs\` - - [x] `F:\CI\Artifacts\` - - [x] `F:\CI\act_runner\` - - [x] `F:\CI\Cache\NuGet\` - - [x] `F:\CI\RunnerWork\` - - [x] `F:\CI\Templates\WinBuild\` - - [x] `F:\CI\ISO\` — contiene `26100.1742.240906-0331.ge_release_svc_refresh_SERVER_VOL_x64FRE_en-us.iso` (Windows Server 2025) +## Open — Bug / Operativo -- [x] **CredentialManager** PowerShell module v2.0 installato (Scope: CurrentUser) +- [ ] **Validazione IP ottetti** — `scripts/Invoke-CIJob.ps1` + `ValidatePattern` attuale accetta `999.x.x.x`. Sostituire con validazione per-ottetto 0-255. -- [x] **Rete VM**: VMnet8 (NAT) — internet access per pip/nuget/npm durante i build +- [ ] **Verifica SHA256 installer** — `template/Setup-TemplateVM.ps1` + Python, VS BuildTools, dotnet-install.ps1 scaricati senza verifica hash. Aggiungere + `-ExpectedHash` o hash hardcoded per le versioni pinnate. -## Template VM +- [ ] **Scheduled task Cleanup-OrphanedBuildVMs.ps1** + Creare via Task Scheduler o estendere `Setup-Host.ps1`. Suggerito: ogni 6 ore, `-MaxAgeHours 4`. -- [x] **Provision template VM** in VMware Workstation — segui questi passi nell'ordine esatto: +- [ ] **Adattare workflow per altri repository** + Generalizzare `BUILD_COMMAND` e `ARTIFACT_SOURCE` in `gitea/workflows/build-nsis.yml` + come template riutilizzabile per repo arbitrari. - ### Fase A — Crea e installa la VM (NIC: NAT per internet) - - [x] Crea nuova VM in VMware Workstation con queste impostazioni: - - 4 vCPU, 6144 MB RAM, disco 80 GB thin - - VMX path: `F:\CI\Templates\WinBuild\WinBuild.vmx` - - **NIC: VMnet8 (NAT)** ← internet necessario per Windows Update e installer - - CD-ROM: `F:\CI\ISO\26100.1742.240906-0331.ge_release_svc_refresh_SERVER_VOL_x64FRE_en-us.iso` - - [x] Installa Windows Server 2025 dall'ISO - - [x] All'interno della VM (come Administrator), abilita WinRM: - ```cmd - winrm quickconfig -q - ``` - ```powershell - Enable-PSRemoting -Force -SkipNetworkProfileCheck - Set-Item WSMan:\localhost\Service\Auth\Basic $true -Force - Set-Item WSMan:\localhost\Service\AllowUnencrypted $true -Force - Set-Item WSMan:\localhost\Client\TrustedHosts -Value '*' -Force - ``` - - [x] **Attiva Windows Server 2025** (prima dello snapshot — i linked clone ereditano l'attivazione): - ```cmd - slmgr /dli - ``` - Se non attivato, scegli il metodo appropriato: - - **KMS** (server KMS in rete): `slmgr /skms ` poi `slmgr /ato` - - **MAK/Retail key**: `slmgr /ipk XXXXX-XXXXX-XXXXX-XXXXX-XXXXX` poi `slmgr /ato` - - **KMS pubblico** (alternativa lab): vedi https://github.com/robin113x/Windows-Server-Activation/ - Verifica: `slmgr /xpr` — deve mostrare attivazione permanente o scadenza lontana - - [x] Nota l'IP assegnato dal DHCP di VMnet8 (es. `192.168.79.x`) — `ipconfig` nella VM +--- - ### Fase B — Provisioning automatico dall'host - - [x] Dall'host, esegui: - ```powershell - cd n:\Code\Workspace\Local-CI-CD-System\template - .\Prepare-TemplateSetup.ps1 -VMIPAddress 192.168.79.128 -SkipWindowsUpdate - ``` - Installa: WinRM config, utente `ci_build`, .NET SDK 10.0, VS Build Tools 2026, Python 3.13.3. - - [x] Setup completato con successo (VS Build Tools 2026 exit code 0). - - ### Fase C — Spegni e prendi lo snapshot - - [x] VM rimane su **VMnet8 (NAT)** — internet access permanente per build che richiedono pip/nuget/npm - - [x] Spegni la VM: Start → Shut down - - [x] Prendi snapshot: VM → Snapshot → Take Snapshot - **Nome esatto: `BaseClean`** - - [x] Lascia la VM spenta — non modificarla mai più dopo questo snapshot - - ### Fase D — Credenziali e config - - [x] Archivia credenziali guest sull'host (PowerShell elevato con CredentialManager): - ```powershell - New-StoredCredential -Target "BuildVMGuest" -UserName "ci_build" ` - -Password "" -Persist LocalMachine - ``` - - [x] Verifica `GITEA_CI_TEMPLATE_PATH` in `F:\CI\act_runner\config.yaml` — aggiornato a `CI-WinBuild.vmx` (2026-05-08) - -## Scripts Verification - -- [x] Test `New-BuildVM.ps1` standalone — clone `Clone_test-002` creato correttamente (2026-05-08) -- [x] Test `Wait-VMReady.ps1` standalone — exit 0 in ~5s, VM pronta (2026-05-08) -- [x] Test `Invoke-RemoteBuild.ps1` — dotnet restore + build OK, artifacts.zip creato in VM (2026-05-08) -- [x] Test `Get-BuildArtifacts.ps1` — artifacts.zip (78 KB) copiato in F:\CI\Artifacts\test-003\ (2026-05-08) -- [x] Test `Remove-BuildVM.ps1` — VM spenta + directory rimossa correttamente (2026-05-08) -- [x] Test `Invoke-CIJob.ps1` end-to-end su una soluzione reale (nsis-plugin-nsinnounp) - - [x] e2e-008: SUCCESS — build OK + artifact raccolto (1632 KB) - - [x] e2e-009: SUCCESS — cleanup automatico VM + clone confermato (finally block) - -## Runner Configuration - -- [x] `runner/config.yaml` aggiornato con percorsi `F:\CI\`, rete VMnet8 (NAT), label corretti -- [x] `capacity: 4` configurato (64 GB RAM / ~8 GB per VM) -- [x] Aggiornare `GITEA_CI_TEMPLATE_PATH` in `config.yaml` dopo creazione template VM -- [x] Archiviare credenziali guest in Windows Credential Manager (target: `BuildVMGuest`) - -## Gitea Workflow Integration - -- [x] Copiare `gitea/workflow-example.yml` in `.gitea/workflows/build.yml` nel repo di test - (workflow `build-nsis.yml` già presente e funzionante per `nsis-plugin-nsinnounp`) -- [x] Push commit e verificare job in Gitea Actions UI -- [x] Verificare artifact scaricabile da Gitea dopo build riuscita -- [ ] Adattare workflow per altri repository (generalizzare `BUILD_COMMAND` e `ARTIFACT_SOURCE`) - -## Performance & Maintenance +## Open — Performance & Maintenance - [ ] Benchmark: tempo creazione clone + tempo WinRM readiness -- [ ] Configurare NuGet package cache su shared folder host (vedi OPTIMIZATION.md) - - [ ] Pianificare refresh semestrale snapshot template VM (KMS lease = 180 giorni): - Boot template su VMnet8 (NAT) → `slmgr /ato` → nuovo snapshot BaseClean -- [ ] Monitoraggio Windows Event Log per fallimenti servizio act_runner -- [ ] Configurare retention artifact (pulizia `F:\CI\Artifacts` più vecchi di N giorni) +- [ ] Configurare NuGet package cache su shared folder host (vedi `docs/OPTIMIZATION.md`) +- [ ] Refresh semestrale snapshot template VM (KMS lease = 180 giorni): + Boot template su VMnet8 (NAT) → `slmgr /ato` → nuovo snapshot `BaseClean` +- [ ] Monitoraggio Windows Event Log per fallimenti servizio `act_runner` +- [ ] Retention artifact — pulizia automatica `F:\CI\Artifacts` più vecchi di N giorni -## In-VM Git Clone (Ottimizzazione) +--- -Sfruttare l'accesso internet della VM (VMnet8 NAT) per fare il `git clone` direttamente -nella VM, eliminando il ciclo host-clone → zip → WinRM-transfer → unzip. +## In-VM Git Clone -### Strategia +Sfruttare internet della VM (VMnet8 NAT) per `git clone` direttamente nella VM, +eliminando il ciclo host-clone → zip → WinRM-transfer → unzip. **Flusso attuale:** ``` @@ -139,95 +59,55 @@ VM avviata → WinRM: git clone --recurse-submodules https://@gitea/... ``` **Punti chiave:** -- Il PAT **non deve essere nello snapshot** — viene iniettato a runtime come env var via WinRM - (`git clone https://Simone:@gitea.emulab.it/.git`) e non viene mai persistito -- Git deve essere installato nel template (`Setup-TemplateVM.ps1`) — ora è assente per design -- L'implementazione deve essere **non-breaking**: nuovo switch opt-in `-UseGitClone` in `Invoke-CIJob.ps1` -- Si perde il parallelismo parziale (clone host avviene mentre VM boota), ma si elimina - tutto l'overhead di zip/transfer (rilevante su repo grandi o con molti submoduli) -- Submoduli funzionano nativamente con `--recurse-submodules` (nessun workaround) +- PAT iniettato a runtime come env var WinRM — mai nello snapshot, mai loggato +- Git deve essere installato nel template — ora assente per design +- Switch opt-in `-UseGitClone` in `Invoke-CIJob.ps1` — default invariato, nessuna regressione +- Si perde parallelismo parziale (host clone mentre VM boota); si elimina overhead zip/transfer ### Task -- [ ] **Setup-TemplateVM.ps1 — installare Git for Windows** - - [ ] Scaricare e installare Git for Windows (installer silenzioso da git-scm.com) - ```powershell - $gitUrl = 'https://github.com/git-for-windows/git/releases/download/v2.47.1.windows.1/Git-2.47.1-64-bit.exe' - Start-Process $gitUrl '/VERYSILENT /NORESTART /COMPONENTS=gitlfs' -Wait - ``` +- [ ] **Setup-TemplateVM.ps1 — Git for Windows** + - [ ] Installer silenzioso: `Git-2.47.1-64-bit.exe /VERYSILENT /NORESTART /COMPONENTS=gitlfs` - [ ] Aggiungere `C:\Program Files\Git\cmd` al PATH di sistema nella VM - [ ] Verificare: `git --version` ritorna exit 0 nella VM - - [ ] Rimuovere il commento "Git is NOT installed" dal docblock di Setup-TemplateVM.ps1 -- [ ] **Setup-TemplateVM.ps1 — altri tool utili** - - [ ] **7-Zip**: installer silenzioso — molto più veloce di `Compress-Archive`/`Expand-Archive` - per archivi grandi (es. npm/NuGet cache warm) - - [ ] **curl.exe**: già presente in Windows 11/Server 2025 (v7.x) — verificare disponibilità - - [ ] Valutare: `jq` (parsing JSON in script PowerShell o bash) — opzionale +- [ ] **Setup-TemplateVM.ps1 — tool opzionali** + - [ ] **7-Zip**: installer silenzioso — più veloce di `Compress-Archive`/`Expand-Archive` su archivi grandi + - [ ] **curl.exe**: già presente in Server 2025 — verificare disponibilità nel PATH -- [ ] **Invoke-CIJob.ps1 — aggiungere switch `-UseGitClone`** - - [ ] Quando `-UseGitClone` è attivo: - - Saltare Phase 1 (host git clone) e la creazione del `HostSourceDir` temporaneo - - Dopo Wait-VMReady, leggere PAT da Windows Credential Manager sull'host - (es. target `git:https://gitea.emulab.it/...` o un target dedicato CI) - - Passare PAT come parametro a `Invoke-RemoteBuild.ps1` (mai loggato/stampato) - - [ ] Comportamento default invariato (`-UseGitClone` = `$false`) — nessuna regressione +- [ ] **Invoke-CIJob.ps1 — switch `-UseGitClone`** + - [ ] Quando attivo: saltare Phase 1 (host clone) e creazione `HostSourceDir` temporaneo + - [ ] Leggere PAT da Credential Manager host, passarlo a `Invoke-RemoteBuild.ps1` (mai loggato) + - [ ] Default `$false` — comportamento attuale invariato - [ ] **Invoke-RemoteBuild.ps1 — modalità in-VM clone** - - [ ] Aggiungere parametri: `-CloneUrl`, `-CloneBranch`, `-CloneCommit`, `-GitPat` - (tutti opzionali, usati solo quando `-UseGitClone` è attivo) - - [ ] Quando presenti: anziché copiare zip, eseguire nella VM: - ```powershell - git clone --recurse-submodules ` - "https://Simone:$env:CI_GIT_PAT@gitea.emulab.it/Simone/.git" ` - C:\CI\build - git -C C:\CI\build checkout $CloneCommit # pin al commit esatto - ``` - - [ ] Iniettare PAT come variabile d'ambiente della sessione WinRM (non argv, non log) - - [ ] Pulire la variabile d'ambiente dopo il clone: `[System.Environment]::SetEnvironmentVariable('CI_GIT_PAT', $null, 'Process')` + - [ ] Parametri aggiuntivi: `-CloneUrl`, `-CloneBranch`, `-CloneCommit`, `-GitPat` + - [ ] Iniettare PAT come env var della sessione WinRM (non argv, non log) + - [ ] Pulire dopo clone: `[System.Environment]::SetEnvironmentVariable('CI_GIT_PAT', $null, 'Process')` -- [ ] **Test e2e con `-UseGitClone`** +- [ ] **Test e2e con `-UseGitClone`** — `e2e-010` - [ ] Aggiornare snapshot `BaseClean` con Git installato - - [ ] Eseguire `e2e-010` con `-UseGitClone` su `nsis-plugin-nsinnounp` (ha submoduli) - - [ ] Confrontare tempo totale con e2e-009 (senza `-UseGitClone`) - - [ ] Verificare che il PAT non appaia nei log di `Invoke-CIJob.ps1` + - [ ] Eseguire su `nsis-plugin-nsinnounp` (ha submoduli) + - [ ] Confrontare tempo totale con e2e-009 + - [ ] Verificare che PAT non appaia nei log --- ## Linux Build VM (Future) -Aggiungere supporto per build su Linux per testare la compilazione cross-platform -(es. versione Linux del plugin o build check con GCC/Clang). - -- [ ] **Template VM Linux** — Provisionare template VM con Ubuntu Server 24.04 LTS - - [ ] Scegliere distro: Ubuntu 24.04 LTS (raccomandato) o Debian 12 - - [ ] Installare toolchain: GCC, Clang, CMake, Python 3.x, build-essential - - [ ] Configurare accesso SSH (chiave pubblica da host) in alternativa/integrazione a WinRM - - [ ] Prendere snapshot `BaseClean-Linux` - - [ ] Archiviare credenziali SSH in Credential Manager (o key file su host) - -- [ ] **Invoke-CIJob.ps1 — branch Linux** - - [ ] Aggiungere parametro `-GuestOS` (`Windows` / `Linux`) o rilevamento automatico da VMX - - [ ] Sostituire WinRM con SSH + SCP per trasferimento zip e raccolta artifacts - - [ ] Aggiungere supporto a comandi Linux (`bash`, `make`, `cmake --build`) - -- [ ] **Workflow Gitea — build matrix** - - [ ] Definire matrix strategy `[windows-build, linux-build]` nel workflow - - [ ] Aggiungere label `linux-build` al runner (o registrare runner separato se necessario) - - [ ] Verificare che artifacts da entrambe le piattaforme vengano raccolti correttamente - -- [ ] **Test e2e Linux** — eseguire almeno un build end-to-end su VM Linux - - [ ] Confermare che `build_plugin.py` (o analogo script) funzioni su Linux - - [ ] Confrontare artifact Linux con quelli Windows +- [ ] Template VM Ubuntu 24.04 LTS — GCC, Clang, CMake, Python 3.x, build-essential +- [ ] Accesso SSH (chiave pubblica da host), snapshot `BaseClean-Linux` +- [ ] `Invoke-CIJob.ps1` — parametro `-GuestOS` (Windows/Linux), SSH+SCP invece di WinRM +- [ ] Workflow Gitea — matrix strategy `[windows-build, linux-build]` +- [ ] Test e2e Linux — confermare `build_plugin.py` funzioni su Linux --- ## Security Hardening (Post-MVP) -- [ ] Passare WinRM da HTTP (5985) a HTTPS (5986) con certificato self-signed -- [ ] Rimuovere `AllowUnencrypted=true` dalla config WinRM dopo migrazione HTTPS -- [ ] Verificare che Get-StoredCredential funzioni correttamente negli script -- [ ] Regole firewall — limitare WinRM alla subnet build VM (192.168.79.0/24 — VMnet8 NAT) +- [ ] WinRM HTTP (5985) → HTTPS (5986) con certificato self-signed +- [ ] Rimuovere `AllowUnencrypted=true` dopo migrazione HTTPS +- [ ] Regole firewall — limitare WinRM a `192.168.79.0/24` (VMnet8 NAT) - [ ] Rotazione password guest VM trimestralmente --- @@ -244,9 +124,10 @@ Aggiungere supporto per build su Linux per testare la compilazione cross-platfor | Snapshot name | `BaseClean` | | Clone base dir | `F:\CI\BuildVMs\` | | Artifact dir | `F:\CI\Artifacts\` | +| Log dir | `F:\CI\Logs\` (retention: 30 giorni) | | Gitea URL (LAN) | `http://10.10.20.11:3100` | | Gitea URL (ext) | `https://gitea.emulab.it` | | Runner name | `local-windows-runner` (ID: 1) | | Build VM subnet | `192.168.79.0/24` (VMnet8 — NAT, internet access per build) | | Credential Manager target | `BuildVMGuest` | -| Guest username | `ci_build` — configurato e verificato | +| Guest username | `ci_build` |