Files
local-ci-cd-system/TODO.md
T
Simone f373c0c24b fix: apply all FIX-TODO items (P0/P1/P2)
P0 bugs:
- Invoke-CIJob.ps1: skip --depth 1 when $Commit specified (shallow clone
  + checkout specific commit was silently failing)
- Get-BuildArtifacts.ps1: check .Length -eq 0 not rounded sizeKB (false
  fail on artifacts smaller than 50 bytes)
- build-nsis.yml: upgrade upload-artifact v3 -> v4 (v3 deprecated)

P0 security:
- Remove hardcoded default password CIBuild!ChangeMe2026 from all scripts,
  README, TODO; prompt Read-Host -AsSecureString at runtime instead
- Setup-TemplateVM.ps1: replace `net user $u $p /add` (password in argv /
  audit log 4688) with New-LocalUser + local ConvertTo-SecureString
- Prepare-TemplateSetup.ps1: save and restore WSMan AllowUnencrypted +
  TrustedHosts in finally block (was permanently mutating host WinRM config)
- Setup-TemplateVM.ps1: remove duplicate MaxMemoryPerShellMB (winrm set
  + Set-Item both setting same value)

P1 doc (stale Host-Only / VMnet11 era):
- Setup-TemplateVM.ps1: rewrite NETWORK REQUIREMENT block + final steps
  (system uses VMnet8 NAT permanently, not VMnet11 Host-Only)
- Invoke-CIJob.ps1 Phase 1 comment: correct network model
- ARCHITECTURE.md: remove Git from toolchain list (not installed); clarify
  zip-transfer rationale (no PAT in VM, not network isolation)
- BEST-PRACTICES.md: rewrite Step 8 as NAT topology verification

P1 minor:
- Invoke-RemoteBuild.ps1: remove wasted first New-Item (created then
  immediately removed and recreated)
- Wait-VMReady.ps1: remove unused $elapsed; simplify try/catch around
  native command (exit codes don't throw)
- Install-Runner.ps1: add deprecation notice pointing to Setup-Host.ps1

P2 operational:
- Add scripts/Cleanup-OrphanedBuildVMs.ps1 with -WhatIf support
- Get-BuildArtifacts.ps1 -IncludeLogs: add -Recurse (msbuild logs in subdir)
- Add gitea/workflows/lint.yml (PSScriptAnalyzer on .ps1 push/PR)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-09 00:39:52 +02:00

13 KiB

TODO — Local CI/CD System

Setup & Infrastructure

  • Gitea Server — già in esecuzione su http://10.10.20.11:3100 (e https://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 in gitea/workflows/build-nsis.yml)
    • Gitea Actions abilitato (runner registrato con successo)
  • act_runner — installato e registrato sull'host Windows

    • Binario gitea-runner v1.0.2 scaricato in F:\CI\act_runner\act_runner.exe
    • Registrato con Gitea (http://10.10.20.11:3100) — runner ID 1, nome local-windows-runner
    • config.yaml copiato in F:\CI\act_runner\config.yaml con label windows-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
  • 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\WinBuild\
    • F:\CI\ISO\ — contiene 26100.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\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
    • Installa Windows Server 2025 dall'ISO
    • 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
    • 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 <IP_KMS> 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
    • Nota l'IP assegnato dal DHCP di VMnet8 (es. 192.168.79.x) — ipconfig nella VM

    Fase B — Provisioning automatico dall'host

    • 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.
    • Setup completato con successo (VS Build Tools 2026 exit code 0).

    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: BaseClean
    • 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_PATH in F:\CI\act_runner\config.yaml — aggiornato a CI-WinBuild.vmx (2026-05-08)

Scripts Verification

  • Test New-BuildVM.ps1 standalone — clone Clone_test-002 creato correttamente (2026-05-08)
  • Test Wait-VMReady.ps1 standalone — 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.ps1 end-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)

Runner Configuration

  • runner/config.yaml aggiornato con percorsi F:\CI\, rete VMnet8 (NAT), label corretti
  • capacity: 4 configurato (64 GB RAM / ~8 GB per VM)
  • Aggiornare GITEA_CI_TEMPLATE_PATH in config.yaml dopo creazione template VM
  • Archiviare credenziali guest in Windows Credential Manager (target: BuildVMGuest)

Gitea Workflow Integration

  • 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)
  • Push commit e verificare job in Gitea Actions UI
  • Verificare artifact scaricabile da Gitea dopo build riuscita
  • Adattare workflow per altri repository (generalizzare BUILD_COMMAND e ARTIFACT_SOURCE)

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)

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.

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-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)

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
    • 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
  • 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-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
    • 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')
  • Test e2e con -UseGitClone

    • 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

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

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)
  • Rotazione password guest VM trimestralmente

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\WinBuild\CI-WinBuild.vmx
Snapshot name BaseClean
Clone base dir F:\CI\BuildVMs\
Artifact dir F:\CI\Artifacts\
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