47 KiB
TODO — Local CI/CD System
Documento unico di lavoro: roadmap, audit trail dei task completati, e backlog post-v1.0 con priorità e razionale. Le voci aperte sono raggruppate per area e marcate P0..P3:
Doc di setup operativi:
docs/HOST-SETUP.md — bootstrap macchina host (Setup-Host.ps1)
docs/WINDOWS-TEMPLATE-SETUP.md — provisioning template Windows (Deploy + Prepare + Setup-WinBuild2025)
docs/LINUX-TEMPLATE-SETUP.md — provisioning template Linux Ubuntu 24.04 (implementato)
P0 — sicurezza o affidabilità: affrontare prima di estendere il sistema
P1 — operatività quotidiana: automatizzare manutenzione e debug
P2 — performance e qualità del codice
P3 — estensioni nice-to-have
Summary
Last updated: 2026-05-11 (post Sprint 10: §6.1 Linux Build VM e2e PASS — Test-Ns7zipBuild-Linux.ps1 4× PASS, nsis7z.dll 2272 KB su Linux = parità Windows; In-VM Git Clone sezione chiusa)
Stato generale: §1, §2, §4, §5 chiusi. §3 completo. §6.1 Linux Build VM completato con e2e PASS (nsis7z.dll 2272 KB, parità Windows). §6.6 Tier-1 (Git+7-Zip) nel template. Prossimo P2: §6.6 Tier-2 toolchain.
| Stato | Area | Done | Open | Note |
|---|---|---|---|---|
| [x] | Setup & Infrastructure | 8 | 0 | Gitea + runner + dirs + rete tutti operativi |
| [x] | Template VM (Fasi A→D) | 4 | 0 | Snapshot BaseClean preso, credenziali in Credential Manager |
| [x] | Scripts Verification | 3 | 0 | e2e-008/009 SUCCESS, cleanup orfani + retry deleteVM ok |
| [x] | Runner Configuration | 2 | 0 | config.yaml, capacity 4, BuildVMGuest |
| [ ] | Gitea Workflow Integration | 4 | 1 | manca solo §P3 generalizzazione workflow |
| [x] | §1 Sicurezza & hardening | 3 | 0 | 1.1, 1.4, 1.6 done; 1.2/1.3/1.5/1.7/1.8 deferred (home lab) |
| [x] | §2 Affidabilità & resilienza | 7 | 0 | tutto done (2.1-2.7) |
| [x] | §3 Performance & throughput | 4 | 0 | 3.1/3.2/3.3/3.6 done; 3.4/3.5 deferred — §3 CHIUSO |
| [x] | §4 Osservabilità & manutenzione | 3 | 0 | 4.1/4.3/4.4 done (4.2 Prometheus, 4.5 Dashboard rimossi) |
| [x] | §5 Qualità codice & test | 5 | 0 | 5.1/5.2/5.3/5.4/5.5 done |
| [ ] | §6 Scalabilità & estensioni | 2 | 4 | 6.1 (Linux) done, 6.6 Tier-1 (Git+7-Zip) done; 6.2-6.5 TODO |
| [ ] | §7 Refactor Deploy ↔ Setup | 4 | 1 | 7.1/7.2/7.3/7.4 done; 7.5 (rinomina) opzionale |
| [x] | In-VM Git Clone (§3.3) | 4 | 0 | COMPLETATO 2026-05-10 — e2e PASS: 34s/25.7% vs baseline |
| [x] | Linux Build VM (§6.1) | 5 | 0 | Deploy/Prepare/Setup/Transport + doc + e2e PASS nsis7z.dll 2272 KB |
Prossimi passi consigliati (vedi anche "Suggerimento di sequencing" in fondo):
- Test Plan — eseguire completo
docs/TEST-PLAN-v1.3-to-HEAD.md(25+ Pester tests, validazione features) - §6.6 expansion — Toolchain Tier-2 (PowerShell 7, NSIS, CMake, Node.js, WiX, gh, Sysinternals, vcpkg)
- Security — Rifiori se condizioni cambiano; vedi sezione "Deferred (Home Lab)"
- §3.5 — vCPU/RAM tuning per workload (P2, deferred — home lab optimization)
- §3.4 — Pre-warm pool di cloni (P3, deferred — profiling-dependent optimization)
Setup & Infrastructure
-
Gitea Server — già in esecuzione su
http://10.10.20.11:3100(ehttps://gitea.emulab.it)- Runner registration token ottenuto e usato
- Create at least one test repository with
.gitea/workflows/build.yml(Simone/nsis-plugin-nsinnounp— testato e2e, workflow ingitea/workflows/build-nsis.yml) - Gitea Actions abilitato (runner registrato con successo)
-
act_runner — installato e registrato sull'host Windows
- Binario
gitea-runner v1.0.2scaricato inF:\CI\act_runner\act_runner.exe - Registrato con Gitea (
http://10.10.20.11:3100) — runner ID 1, nomelocal-windows-runner config.yamlcopiato inF:\CI\act_runner\config.yamlcon labelwindows-build:host- Installato come servizio Windows via NSSM — stato: Running, StartType: Automatic
- Verificare che il runner appaia "Online" nell'UI Gitea Admin → Actions → Runners
- Confermare riavvio automatico dopo reboot host
- Binario
-
Directory CI create su
F:\CI\F:\CI\BuildVMs\F:\CI\Artifacts\F:\CI\act_runner\F:\CI\Cache\NuGet\F:\CI\RunnerWork\F:\CI\Templates\WinBuild2025\F:\CI\Logs\— log per job (retention: 30 giorni)F:\CI\ISO\— contiene26100.1742.240906-0331.ge_release_svc_refresh_SERVER_VOL_x64FRE_en-us.iso(Windows Server 2025)
-
CredentialManager PowerShell module v2.0 installato (Scope: CurrentUser)
-
Rete VM: VMnet8 (NAT) — internet access per pip/nuget/npm durante i build
Template VM
-
Provision template VM in VMware Workstation — segui questi passi nell'ordine esatto:
Fase A — Crea e installa la VM (NIC: NAT per internet)
- Crea nuova VM in VMware Workstation con queste impostazioni:
- 4 vCPU, 6144 MB RAM, disco 80 GB thin
- VMX path:
F:\CI\Templates\WinBuild2025\WinBuild2025.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 - Installa Windows Server 2025 dall'ISO
- All'interno della VM (come Administrator), abilita WinRM:
cmd winrm quickconfig -qpowershell Enable-PSRemoting -Force -SkipNetworkProfileCheck Set-Item WSMan:\localhost\Service\Auth\Basic $true -Force # AllowUnencrypted left false — Deploy post-install.ps1 configures HTTPS/5986 listener Set-Item WSMan:\localhost\Client\TrustedHosts -Value '*' -Force - Attiva Windows Server 2025 (prima dello snapshot — i linked clone ereditano l'attivazione):
cmd slmgr /dliSe non attivato, scegli il metodo appropriato: - KMS (server KMS in rete):slmgr /skms <IP_KMS>poislmgr /ato- MAK/Retail key:slmgr /ipk XXXXX-XXXXX-XXXXX-XXXXX-XXXXXpoislmgr /ato- KMS pubblico (alternativa lab): vedi https://github.com/robin113x/Windows-Server-Activation/ Verifica:slmgr /xpr— deve mostrare attivazione permanente o scadenza lontana - Nota l'IP assegnato dal DHCP di VMnet8 (es.
192.168.79.x) —ipconfignella VM
Fase B — Provisioning automatico dall'host
- Dall'host, esegui:
powershell cd n:\Code\Workspace\Local-CI-CD-System\template .\Prepare-WinBuild2025.ps1 -VMIPAddress 192.168.79.128 -SkipWindowsUpdateInstalla: WinRM config, utenteci_build, .NET SDK 10.0, VS Build Tools 2026, Python 3.13.3. Lo script esegue validazione automatica ad ogni passaggio (Assert-Step): - Pre-flight: IP ottetti 0-255, TCP/5986 raggiungibile, Setup-WinBuild2025.ps1 presente - Host WinRM: AllowUnencrypted, TrustedHosts - Guest prep:C:\CIesiste, file copiato, size match - Post-setup remoto (9 check): WinRM, user+admin, UAC, firewall, .NET, Python, MSBuild, CI dirs Se qualsiasi check fallisce → script termina con errore → non prendere lo snapshot. - Setup completato con successo (VS Build Tools 2026 exit code 0).
Setup-WinBuild2025.ps1ora esegue validazioneAssert-Stepdopo ogni step interno (WinRM, Firewall, User, UAC, Dirs, Defender, .NET, Python, VS Build Tools, Toolchain, Cleanup, Final pre-snapshot gate) — throws se qualsiasi check fallisce (2026-05-09)
Fase C — Spegni e prendi lo snapshot
- VM rimane su VMnet8 (NAT) — internet access permanente per build che richiedono pip/nuget/npm
- Spegni la VM: Start → Shut down
- Prendi snapshot: VM → Snapshot → Take Snapshot
Nome esatto:
BaseCleanPrerequisito:Prepare-WinBuild2025.ps1deve essere uscito con exit 0 — tutti gliAssert-Steppassati, incluso il Final pre-snapshot gate nel guest. - Lascia la VM spenta — non modificarla mai più dopo questo snapshot
Fase D — Credenziali e config
- Archivia credenziali guest sull'host (PowerShell elevato con CredentialManager):
powershell New-StoredCredential -Target "BuildVMGuest" -UserName "ci_build" ` -Password "<your-build-password>" -Persist LocalMachine - Verifica
GITEA_CI_TEMPLATE_PATHinF:\CI\act_runner\config.yaml— aggiornato aWinBuild2025.vmx(2026-05-08)
- Crea nuova VM in VMware Workstation con queste impostazioni:
- 4 vCPU, 6144 MB RAM, disco 80 GB thin
- VMX path:
Scripts Verification
- Test
New-BuildVM.ps1standalone — cloneClone_test-002creato correttamente (2026-05-08) - Test
Wait-VMReady.ps1standalone — exit 0 in ~5s, VM pronta (2026-05-08) - Test
Invoke-RemoteBuild.ps1— dotnet restore + build OK, artifacts.zip creato in VM (2026-05-08) - Test
Get-BuildArtifacts.ps1— artifacts.zip (78 KB) copiato in F:\CI\Artifacts\test-003\ (2026-05-08) - Test
Remove-BuildVM.ps1— VM spenta + directory rimossa correttamente (2026-05-08) - Test
Invoke-CIJob.ps1end-to-end su una soluzione reale (nsis-plugin-nsinnounp)- e2e-008: SUCCESS — build OK + artifact raccolto (1632 KB)
- e2e-009: SUCCESS — cleanup automatico VM + clone confermato (finally block)
scripts/Cleanup-OrphanedBuildVMs.ps1creato e verificato —-WhatIf, soglia-MaxAgeHours, hard stop + deleteVM + rimozione dir (2026-05-09)scripts/Remove-BuildVM.ps1fixvmrun deleteVMexit -1 — pollvmrun list+ retry 3× backoff 0/3/6s (2026-05-09)
Runner Configuration
runner/config.yamlaggiornato con percorsiF:\CI\, rete VMnet8 (NAT), label corretticapacity: 4configurato (64 GB RAM / ~8 GB per VM)- Aggiornare
GITEA_CI_TEMPLATE_PATHinconfig.yamldopo creazione template VM - Archiviare credenziali guest in Windows Credential Manager (target:
BuildVMGuest)
Gitea Workflow Integration
- Copiare
gitea/workflow-example.ymlin.gitea/workflows/build.ymlnel repo di test (workflowbuild-nsis.ymlgià presente e funzionante pernsis-plugin-nsinnounp) - Push commit e verificare job in Gitea Actions UI
- Verificare artifact scaricabile da Gitea dopo build riuscita
gitea/workflows/lint.ymlcreato — PSScriptAnalyzer su push/PR che toccano.ps1(2026-05-09)- [P3] Adattare workflow per altri repository — generalizzare
BUILD_COMMANDeARTIFACT_SOURCE. Vedi anche §6.2 (composite action riutilizzabile).
1. Sicurezza & hardening
1.1 [P0] [x] Migrare WinRM da HTTP/Basic a HTTPS/5986 — COMPLETATO 2026-05-10
Azioni:
- Generare cert self-signed nel template prima dello snapshot (già in Deploy post-install.ps1).
- Sostituire
New-PSSession -ComputerName $ipcon-UseSSL -Port 5986 -Authentication BasicinInvoke-RemoteBuild.ps1,Get-BuildArtifacts.ps1,Prepare-WinBuild2025.ps1,Validate-*.ps1. - Rimuovere
AllowUnencrypted=trueda Deploy post-install.ps1 e Setup-WinBuild2025.ps1 (assertion → false). -SkipCACheck/-SkipCNCheck/-SkipRevocationCheckmantenuti neiNew-PSSessionOptioneNew-WSManSessionOption(cert lab self-signed — documentato inline).- Regola firewall
WinRM-HTTPSin Deploy ristretta aRemoteAddress '192.168.79.0/24'. Wait-VMReady.ps1usaNew-WSManSessionOption+Test-WSMan -Port 5986 -UseSSL.Prepare-WinBuild2025.ps1: preflight TCP/5986, host non imposta piùAllowUnencrypted; soloTrustedHostsviene salvato/ripristinato.Validate-DeployState.ps1,Validate-SetupState.ps1: connessione HTTPS/5986, checkAllowUnencrypted=false.
1.4 [P1] [x] Validazione IP per-ottetto — COMPLETATO 2026-05-10
Regex per-ottetto sostituita in tutti e 4 i file:
'^((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.){3}(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)$'
Estrazione in scripts/_Common.psm1 — vedi §5.2 (P2, backlog).
1.6 [P2] [x] Defender + Firewall + UAC tutti disattivati nel template — documentare il modello di minaccia — COMPLETATO 2026-05-10
File: docs/BEST-PRACTICES.md:§2.1 Threat Model.
COMPLETATO: Sezione "2.1. Threat Model — Disabled Security Features" aggiunta a BEST-PRACTICES.md. Documenta:
- Stato corrente: Defender, Firewall, UAC disabilitate (costi vs. benefici tabellati).
- Quando è accettabile: ambiente lab isolato con code trusted.
- Quando rompe: code non fidate, sharing host, esposizione VMnet8 a LAN.
- Mitigazioni: come riabilitare Firewall, Defender con esclusioni, UAC con costi specifici.
Future modifiche di sicurezza vanno documentate nello stesso posto.
2. Affidabilità & resilienza
2.1 [P0] [x] Race su IP allocation — COMPLETATO 2026-05-10
File: runner/config.yaml:17, scripts/Invoke-CIJob.ps1:244-253.
Stato osservato: race non riprodotta in e2e-008/009 (un job alla volta). capacity: 4
resta attivo in produzione — bug teorico finché non si esegue stress test parallelo.
Motivazione: con 4 job paralleli e DHCP VMnet8, due VM possono ottenere lo stesso IP se
la lease pool è stretta o se due vmrun start rispondono troppo vicini.
getGuestIPAddress ritorna l'IP visto dalla VM stessa, quindi la collisione non viene
rilevata in fase di Wait-VMReady — apparirà come "WinRM risponde ma è la VM sbagliata".
Opzioni:
- A — IP allocator file-based con lock: prendere un IP libero da
192.168.79.101..104, scriverlo inF:\CI\State\ip-leases\<jobid>e iniettarlo comebootArgso viavmrun writeVariableprima di start. Rilascio nelfinally. - B — DHCP reservation per MAC nel VMware NAT DHCP server (
vmnetdhcp.conf): assegnare 4 MAC noti, hard-coded nei VMX dei cloni. Più semplice ma richiede gestire il VMX clonato. - C — pool fissato a
capacity: 1finché non si implementa A o B.
L'opzione A è la più portabile e si integra con il pre-warm pool (§3.4).
2.2 [P1] [x] Cleanup orfani schedulato — COMPLETATO 2026-05-10
File: scripts/Cleanup-OrphanedBuildVMs.ps1 — script pronto, scheduling registrato da scripts/Register-CIScheduledTasks.ps1.
Estendere Setup-Host.ps1 per registrare un Task Scheduler:
$action = New-ScheduledTaskAction -Execute 'powershell.exe' `
-Argument '-NoProfile -NonInteractive -ExecutionPolicy Bypass -File "N:\Code\Workspace\Local-CI-CD-System\scripts\Cleanup-OrphanedBuildVMs.ps1"'
$trigger = New-ScheduledTaskTrigger -Daily -At 4am -RandomDelay (New-TimeSpan -Minutes 30)
$principal = New-ScheduledTaskPrincipal -UserId 'SYSTEM' -RunLevel Highest
Register-ScheduledTask -TaskName 'CI-CleanupOrphans' -Action $action -Trigger $trigger -Principal $principal -Force
Aggiungere anche un trigger AtStartup per gestire crash dell'host.
Suggerito: ogni 6 ore, -MaxAgeHours 4.
2.3 [P1] [x] Retention artifact + log automatica — COMPLETATO 2026-05-10
File: scripts/Invoke-RetentionPolicy.ps1 — script creato; scheduling via scripts/Register-CIScheduledTasks.ps1.
Stessa pattern di §2.2 ma su F:\CI\Artifacts con -AddDays(-30) e su F:\CI\Logs con la
finestra già configurata in Invoke-CIJob.ps1. Aggiungere
Get-PSDrive F | Where-Object { $_.Free -lt 50GB } come guard: se libero < 50 GB,
retention più aggressiva (7 giorni) e log warning.
2.4 [P1] [x] Remove-BuildVM.ps1 — supportare -WhatIf — COMPLETATO 2026-05-10
File: scripts/Remove-BuildVM.ps1:28.
[CmdletBinding(SupportsShouldProcess)] aggiunto; op distruttive (stop, deleteVM, Remove-Item) gated su $PSCmdlet.ShouldProcess.
2.5 [P1] [x] Snapshot versionato BaseClean_<yyyyMMdd> — COMPLETATO 2026-05-10
File: docs/BEST-PRACTICES.md:142-145, scripts/Invoke-CIJob.ps1:100.
Motivazione: quando si refresha il template (KMS lease semestrale, update toolchain), il
flusso attuale richiede di sovrascrivere BaseClean — i cloni esistenti diventano invalidi
e non c'è rollback.
Strategia:
- Naming:
BaseClean_20260509. runner/config.yamlaggiungeGITEA_CI_SNAPSHOT_NAMEcome env var.Invoke-CIJob.ps1legge da env, default'BaseClean'per compat.- Pratica: tieni gli ultimi 2 snapshot, cancella il più vecchio dopo 1 settimana di uso pulito del nuovo.
Si lega al task: refresh semestrale snapshot template VM (KMS lease = 180 giorni).
Boot template su VMnet8 (NAT) → slmgr /ato → nuovo snapshot.
2.6 [P2] [x] Backup automatico VMDK template — COMPLETATO 2026-05-10
File: scripts/Backup-CITemplate.ps1.
Copia atomica F:\CI\Templates\WinBuild → F:\CI\Backups\Template_<yyyyMMdd_HHmmss>\.
Ferma act_runner prima, lo riavvia nel finally. Prune automatico (default: mantieni 3).
SupportsShouldProcess → supporta -WhatIf. Esecuzione manuale pre-refresh.
2.7 [P2] [x] Health check del runner + monitoraggio Event Log — COMPLETATO 2026-05-10
File: scripts/Watch-RunnerHealth.ps1; task registrato da scripts/Register-CIScheduledTasks.ps1 come CI-RunnerHealth (ogni 15 min).
Controlla Get-Service act_runner. Se non Running: EventId 1002 (Warning) + Restart-Service.
Cooldown: max 3 restart/h via JSON state file F:\CI\State\runner-restart-log.json.
Oltre il limite: EventId 1004 (Error) + webhook :sos: senza restart. Webhook opzionale
Discord/Gitea identico a Watch-DiskSpace.ps1.
3. Performance & throughput
3.1 [P1] [x] NuGet/pip cache su shared folder — COMPLETATO 2026-05-10
File: scripts/Set-TemplateSharedFolders.ps1, scripts/Invoke-RemoteBuild.ps1.
Set-TemplateSharedFolders.ps1: edita il VMX template aggiungendo due shared folder
(nuget-cache → F:\CI\Cache\NuGet, pip-cache → F:\CI\Cache\pip), idempotente,
.bak del VMX originale mantenuto, SupportsShouldProcess.
Invoke-RemoteBuild.ps1: aggiunto -UseSharedCache switch. Quando attivo, inietta
$env:NUGET_PACKAGES nel scriptblock dotnet restore/build e $env:PIP_CACHE_DIR nel
scriptblock custom build command.
Attivazione:
- Fermare template VM.
.\Set-TemplateSharedFolders.ps1(una tantum, pre-snapshot).- Passare
-UseSharedCacheaInvoke-RemoteBuild.ps1nei job dotnet/pip.
Dopo snapshot refresh: cache si riscalda al primo build — accettabile.
3.2 [P1] [x] Sostituire Compress-Archive con 7-Zip — COMPLETATO 2026-05-10
File: scripts/Invoke-RemoteBuild.ps1 (3 rimpiazzi Compress-Archive → 7-Zip + fallback).
Implementazione:
- Host-side: nuova funzione
Compress-BuildArtifact(check 7-Zip, fallback Compress-Archive) usata per comprimere source tree - Guest-side (custom build): inline 7-Zip check in scriptblock per artifact compression
- Guest-side (dotnet build): inline 7-Zip check in scriptblock per output directory compression
- Usa
-mmt=on -mx1per multi-thread con ratio simile a Compress-Archive
Vantaggio: 10-20 s risparmio per repo >100 MB una volta che 7-Zip installato (§6.6). Attuale: Fallback a Compress-Archive finché 7-Zip non nel template — zero overhead.
3.3 [P2] [x] In-VM clone (-UseGitClone) — COMPLETATO 2026-05-10
File: scripts/Invoke-CIJob.ps1, scripts/Invoke-RemoteBuild.ps1.
Implementazione:
- Invoke-CIJob.ps1:
-UseGitCloneswitch + conditional Phase 1 (skip host clone) - Invoke-RemoteBuild.ps1: Mode 1 (host) vs Mode 2 (guest) + params (CloneUrl, CloneBranch, CloneCommit, CloneSubmodules)
- Guest clone: git clone direttamente nel VM, PAT da Credential Manager (§1.5 no-log cleanup)
- Prerequisiti satisfatti: Git + 7-Zip in template (§6.6, completato)
Beneficio: Elimina host-zip-transfer overhead (rilevante per repo > 200 MB con submoduli). Prossimo: E2E test con nsis-plugin-nsinnounp (-UseGitClone flag) per misurare impatto.
3.5 [P2] [ ] vCPU/RAM tuning per workload — DEFERRED (home lab)
File: docs/OPTIMIZATION.md:82-89, VMX template.
numvcpus=4, memsize=6144 è ragionevole ma non ottimo per ogni build. Per
nsis-plugin-nsinnounp (4 build paralleli interni con thread divisi) 4 vCPU sono già saturati.
Considerare:
- VMX pinning: 6 vCPU per build C++ pesanti, 2 vCPU per build .NET piccoli.
- Esporre
-VMCpu/-VMMemoryaInvoke-CIJob.ps1con override via workflow.
Deferred: Non necessario per home lab; priorità bassa fino a che performance non è bottleneck.
3.6 [P2] [x] Benchmark baseline — COMPLETATO 2026-05-10
File: scripts/Measure-CIBenchmark.ps1.
Misura 5 fasi per iterazione: clone, start, IP acquire, WinRM ready, destroy.
Output: tabella console + append a F:\CI\Logs\benchmark.jsonl (JSONL, una riga per iterazione).
Supporta -Iterations N per ridurre varianza. Importa _Common.psm1 (Invoke-Vmrun, Resolve-VmrunPath).
Uso: .\Measure-CIBenchmark.ps1 prima e dopo §3.1/§3.2 per misurare impatto.
4. Osservabilità & manutenzione
4.1 [P1] [x] Log strutturati per parsing — COMPLETATO 2026-05-10
File: scripts/Invoke-CIJob.ps1:178-187.
Motivazione: i log attuali sono Write-Host testuale. Per dashboard / alerting servono
log machine-readable.
Aggiungere a fianco del transcript un secondo file invoke-ci.jsonl:
function Write-JobEvent {
param([string]$Phase, [string]$Status, [hashtable]$Data = @{})
$event = @{
ts = (Get-Date).ToString('o')
jobId = $JobId
phase = $Phase
status = $Status
data = $Data
}
$event | ConvertTo-Json -Compress | Add-Content $jsonLog
}
Emettere in ogni transizione di fase. Permette grafici (durata media per fase, tasso di
fallimento) con jq o Loki/Grafana se in futuro.
4.3 [P1] [x] Disk space alert — COMPLETATO 2026-05-10
File: estendere Setup-Host.ps1 o creare scripts/Watch-DiskSpace.ps1.
F: riempito = build silenziosamente fallite (linked clone fallirà su vmrun clone con
messaggi criptici). Alert via eventcreate o webhook Gitea/Discord quando libero < 50 GB.
4.4 [P2] [x] Runbook per incident comuni — COMPLETATO 2026-05-10
File: nuovo docs/RUNBOOK.md.
Documentare con copy-pasta:
- "Runner offline in Gitea UI" → check service, log, restart.
- "Tutte le build falliscono in Phase 2" →
vmrun -T ws list, parent VMDK lock, snapshot mancante. - "Build lente" → check disk free, vmware-vmx.exe CPU, rete VMnet8.
- "VMX corrotto post-crash host" → restore from
F:\CI\Backups\Template_<latest>.
Ogni voce: sintomo, comando di triage, fix, escalation.
5. Qualità codice & test
5.1 [P1] [x] Pester smoke tests sugli script — COMPLETATO 2026-05-10
File: tests/_Common.Tests.ps1, tests/New-BuildVM.Tests.ps1, tests/Remove-BuildVM.Tests.ps1, tests/Wait-VMReady.Tests.ps1.
Test con fake vmrun .cmd (exit code via %FAKE_VMRUN_EXIT% env var — nessuna VM reale):
_Common.psm1:New-CISessionOptionTLS flags,Resolve-VmrunPaththrow/return,Invoke-VmrunExitCode/Output/ThrowOnErrorNew-BuildVM.ps1: throw su template mancante, throw + cleanup su clone fail, formato nome Clone_{JobId}_{timestamp}Remove-BuildVM.ps1: no-op su VMX mancante, cleanup dir parziale, -WhatIf non distrugge, destroy rimuove dirWait-VMReady.ps1: throw su vmrun mancante, throw su timeout, ValidatePattern IP (accetta/rifiuta)
Eseguire: Invoke-Pester tests\ -Output Detailed
5.2 [P2] [x] Modulo PowerShell condiviso scripts/_Common.psm1 — COMPLETATO 2026-05-10
File: scripts/_Common.psm1.
Esporta: New-CISessionOption (WinRM self-signed TLS), Resolve-VmrunPath (valida vmrun.exe),
Invoke-Vmrun (wrapper uniforme -T ws, ritorna {ExitCode, Output}, supporta -ThrowOnError).
Importato da: Invoke-RemoteBuild.ps1, Get-BuildArtifacts.ps1, New-BuildVM.ps1.
5.3 [P2] [x] Esecuzione vmrun con check exit code uniforme — COMPLETATO 2026-05-10
Invoke-Vmrun in _Common.psm1. New-BuildVM.ps1 refactored per usarlo.
Invoke-RemoteBuild.ps1 e Get-BuildArtifacts.ps1 usano New-CISessionOption.
5.4 [P2] [x] PSScriptAnalyzer rules custom — COMPLETATO 2026-05-10
File: PSScriptAnalyzerSettings.psd1.
Regole attive: PSAvoidUsingInvokeExpression, PSUseShouldProcessForStateChangingFunctions,
PSUsePSCredentialType, PSAvoidUsingPlainTextForPassword,
PSAvoidUsingConvertToSecureStringWithPlainText, PSAvoidGlobalVars,
PSUseConsistentIndentation (4 spazi), PSUseConsistentWhitespace.
Soppresso progetto-wide: PSAvoidUsingWriteHost (output strutturato per act_runner).
5.5 [P3] [x] Type hints nei param block — COMPLETATO 2026-05-10
File: tutti script in scripts/ — 15 file, tutti con type hints.
Coverage: Tutti param hanno type hints ([string], [int], [switch]) +
validation ([ValidateRange], [ValidatePattern], [ValidateScript]) +
[Parameter(Mandatory)] dove necessario.
6. Scalabilità & estensioni
6.1 [P2] [x] Linux Build VM
Documento di pianificazione dedicato: docs/LINUX-TEMPLATE-SETUP.md — bozza completa con fasi A→H, decisioni di design, differenze rispetto al template Windows.
Implementato — vedi sezione "Linux Build VM" sotto per il riassunto inline.
Considerazione architetturale: SSH su WSL2 non basta — serve VM vera per parità con il
flusso Windows. Ubuntu 24.04 minimal con script bash diretto (parità con flusso Windows).
Sostituire WinRM con SSH key-based; Invoke-Command non funziona — usare ssh.exe +
scp.exe o il modulo Posh-SSH.
Aggiungere scripts/_Transport.psm1 con due implementazioni (WinRM, SSH) dietro la
stessa interfaccia. Invoke-CIJob.ps1 sceglie dal parametro -GuestOS.
6.2 [P3] [ ] Workflow generico riutilizzabile (composite action)
File: gitea/workflow-example.yml.
Trasformare in composite action Gitea (.gitea/actions/local-ci-build/action.yml)
richiamabile da qualsiasi repo:
- uses: ./Simone/local-ci-build@v1
with:
build-command: 'python build_plugin.py --final'
artifact-source: 'dist'
submodules: true
Riduce la duplicazione su nuovi repo e centralizza l'evoluzione del wrapper.
6.3 [P3] [ ] Multi-host runner federation
Quando 4 VM in parallelo non bastano, l'opzione naturale è un secondo host Windows con
stesso Setup-Host.ps1 registrato come secondo runner Gitea (label windows-build:host-2).
Già supportato lato Gitea, basta replicare il setup.
Premessa: prima di scalare orizzontale, profilare se il collo di bottiglia è CPU (i9-10900X 20T è abbondante) o I/O (NVMe). Se è I/O, una seconda NVMe sullo stesso host basta.
6.4 [P3] [ ] Build matrix nel workflow
File: gitea/workflows/build-nsis.yml.
Attualmente single job. Quando arriverà la VM Linux:
strategy:
matrix:
target: [windows, linux]
runs-on: ${{ matrix.target }}-build
6.5 [P3] [ ] Secret injection workflow-level
Per chiavi di firma (Authenticode, GPG), usare i Gitea secrets nel workflow e passarli a
Invoke-CIJob.ps1 come param + env, mai loggati. Stesso modello di §1.5 per il PAT.
6.6 [P2] [~] Toolchain Tier-1 in Setup-WinBuild2025
File: template/Setup-WinBuild2025.ps1.
Status: Git + 7-Zip implemented (Step 11, 2026-05-10); Tier-2 (8 tools) pending.
Motivazione: toolchain attuale (.NET SDK, Python, VS Build Tools) copre solo C#/Python/MSBuild.
Aggiungere tools generici-CI riduce il bisogno di installazione ad-hoc nei workflow e abilita
build più ampi senza toccare il template.
Tier-1 (implementato)
- Git for Windows (v2.54.0.windows.1) — Step 11, self-clone in VM
- 7-Zip (26.01) — Step 11, universal compression + fallback §3.2
Tier-2 (backlog) — tool da aggiungere come ulteriori step Setup-WinBuild2025 (ognuno con Assert-Step):
| Tool | Versione | Razionale |
|---|---|---|
| Git for Windows | 2.54.0.windows.1 | [x] Self-clone in VM (alt a host-zip-transfer), submodule fetch |
| 7-Zip | 26.01 | [x] Universale unpack/zip; molti installer e workflow ne dipendono |
| PowerShell 7.x | latest LTS | [ ] Più veloce di 5.1, parallel pipelines, operatori moderni |
| NSIS | latest | Test build installer (es. nsis-plugin-nsinnounp) |
| CMake | latest | Build system cross-platform per progetti C/C++ nativi |
| Node.js LTS | latest LTS | Frontend/Electron pipelines, JS toolchain (npm) |
| WiX Toolset | v4 stable | MSI building da .NET projects |
| gh CLI | latest | Upload artifact a release Gitea/GitHub, comment PR |
| Sysinternals | sysinternals.com live |
Diagnostica process/handle quando build flaky |
| vcpkg | latest | Package manager C++ per dipendenze native |
Approccio:
- Pinning hash SHA256 per ogni installer (vedi §1.3)
- Convenzione path guest: tool in
C:\BuildTools\<tool>\(separato daC:\CI\runtime —C:\CI\resta per artefatti job e worker temp;C:\BuildTools\per software statico). Documentare indocs/BEST-PRACTICES.mdprima di implementare. - Aggiungere a
PATHmachine-wide - Defender già off → no scan overhead durante install
- Step esegue in seriale dopo
Toolchain cross-checkesistente, prima diCleanup Final pre-snapshot gate: aggiungere checkwhere.exeper ogni tool- Cross-link: Git for Windows e 7-Zip sono richiesti anche da §3.2 e dalla sezione "In-VM Git Clone" — implementare qui per evitare doppio lavoro
Validazione per-tool:
- Eseguibile risolvibile via
where.exe - Versione exact match al param
-<Tool>Version - (per gh)
gh --versionreturns 0 - (per vcpkg)
vcpkg.exe version
Param da aggiungere a Setup + Prepare:
-GitVersion,-7ZipVersion,-Pwsh7Version,-NSISVersion,-CMakeVersion,-NodeJSVersion,-WiXVersion,-GhCliVersion,-VcpkgRev(rev SHA del repo)
Tier-2 (opzionali, separati): Java JDK, Maven/Gradle, Rust, Go, LLVM, Docker, Azure/AWS CLI, WinDbg.
Non includere in Setup base — workflow-level via choco install o download diretto.
7. Refactor confine Deploy ↔ Setup
Obiettivo: separazione netta delle responsabilità — Deploy produce template OS stand-alone, Setup fa build customization (user, dirs, toolchain). Eliminare drift e duplicazioni; ogni concern ha una sola sorgente di verità.
Stato attuale (duplicati): UAC, Explorer LaunchTo, Server Manager off, DisableCAD, OOBE telemetry, WU services disable — entrambi gli script li toccano.
7.1 [P1] [x] Spostare base OS hardening da Setup a Deploy
File: template/Deploy-WinBuild2025.ps1, template/Setup-WinBuild2025.ps1.
- Aggiungere
Set-NetFirewallProfile -Enabled False(tutti i profili) in Deploy post-install.ps1 - Aggiungere
MaxMemoryPerShellMB=2048,IdleTimeOut=7200000,MaxProcessesPerShell=25,StartupType=Automaticin Deploy dopo Enable-PSRemoting - Aggiungere in Deploy items mancanti rispetto a Setup 5c: lock screen (
NoLockScreen), SM GPO policy key (DoNotOpenAtLogon), SM scheduled task disable,DisableCADin Winlogon, OOBE non-policy key - Setup Step 1 (Firewall) → Assert-Step only
- Setup Step 2 (Defender) → già validation-only (refactor 2026-05-09)
- Setup Step 3 (WinRM tuning) → Assert-Step only (rimuovi Enable-PSRemoting, winrm set, Set-Item, Set-Service)
- Setup Step 4b (UAC) → Assert-Step only
- Setup Step 5b (Explorer LaunchTo) → Assert-Step only
- Setup Step 5c (Server Manager / DisableCAD / OOBE) → Assert-Step only
- E2e validation — completata §7.4 (2026-05-10)
7.2 [P1] [x] WU lifecycle — strategia B (Deploy: GPO + Manual; Setup: lifecycle)
File: template/Deploy-WinBuild2025.ps1, template/Setup-WinBuild2025.ps1.
Strategia B: Deploy lascia servizi WU start=demand (Manual, default Windows) e scrive solo
GPO NoAutoUpdate=1 + DisableWindowsUpdateAccess=1. Setup Step 6 clears i GPO locks (Step A),
avvia WU via SchTask SYSTEM, poi Step 6b disabilita servizi permanentemente post-update.
- Deploy: rimuovere
sc.exe config wuauserv start= disabled(e UsoSvc, WaaSMedicSvc) - Deploy: aggiungere GPO
DisableWindowsUpdateAccess=1(era mancante;NoAutoUpdate=1già presente) - Setup Step 6 Step A: già rimuove
DisableWindowsUpdateAccess+NoAutoUpdateprima del COM API — nessuna modifica necessaria - Setup Step 6 Step D: già fa
Set-Service start=Manual+Start-Service— idempotente con servizi già Manual - Setup Step 6b: già disabilita wuauserv/UsoSvc + GPO keys — nessuna modifica necessaria
- E2e validation — completata §7.4 (2026-05-10)
7.3 [P2] [x] Update header docs di entrambi gli script
- template/Deploy-WinBuild2025.ps1
.DESCRIPTION: aggiornato con tutte le hardening voci (firewall, WinRM tuning, WU GPO strategy B, lock screen, SM, OOBE) - template/Setup-WinBuild2025.ps1
.DESCRIPTION: Steps 1/3/4b/5b/5c marcati "validation-only — set by Deploy"; step ordering rationale aggiornato - docs/WINDOWS-TEMPLATE-SETUP.md: architettura "tre script", VMX path
WinBuild2025.vmx, Fase C step list + razionale + tabella validazioni aggiornati
7.4 [P2] [x] Test e2e refactor — COMPLETATO 2026-05-10
- Deploy stand-alone su VM test →
Get-NetFirewallProfiletuttiEnabled=False,Get-Service wuauserv | Select StartType→Manual,NoAutoUpdate=1GPO presente - Prepare dopo Deploy con
-SkipWindowsUpdate→ tuttiAssert-Steppassano[OK]senza eseguire Set (log mostra solo validation output) - Prepare senza
-SkipWindowsUpdate→ WU (0 update trovati, ResultCode=0), Step 6b disabilita wuauserv/UsoSvc (StartType=Disabled) - Final gate del guest passa su tutti e 7 i check; snapshot
BaseCleanpreso
Fix emersi durante §7.4 (applicati):
- Deploy:
UsoSvcimpostato aManualesplicitamente (default Server 2025 = Automatic) - Setup cleanup:
Set-Service -StartupType Disabledri-applicato su wuauserv/UsoSvc dopo DISMStartComponentCleanup(DISM/WaaSMedicSvc può resettare StartType) - Deploy + Setup: autologin Administrator (
AutoAdminLogon=1) aggiunto in post-install.ps1 e validato in Assert-Step 5c - Nuovi script:
template/Validate-DeployState.ps1,template/Validate-SetupState.ps1
7.5 [P3] [ ] Rinomina Setup → Setup-CITools (opzionale, futuro)
Una volta che Setup fa solo build customization, nome Setup-WinBuild2025 è impreciso —
non setup-a la build VM, estende un template OS già pronto con toolchain CI.
Rinominare in Setup-CITools.ps1 o Install-CIToolchain.ps1 rifletterebbe meglio la
responsabilità ridotta. Tracciare in TODO post-7.1/7.2.
In-VM Git Clone (Ottimizzazione) — riferimento §3.3
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.
Strategia
Flusso attuale:
host: git clone → host: Compress-Archive → WinRM: copia zip → VM: Expand-Archive → VM: build
Flusso proposto:
VM avviata → WinRM: git clone --recurse-submodules https://<token>@gitea/... → VM: build
Punti chiave:
- Il PAT non deve essere nello snapshot — viene iniettato a runtime come env var via WinRM
(
git clone https://Simone:<pat>@gitea.emulab.it/<repo>.git) e non viene mai persistito - Git deve essere installato nel template (
Setup-WinBuild2025.ps1) — ora è assente per design - L'implementazione deve essere non-breaking: nuovo switch opt-in
-UseGitCloneinInvoke-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)
Task
-
Tool prerequisiti nel template — implementati in §6.6 (Tier-1 Toolchain):
- Git for Windows + 7-Zip + gh CLI installati con hash pinning e
Assert-Step - Rimuovere il commento "Git is NOT installed" dal docblock di Setup-WinBuild2025.ps1 una volta applicato §6.6
- curl.exe: già presente in Windows Server 2025 — verificare con
where.exe curl
- Git for Windows + 7-Zip + gh CLI installati con hash pinning e
-
Invoke-CIJob.ps1 — aggiungere switch
-UseGitClone- Quando
-UseGitCloneè attivo:- Saltare Phase 1 (host git clone) e la creazione del
HostSourceDirtemporaneo - 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 a
Invoke-RemoteBuild.ps1rispettando i vincoli sicurezza di §1.5
- Saltare Phase 1 (host git clone) e la creazione del
- Comportamento default invariato (
-UseGitClone=$false) — nessuna regressione
- Quando
-
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/<repo>.git" ` C:\CI\build git -C C:\CI\build checkout $CloneCommit # pin al commit esatto - Implementare iniezione/pulizia PAT secondo §1.5 (env var sessione, no argv, no log,
cleanup
[System.Environment]::SetEnvironmentVariable('CI_GIT_PAT', $null, 'Process'))
- Aggiungere parametri:
-
Test e2e con
-UseGitClone— COMPLETATO 2026-05-10- Aggiornare snapshot
BaseCleancon Git installato - Eseguire
e2e-010con-UseGitClonesunsis-plugin-nsinnounp(ha submoduli) - Confrontare tempo totale con e2e-009 (senza
-UseGitClone) — 34s / 25.7% più veloce - Verificare che il PAT non appaia nei log di
Invoke-CIJob.ps1
- Aggiornare snapshot
Linux Build VM — riferimento §6.1 [IMPLEMENTATO]
Supporto build su Linux aggiunto con le seguenti fasi completate:
-
Template VM Linux — script di provisioning per Ubuntu Server 24.04 LTS
template/Deploy-LinuxBuild2404.ps1— crea VM da cloud VMDK, cloud-init, SSH waittemplate/Setup-LinuxBuild2404.sh— installa toolchain CI (GCC, Clang, CMake, Python 3, git, 7z), hardening SSH, swap off, timer apt offtemplate/Prepare-LinuxBuild2404.ps1— SCP script, esegue via SSH, valida, snapshotBaseClean-Linux
-
Invoke-CIJob.ps1 — branch Linux
- Parametro
-GuestOS(Windows/Linux/Auto) con auto-detect dal VMXguestOSfield - Transport SSH via
scripts/_Transport.psm1(Invoke-SshCommand, Copy-SshItem, Test-SshReady) - Phase 4/5/6 branch su GuestOS: SSH per Linux, WinRM per Windows (nessuna regressione)
- Parametro
-
Workflow Gitea — build matrix
- Label
linux-build:hostaggiunto arunner/config.yaml GITEA_CI_LINUX_TEMPLATE_PATHeGITEA_CI_SSH_KEY_PATHaggiunti alle env vars del runner- Matrix strategy cross-platform (windows + linux) documentata in
gitea/workflow-example.yml
- Label
-
Doc updates
docs/ARCHITECTURE.md— SSH transport, _Transport.psm1, Linux VM boxes, topology SSH :22docs/CI-FLOW.md— Step 0: Linux template + SSH key; Step 6 SSH transport note; Steps 7-8 Linux branchdocs/HOST-SETUP.md— directory layout: keys\ + LinuxBuild2404; SSH key gen step; Reference Paths Linuxdocs/LINUX-TEMPLATE-SETUP.md— Status: implementato; tutte le checkbox Fasi A-E marcate [x]
-
Test e2e Linux — COMPLETATO 2026-05-11 — Test-Ns7zipBuild-Linux.ps1 4× PASS
- Confermare che la build di esempio funzioni su Linux — nsis7z.dll 2272 KB prodotto
- Confrontare artifact Linux con quelli Windows — 2272 KB su entrambe le piattaforme
Deferred (Home Lab)
Nel contesto di un home lab isolato, i seguenti security task hanno costi eccessivi relativi ai benefici in questo ambiente. Rifiori se le condizioni cambiano (code non fidata, sharing host, esposizione di rete, etc.).
1.2 [P1] [ ] Audit TrustedHosts setting
File: docs/BEST-PRACTICES.md:§2.
Verificare che host Windows abbia WSMan:\localhost\Client\TrustedHosts configurato
per 192.168.79.* instead of *. Attualmente impostato a * durante setup template.
Stato attuale: Accettabile per lab — WinRM è isolato su VMnet8 NAT. Rifiori se: Host esposto a LAN / internet.
1.3 [P0] [ ] Pinning hash SHA256 degli installer
File: template/Setup-WinBuild2025.ps1.
SHA256 hash per dotnet-install.ps1, Python installer, vs_buildtools.exe.
Stato attuale: Struttura aggiunta, valori placeholder — funziona con warning. Rifiori quando: Build di codice di terze parti non fidate che scaricano installer.
1.5 [P1] [ ] PAT mai persistito per -UseGitClone
File: sezione "In-VM Git Clone (Ottimizzazione)" in TODO.
Vincoli: PAT da Credential Manager subito prima sessione, non in argv/log, cancellato in finally, grep post-job se compare in transcript.
Stato attuale: Struttura documentata, non implementata.
Rifiori quando: -UseGitClone implementato (§3.3).
1.7 [P2] [ ] Rotazione password guest VM
Aggiornare BuildVMGuest in Credential Manager + nel template ogni trimestre.
Stato attuale: Password manuale. Rifiori quando: Change management/compliance lo richiede.
1.8 [P2] [ ] Verifica Get-StoredCredential
Confermare che Get-StoredCredential (CredentialManager module) funzioni
in tutti gli script che lo usano post-migrazione HTTPS.
Stato attuale: Usato in template ma non testato in unit test. Rifiori quando: Script fallisce su recovery da Credential Manager.
3.4 [P3] [ ] Pre-warm pool di cloni
File: F:\CI\WarmPool\ (hypothetical); scheduled task via scripts/Register-CIScheduledTasks.ps1.
Mantenere 2 cloni avviati in background, pronti per il binding a job. Salta la fase di
New-BuildVM + Wait-VMReady (~30-60s) nel percorso critico. Richiede una VM "watcher" che
monitora il pool e ricrea cloni dopo uso.
Stato attuale: Disegnato ma non implementato. Dipende da §2.1 (IP allocator). Rifiori quando: Profiling mostra che New-BuildVM+Wait-VMReady è bottleneck >30% nel tempo totale di job. Con build >2 minuti, overhead stimato ~40% (rilevante solo per 1-min builds).
3.5 [P2] [ ] vCPU/RAM tuning per workload
File: docs/OPTIMIZATION.md, VMX template config.
Esporre parametri -VMCpu / -VMMemory a Invoke-CIJob.ps1 per permettere override
da workflow. Attualmente fisso a numvcpus=4, memsize=6144 — subottimo per build leggeri
(waste) e pesanti (throttle).
Stato attuale: Progettato, non implementato. Template supporta la modifica. Rifiori quando: Performance profiling mostra contentione CPU/RAM è bottleneck per la workload target. Per home lab, 4 vCPU/6 GB è ragionevole compromesso.
Suggerimento di sequencing
Sprint progressivi per ridurre rischio / ottenere valore prima:
- Sprint 1 (sicurezza) — §1.1, §1.2, §1.3, §1.4 — superficie di attacco e bug noti.
- Sprint 2 (operatività) — §2.1, §2.2, §2.3, §2.5 — rendere il sistema "fire and forget".
- Sprint 3 (osservabilità) — §4.1, §4.3, §4.4 — visibilità prima di estendere.
- Sprint 4 (perf) — §3.1, §3.2 misurati su un repo reale (baseline §3.6).
- Sprint 5 (qualità) — §5.1, §5.2 — rifattorizzazione con safety net di test.
- Sprint 6+ (estensioni) — Linux VM, workflow generico/composite action, federation.
Tenere ogni sprint piccolo: 1-2 voci alla volta, validare e2e dopo ognuna prima di passare alla successiva.
Reference Paths
| Item | Path / Value |
|---|---|
| vmrun.exe | C:\Program Files (x86)\VMware\VMware Workstation\vmrun.exe |
| act_runner | F:\CI\act_runner\act_runner.exe (servizio: act_runner) |
| act_runner config | F:\CI\act_runner\config.yaml |
| act_runner logs | F:\CI\act_runner\logs\ |
| Template VMX | F:\CI\Templates\WinBuild2025\WinBuild2025.vmx |
| 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 |