diff --git a/docs/LINUX-TEMPLATE-SETUP.md b/docs/LINUX-TEMPLATE-SETUP.md index 93eab1f..282562b 100644 --- a/docs/LINUX-TEMPLATE-SETUP.md +++ b/docs/LINUX-TEMPLATE-SETUP.md @@ -1,346 +1,389 @@ -# Linux Template VM Setup — DRAFT / TODO +# Linux Template VM Setup Piano di implementazione -> **Status**: bozza. Non implementato. Vedi [TODO.md §6.1](../TODO.md) (P2). -> Documento di pianificazione per estendere il sistema CI con build su Linux, -> in parallelo al template Windows già operativo. +> **Status**: pianificato non ancora implementato. Vedi [TODO.md §6.1](../TODO.md) (P2). +> Distro scelta: **Ubuntu 24.04 LTS** (cloud image, cloud-init). Approccio simmetrico a Windows. --- -## Obiettivo +## Architettura: tre script + modulo transport -Aggiungere supporto a build su Linux per: -- Compilazione cross-platform (es. versione Linux di plugin C/C++, build check con GCC/Clang) -- Test su distro Linux per progetti che lo richiedono -- Build matrix `[windows, linux]` nei workflow Gitea +| Script / Modulo | Dove gira | Ruolo | +| --------------------------------------- | -------------- | ----------------------------------------------------------------- | +| `template/Deploy-LinuxBuild2404.ps1` | **Host** (PS) | Crea VM da cloud image VMDK, genera seed ISO cloud-init, avvia, aspetta SSH | +| `template/Prepare-LinuxBuild2404.ps1` | **Host** (PS) | Copia + esegue setup via SSH, valida stato, prende snapshot | +| `template/Setup-LinuxBuild2404.sh` | **Guest** (Bash) | Installa toolchain CI, dirs, hardening, gate finale | +| `scripts/_Transport.psm1` | **Host** (PS) | Interfaccia comune WinRM/SSH per Invoke-CIJob e script CI | -Architettura simmetrica al template Windows: VM template → snapshot `BaseClean-Linux` → -linked clone per ogni job → cleanup automatico. +Perche tre script separati (non tutto-in-uno): cloud-init copre solo il bootstrap OS +(utente, SSH key, pacchetti base). Il toolchain CI e le validazioni per step sono piu +leggibili e manutenibili in un secondo script dedicato identico alla divisione +Deploy/Setup/Prepare di Windows. --- -## Decisioni di design (da validare) +## Specifiche VM -### Distro +| Parametro | Valore | +| ------------- | --------------------------------------------------- | +| OS | Ubuntu 24.04 LTS (cloud image, non ISO installer) | +| Immagine base | `ubuntu-24.04-server-cloudimg-amd64.vmdk` | +| Download | `https://cloud-images.ubuntu.com/noble/current/` | +| vCPU | 4 | +| RAM | 4096 MB | +| Disco | 40 GB thin (resize del cloud VMDK) | +| NIC | VMnet8 (NAT) vmxnet3 diretto (driver nativo kernel) | +| VMX path | `F:\CI\Templates\LinuxBuild2404\LinuxBuild2404.vmx` | +| Snapshot name | `BaseClean-Linux` | -| Opzione | Pro | Contro | -| ------------------------ | ------------------------------------------------------------------ | -------------------------------------------- | -| **Ubuntu 24.04 LTS** | Toolchain recente, supporto LTS fino al 2029, cloud-init ottimo | Snap default (lento per CI) | -| Debian 12 | Stabile, leggero, no snap | Toolchain meno recente | -| Rocky Linux 9 / Alma 9 | RHEL-compat, glibc moderno, dnf | Meno comune in workflow CI tipici | - -**Scelta proposta**: Ubuntu 24.04 LTS minimal. Rationale: maggior parità con runner GitHub -ufficiali (`ubuntu-latest` mappa a 22.04/24.04), toolchain recente out-of-box, cloud-init -maturo per provisioning automatico. - -### Transport host → VM - -| Opzione | Pro | Contro | -| ------------------------ | ------------------------------------------------------------------ | -------------------------------------------- | -| **SSH (chiave pubblica)**| Standard Linux, supporto nativo OpenSSH su Win11/Server 2025 | Diversa API rispetto WinRM (PSSession) | -| WinRM su Linux (PSCore) | Codice script unificato | Setup complesso, non standard, fragile | - -**Scelta proposta**: SSH key-based con `ssh.exe` + `scp.exe` (built-in Windows 10+) o -modulo `Posh-SSH`. WinRM su Linux non è production-ready. - -### Layer di astrazione - -Aggiungere `scripts/_Transport.psm1` con interfaccia comune: - -```powershell -# Pseudo-API -function Invoke-RemoteCommand { - param($Target, $ScriptBlock, $Args, [ValidateSet('WinRM','SSH')] $Transport) -} -function Copy-RemoteItem { - param($Source, $Destination, $Target, $Direction, $Transport) -} -function Test-RemoteReady { - param($Target, $TimeoutSec, $Transport) -} -``` - -Implementazioni: -- **WinRM** wrapper: `New-PSSession` + `Invoke-Command` + `Copy-Item -ToSession` -- **SSH** wrapper: `ssh.exe` + `scp.exe` con `-i $keyfile -o StrictHostKeyChecking=accept-new` - -`Invoke-CIJob.ps1` riceve `-GuestOS Windows|Linux` (o auto-detect dal VMX `guestOS`), -sceglie transport. +Differenza chiave da Windows: l'immagine di partenza e gia installata (cloud VMDK, +~600 MB). Nessuna fase di installazione OS cloud-init provvede al bootstrap al primo +boot in 30-60 secondi. La NIC non richiede lo swap e1000e vmxnet3 perche il kernel +Linux ha il driver vmxnet3 nativo. --- -## Specifiche VM proposte +## Prerequisiti host -| Parametro | Valore | -| ----------------------- | --------------------------------------------------------------- | -| OS | Ubuntu Server 24.04 LTS minimal | -| vCPU | 4 | -| RAM | 4096 MB (4 GB) — meno di Windows, footprint Linux più snello | -| Disco | 40 GB thin | -| NIC | VMnet8 (NAT) — internet per `apt` | -| VMX path | `F:\CI\Templates\LinuxBuild\LinuxBuild.vmx` | -| ISO | `ubuntu-24.04.x-live-server-amd64.iso` (in `F:\CI\ISO\`) | -| Snapshot name | `BaseClean-Linux` | +- [ ] **SSH key CI dedicata** generare una volta sola (no passphrase): + ```powershell + New-Item -ItemType Directory -Force F:\CI\keys | Out-Null + ssh-keygen -t ed25519 -f F:\CI\keys\ci_linux -N '""' -C 'ci-linux-runner' + # Risultato: F:\CI\keys\ci_linux (privata) + F:\CI\keys\ci_linux.pub (pubblica) + ``` +- [ ] **OpenSSH client** verificato presente sull'host (default su Windows 11): + ```powershell + Get-WindowsCapability -Online -Name OpenSSH.Client* | Select-Object State + # Atteso: State = Installed + ``` +- [ ] **Download cloud image VMDK** in `F:\CI\ISO\`: + ``` + https://cloud-images.ubuntu.com/noble/current/ubuntu-24.04-server-cloudimg-amd64.vmdk + ``` +- [ ] **`F:\CI\Templates\LinuxBuild2404\`** creata (Setup-Host.ps1 o manuale) --- -## TODO — Implementazione +## Fase A Deploy-LinuxBuild2404.ps1 -### Pre-requisiti host +Script host-side. Produce una VM pronta con cloud-init completato e SSH raggiungibile. +Non richiede installazione OS parte dal cloud VMDK pre-built. -- [ ] **OpenSSH client** verificato presente su host (default Win11/Server 2025) - ```powershell - Get-WindowsCapability -Online -Name OpenSSH.Client* - ``` -- [ ] **Genera SSH key dedicata** per CI (no passphrase, separata da chiavi utente): - ```powershell - ssh-keygen -t ed25519 -f F:\CI\keys\ci_linux -N '""' -C 'ci-linux-runner' - ``` -- [ ] **Aggiungere a `Setup-Host.ps1`** uno step opzionale `-GenerateLinuxCIKey` che crea - la chiave e la archivia con permessi corretti (`F:\CI\keys\` con ACL ristretta) +- [ ] **Step 1 Validate prerequisites** + - `vmrun.exe` presente nel path atteso + - Cloud image VMDK sorgente presente in `F:\CI\ISO\` + - SSH key `F:\CI\keys\ci_linux.pub` presente + - Cartella destinazione VMX non gia occupata (o `-Force` per sovrascrivere) -### Fase A — Crea VM e installa Ubuntu +- [ ] **Step 2 Genera cloud-init user-data + meta-data** (inline, no template esterno) + - `meta-data`: `instance-id: linuxbuild-001`, `local-hostname: ci-linux-template` + - `user-data` (YAML): + - `hostname: ci-linux-template`, `timezone: Europe/Rome` + - `users`: utente `ci_build`, shell `/bin/bash`, `sudo: ALL=(ALL) NOPASSWD:ALL`, + `ssh_authorized_keys` con contenuto di `ci_linux.pub` + - `packages`: `[openssh-server, curl, ca-certificates, p7zip-full]` + - `package_update: true` + - `runcmd`: `swapoff -a`, commenta swap in `/etc/fstab`, + `sed PasswordAuthentication no` in sshd_config, `systemctl restart sshd` + - `power_state`: `mode: reboot` dopo primo provisioning -- [ ] Crea nuova VM in VMware Workstation (4 vCPU, 4 GB RAM, 40 GB thin) -- [ ] NIC: VMnet8 (NAT) -- [ ] Boot da ISO Ubuntu Server 24.04 LTS minimal -- [ ] Durante install scegli: - - [ ] **Minimal install** (no extra packages) - - [ ] OpenSSH server: **Yes** - - [ ] Username: `ci_build` - - [ ] Hostname: `ci-linux-template` - - [ ] LVM: opzionale (non necessario per template) -- [ ] Annota IP DHCP (`ip a`) +- [ ] **Step 3 Costruisce seed ISO nocloud** via IMAPI2FS COM + - Due file: `user-data` + `meta-data` (volume label: `cidata`) + - Stesso codice COM gia usato in Deploy-WinBuild2025.ps1 Step 3 + - Output: `F:\CI\Templates\LinuxBuild2404\cloud-init-seed.iso` -### Fase B — Provisioning iniziale (manuale, una volta) +- [ ] **Step 4 Copia e ridimensiona cloud VMDK** + - Copia `ubuntu-24.04-server-cloudimg-amd64.vmdk` `LinuxBuild2404.vmdk` + - Ridimensiona a 40 GB: `vmware-vdiskmanager -x 40GB LinuxBuild2404.vmdk` -Dentro la VM, come `ci_build`: +- [ ] **Step 5 Genera .vmx** + - `guestOS = "ubuntu-64"`, BIOS (cloud image Ubuntu compatibile entrambi; + BIOS piu semplice per lab) + - NIC: `vmxnet3`, VMnet8 + - Disco: `LinuxBuild2404.vmdk` (scsi0:0) + - CD-ROM secondario: `cloud-init-seed.iso` (connesso) + - Nessun USB controller, nessuna sound card + - `memsize = 4096`, `numvcpus = 4` -- [ ] **Disabilita swap permanente** (overhead I/O su NVMe condivisa): - ```bash - sudo swapoff -a - sudo sed -i '/ swap / s/^/#/' /etc/fstab +- [ ] **Step 6 Power on** (`vmrun start nogui`) + +- [ ] **Step 7 Polling SSH port 22** fino a ready + - `Test-NetConnection -ComputerName $IP -Port 22` ogni 10 secondi + - Timeout: 5 minuti (cloud-init + reboot finale) + - IP rilevato via `vmrun getGuestIPAddress` + + > open-vm-tools e pre-installato nell'Ubuntu 24.04 cloud image. + > `vmrun getGuestIPAddress` funziona senza installazione aggiuntiva. + +- [ ] **Step 8 Verifica cloud-init completato** + ```powershell + ssh -i F:\CI\keys\ci_linux -o StrictHostKeyChecking=accept-new ` + -o ConnectTimeout=5 ci_build@$IP ` + "test -f /var/lib/cloud/instance/boot-finished && echo OK" + # Atteso: OK ``` -- [ ] **Disabilita servizi non necessari** (snap, motd-news, ecc.): - ```bash - sudo systemctl disable --now snapd.service snapd.socket snapd.seeded.service 2>/dev/null - sudo systemctl disable --now motd-news.timer 2>/dev/null - sudo systemctl disable --now apt-daily.timer apt-daily-upgrade.timer - ``` - Rationale: snap e timer apt rallentano boot e mangiano CPU su VM efimere. +- [ ] **Step 9 Rimuove seed ISO dal VMX** + - Setta `ide1:0.present = "FALSE"` nel VMX + - Evita che linked clone ricevano il seed ISO e ri-eseguano cloud-init -- [ ] **Sudo passwordless** per `ci_build` (parità con WinRM admin senza prompt UAC): - ```bash - echo 'ci_build ALL=(ALL) NOPASSWD:ALL' | sudo tee /etc/sudoers.d/90-ci_build - sudo chmod 440 /etc/sudoers.d/90-ci_build +- [ ] **Step 10 Print summary** (VMX path, IP, SSH fingerprint) + +--- + +## Fase B Prepare-LinuxBuild2404.ps1 + +Script host-side. Copia il setup script, lo esegue via SSH, valida stato, prende snapshot. +Equivalente di `Prepare-WinBuild2025.ps1` con SSH al posto di WinRM. + +- [ ] **Step 1 Pre-flight** + - VMX presente; se VM spenta, avvia con `vmrun start nogui` + - SSH key `F:\CI\keys\ci_linux` presente + - `ssh.exe` e `scp.exe` nel PATH host + - TCP/22 raggiungibile (`Test-NetConnection`) + +- [ ] **Step 2 Auto-detect IP** via `vmrun getGuestIPAddress $VMXPath` + - Se `-VMIPAddress` e fornito esplicitamente, salta il rilevamento automatico + +- [ ] **Step 3 Aggiungi host key a known_hosts** + ```powershell + ssh -i F:\CI\keys\ci_linux -o StrictHostKeyChecking=accept-new ` + ci_build@$IP "echo connected" | Out-Null + ``` + Solo al primo run; idempotente se gia presente. + +- [ ] **Step 4 Copia Setup-LinuxBuild2404.sh in VM** + ```powershell + scp -i F:\CI\keys\ci_linux ` + "$PSScriptRoot\Setup-LinuxBuild2404.sh" ` + "ci_build@${IP}:/tmp/Setup-LinuxBuild2404.sh" + ``` + Valida: confronta size locale vs remota via `ssh ... stat -c %s /tmp/...` + +- [ ] **Step 5 Esegui setup script** nel guest + ```powershell + ssh -i F:\CI\keys\ci_linux ci_build@$IP ` + "chmod +x /tmp/Setup-LinuxBuild2404.sh && sudo /tmp/Setup-LinuxBuild2404.sh" + # Cattura exit code; != 0 => abort con errore leggibile + ``` + Flag opzionali passabili: `--skip-update`, `--dotnet`, `--mingw` + +- [ ] **Step 6 Post-setup remote validation** (batch via singola sessione SSH) + - `systemctl is-active ssh` = `active` + - `id ci_build` contiene `sudo` + - `sudo -n true` exit 0 (passwordless sudo) + - `which gcc g++ clang cmake python3 git 7z` tutti trovati + - `test -d /opt/ci/build -a -d /opt/ci/output -a -d /opt/ci/scripts` exit 0 + - `swapon --show` output vuoto (swap disabilitato) + - `grep -q "^PasswordAuthentication no" /etc/ssh/sshd_config` + +- [ ] **Step 7 Shutdown VM** + ```powershell + & $vmrun stop $VMXPath soft + # Polling vmrun list fino a VM non piu presente ``` -- [ ] **Authorized SSH key** dell'host CI: - ```bash - mkdir -p ~/.ssh && chmod 700 ~/.ssh - # Incolla la chiave pubblica generata su host (F:\CI\keys\ci_linux.pub) - echo 'ssh-ed25519 AAAA... ci-linux-runner' >> ~/.ssh/authorized_keys - chmod 600 ~/.ssh/authorized_keys +- [ ] **Step 8 Snapshot BaseClean-Linux** + ```powershell + & $vmrun snapshot $VMXPath 'BaseClean-Linux' ``` -- [ ] **SSH hardening** per template (ma non così stretto da bloccare CI): - ```bash - sudo sed -i 's/^#*PermitRootLogin.*/PermitRootLogin no/' /etc/ssh/sshd_config - sudo sed -i 's/^#*PasswordAuthentication.*/PasswordAuthentication no/' /etc/ssh/sshd_config - sudo systemctl restart sshd - ``` +- [ ] **Final Print summary** (VMX, snapshot name, toolchain versions rilevate) -### Fase C — Setup-LinuxTemplateVM.sh (script equivalente a Setup-WinBuild2025.ps1) +--- -Da creare: `template/Setup-LinuxTemplateVM.sh` con `set -euo pipefail` + `assert_step()` helper. +## Fase C Setup-LinuxBuild2404.sh -- [ ] **Helper `assert_step`** (throw on fail, log su success): - ```bash - assert_step() { - local step="$1"; local desc="$2"; shift 2 - if "$@" >/dev/null 2>&1; then - echo " [OK] [$step] $desc" - else - echo " [FAIL] [$step] $desc" >&2; exit 1 - fi - } - ``` +Script guest-side (Bash). Installazione toolchain CI e hardening. +Eseguito da Prepare via SSH come `ci_build` con sudo. -- [ ] **Step 1 — `apt update` + upgrade** +Header: `#!/usr/bin/env bash` + `set -euo pipefail` +Helper `assert_step()`: stampa `[OK] [Step N] desc` su successo, `exit 1` su fallimento. + +- [ ] **Step 1 apt update + upgrade** (saltabile con `--skip-update`) ```bash sudo DEBIAN_FRONTEND=noninteractive apt-get update -qq sudo DEBIAN_FRONTEND=noninteractive apt-get upgrade -y -qq - assert_step 'apt' 'no errors' true ``` -- [ ] **Step 2 — Toolchain build essentials** +- [ ] **Step 2 Toolchain build essentials** ```bash sudo apt-get install -y -qq \ build-essential gcc g++ clang \ make cmake ninja-build \ - pkg-config autoconf automake libtool \ - git curl wget ca-certificates \ - python3 python3-pip python3-venv \ - unzip zip xz-utils - assert_step 'toolchain' 'gcc presente' command -v gcc - assert_step 'toolchain' 'clang presente' command -v clang - assert_step 'toolchain' 'cmake presente' command -v cmake - assert_step 'toolchain' 'python3 presente' command -v python3 + pkg-config autoconf automake libtool ``` + - assert: `command -v gcc`, `command -v clang`, `command -v cmake` -- [ ] **Step 3 — Toolchain extra opzionale** - - [ ] **mingw-w64** se serve cross-compile per Windows: `sudo apt-get install -y mingw-w64` - - [ ] **.NET SDK** (per parità Windows): script `dotnet-install.sh` con channel pinned - - [ ] **Node.js** se workflow lo richiede: nvm o nodesource repo +- [ ] **Step 3 Python** + ```bash + sudo apt-get install -y -qq python3 python3-pip python3-venv + sudo ln -sf /usr/bin/python3 /usr/local/bin/python + ``` + - assert: `python3 --version`, `pip3 --version` -- [ ] **Step 4 — CI working directories** +- [ ] **Step 4 Tier-1 Toolchain** (speculare a §6.6 Windows: Git + 7-Zip) + ```bash + sudo apt-get install -y -qq git p7zip-full curl wget ca-certificates + ``` + - assert: `command -v git`, `command -v 7z` + +- [ ] **Step 4b .NET SDK** (opzionale, flag `--dotnet`) + ```bash + curl -fsSL https://dotnet.microsoft.com/download/dotnet/scripts/v1/dotnet-install.sh \ + | sudo bash -s -- --channel 10.0 --install-dir /usr/local/dotnet + sudo ln -sf /usr/local/dotnet/dotnet /usr/local/bin/dotnet + ``` + - assert: `dotnet --version` + +- [ ] **Step 4c mingw-w64** (opzionale, flag `--mingw` cross-compile per Windows) + ```bash + sudo apt-get install -y -qq mingw-w64 + ``` + - assert: `command -v x86_64-w64-mingw32-gcc` + +- [ ] **Step 5 CI directories** ```bash sudo mkdir -p /opt/ci/{build,output,scripts,cache} sudo chown -R ci_build:ci_build /opt/ci - assert_step 'dirs' 'tutte presenti' test -d /opt/ci/build -a -d /opt/ci/output ``` + - assert: `test -d /opt/ci/build`, `test -d /opt/ci/output`, `test -d /opt/ci/scripts` -- [ ] **Step 5 — Disabilita auto-update apt** (no surprise reboot/lock): +- [ ] **Step 6 SSH hardening** (PasswordAuth off gia impostato da cloud-init, ri-validato) ```bash - sudo apt-get remove -y unattended-upgrades 2>/dev/null - sudo systemctl mask apt-daily.service apt-daily-upgrade.service + sudo sed -i 's/^#*PasswordAuthentication.*/PasswordAuthentication no/' /etc/ssh/sshd_config + sudo sed -i 's/^#*PubkeyAuthentication.*/PubkeyAuthentication yes/' /etc/ssh/sshd_config + sudo systemctl restart sshd + ``` + - assert: `grep -q "^PasswordAuthentication no" /etc/ssh/sshd_config` + +- [ ] **Step 7 Disabilita swap permanente** + ```bash + sudo swapoff -a + sudo sed -i '/ swap / s/^/#/' /etc/fstab + ``` + - assert: `swapon --show` output vuoto + +- [ ] **Step 8 Disabilita apt auto-update** (no lock durante build) + ```bash + sudo systemctl mask apt-daily.service apt-daily-upgrade.service \ + apt-daily.timer apt-daily-upgrade.timer + sudo apt-get remove -y unattended-upgrades 2>/dev/null || true ``` -- [ ] **Step 6 — Cleanup pre-snapshot** +- [ ] **Step 9 Cleanup pre-snapshot** ```bash sudo apt-get clean sudo rm -rf /var/lib/apt/lists/* sudo journalctl --vacuum-time=1d sudo rm -rf /tmp/* /var/tmp/* - history -c && cat /dev/null > ~/.bash_history - # Zero free space (riduce dim VMDK dopo compact, opzionale) - # sudo dd if=/dev/zero of=/zero bs=1M; sudo rm /zero + history -c + cat /dev/null > ~/.bash_history ``` -- [ ] **Step 7 — Final pre-snapshot validation** - - SSH server abilitato e in ascolto su 22 - - `sudo` passwordless funzionante per `ci_build` - - Tutti i tool elencati (`gcc --version`, `cmake --version`, ecc.) ritornano exit 0 - - `/opt/ci/{build,output,scripts}` esistono con owner corretto - - No leftover `/tmp/*`, history vuota +- [ ] **Final Gate pre-snapshot** (exit 1 se qualcosa manca) + - Ogni tool richiesto raggiungibile con `command -v` + - `/opt/ci/{build,output,scripts}` esistenti con owner `ci_build` + - `swapon --show` vuoto + - `sshd` attivo + - `PasswordAuthentication no` in sshd_config + - Nessun installer residuo in `/tmp` -### Fase D — Prepare-LinuxTemplateSetup.ps1 (orchestratore host-side) +--- -Equivalente di `Prepare-WinBuild2025.ps1` per Linux. Usa SSH invece di WinRM. +## Fase D Adattamento script CI -- [ ] **Pre-flight host**: - - SSH key esiste (`F:\CI\keys\ci_linux`) - - `ssh.exe` e `scp.exe` raggiungibili - - IP target risponde a `Test-NetConnection -Port 22` - -- [ ] **Copia script in VM**: +- [ ] **`scripts/_Transport.psm1`** nuovo modulo con interfaccia comune WinRM/SSH: ```powershell - scp -i F:\CI\keys\ci_linux -o StrictHostKeyChecking=accept-new ` - template\Setup-LinuxTemplateVM.sh ci_build@${VMIPAddress}:/tmp/ + function Invoke-RemoteCommand { param($Target, $Command, [ValidateSet('WinRM','SSH')] $Transport, ...) } + function Copy-RemoteItem { param($Source, $Dest, $Target, $Direction, $Transport, ...) } + function Test-RemoteReady { param($Target, $TimeoutSec, $Transport, ...) } ``` -- [ ] **Esegui script in VM**: - ```powershell - ssh -i F:\CI\keys\ci_linux ci_build@${VMIPAddress} ` - "chmod +x /tmp/Setup-LinuxTemplateVM.sh && sudo /tmp/Setup-LinuxTemplateVM.sh" - ``` - Cattura stdout + exit code, parse `[OK]`/`[FAIL]` lines. +- [ ] **`scripts/Invoke-CIJob.ps1`** aggiungere parametro `-GuestOS Windows|Linux` + - Auto-detect da VMX `guestOS` field se non fornito + - Branch su transport (WinRM vs SSH) in ogni fase -- [ ] **Post-setup remote validation** (parità Windows): query SSH per state checks: - - `systemctl is-active ssh` = active - - `id ci_build` ritorna gruppo + sudo - - `gcc --version`, `cmake --version`, `python3 --version` exit 0 - - `test -d /opt/ci/build` exit 0 +- [ ] **`scripts/Wait-VMReady.ps1`** aggiungere `-Transport SSH` + - Probe: `Test-NetConnection -Port 22` + `ssh -o ConnectTimeout=5 ... "echo ok"` -### Fase E — Snapshot +- [ ] **`scripts/Invoke-RemoteBuild.ps1`** branch SSH+scp per Linux + - Transfer: `scp` invece di `Copy-Item -ToSession` + - Build: `ssh ... "cd /opt/ci/build && $BuildCommand"` -- [ ] Solo se Prepare exit 0 → power off VM: - ```bash - sudo shutdown -h now - ``` -- [ ] Take snapshot in VMware Workstation: **`BaseClean-Linux`** (case-sensitive) +- [ ] **`scripts/Get-BuildArtifacts.ps1`** branch `scp` per Linux + - `scp -r ci_build@$IP:/opt/ci/output/* $LocalArtifactDir\` -### Fase F — Adattamento script CI +- [ ] **`scripts/New-BuildVM.ps1`** gia OS-agnostic (vmrun clone) + - Verificare che `-SnapshotName BaseClean-Linux` funzioni correttamente -- [ ] **`scripts/_Transport.psm1`** (nuovo modulo) con interfaccia comune -- [ ] **`scripts/Invoke-CIJob.ps1`** — aggiungere `-GuestOS Windows|Linux`, branching su transport -- [ ] **`scripts/Wait-VMReady.ps1`** — supporto SSH probe (`Test-NetConnection -Port 22` + `ssh -o ConnectTimeout=5 ...`) -- [ ] **`scripts/Invoke-RemoteBuild.ps1`** — branch SSH+scp per Linux -- [ ] **`scripts/Get-BuildArtifacts.ps1`** — `scp` per Linux invece di `Copy-Item -FromSession` -- [ ] **`scripts/New-BuildVM.ps1`** — already OS-agnostic (vmrun clone), verificare che `BaseClean-Linux` sia parametrizzabile -- [ ] **`scripts/Remove-BuildVM.ps1`** — already OS-agnostic +- [ ] **`scripts/Remove-BuildVM.ps1`** gia OS-agnostic, nessuna modifica prevista -### Fase G — Workflow Gitea +--- -- [ ] **Registrare label `linux-build`** sul runner (oppure secondo runner dedicato): +## Fase E Runner e workflow Gitea + +- [ ] **Label `linux-build`** aggiunta al runner in `runner/config.yaml`: ```yaml - # runner/config.yaml — aggiungere a labels esistenti labels: - 'windows-build:host' - 'linux-build:host' ``` -- [ ] **Workflow matrix**: +- [ ] **Variabile d'ambiente** `GITEA_CI_LINUX_TEMPLATE_PATH` nel servizio act_runner: + `F:\CI\Templates\LinuxBuild2404\LinuxBuild2404.vmx` + +- [ ] **Workflow matrix** di esempio (`gitea/workflow-example.yml` aggiornato): ```yaml - jobs: - build: - strategy: - matrix: - target: [windows, linux] - runs-on: ${{ matrix.target }}-build - steps: - - uses: actions/checkout@v4 - - run: pwsh -File scripts/Invoke-CIJob.ps1 -GuestOS ${{ matrix.target }} + strategy: + matrix: + target: [windows, linux] + runs-on: ${{ matrix.target }}-build ``` -### Fase H — Test e2e +--- -- [ ] **Smoke test** clone + SSH ready: +## Fase F Test e2e + +- [ ] **Smoke test** linked clone + SSH ready: ```powershell - .\scripts\New-BuildVM.ps1 -JobId 'linux-smoke' -SnapshotName 'BaseClean-Linux' - .\scripts\Wait-VMReady.ps1 -JobId 'linux-smoke' -Transport SSH - .\scripts\Remove-BuildVM.ps1 -JobId 'linux-smoke' + .\scripts\New-BuildVM.ps1 -JobId 'linux-smoke-001' ` + -TemplatePath 'F:\CI\Templates\LinuxBuild2404\LinuxBuild2404.vmx' ` + -SnapshotName 'BaseClean-Linux' ``` -- [ ] **Build reale**: scegliere repo con build Linux nativo (es. `cmake` based) e - eseguire job e2e via `Invoke-CIJob.ps1 -GuestOS Linux` +- [ ] **Build test** comando reale nella VM: + ```powershell + .\scripts\Invoke-CIJob.ps1 -JobId 'linux-e2e-001' -GuestOS Linux ` + -RepoUrl 'ssh://gitea-ci/Simone/.git' -Branch 'main' ` + -TemplatePath 'F:\CI\Templates\LinuxBuild2404\LinuxBuild2404.vmx' ` + -BuildCommand 'make -C /opt/ci/build all' ` + -GuestArtifactSource '/opt/ci/output' + ``` -- [ ] **Confronto artifact**: build dello stesso repo target Windows vs Linux, - verifica che entrambi vengano raccolti in `F:\CI\Artifacts\\` +- [ ] **Cleanup** linked clone rimosso dopo build (`Remove-BuildVM.ps1`) +- [ ] **Matrix build** run parallela Windows + Linux sullo stesso push --- -## Differenze chiave rispetto al template Windows +## Differenze da Windows riepilogo -| Aspetto | Windows | Linux | -| ----------------------- | -------------------------------------- | ------------------------------------------- | -| Transport | WinRM HTTPS/5986 + Basic (-SkipCACheck) | SSH/22 + ed25519 key | -| Auth fluid | `ci_build` admin + UAC off + LATFP=1 | `ci_build` + sudoers NOPASSWD | -| Trasferimento file | `Copy-Item -ToSession` | `scp` o `rsync` | -| Esecuzione remota | `Invoke-Command -Session` | `ssh user@host 'cmd'` | -| AV/Firewall disable | Defender + Win Firewall off | ufw inattivo (default), no AV | -| Update package | Windows Update (COM API + sched task) | `apt-get update && upgrade` non-interactive | -| Toolchain | VS Build Tools 2026 + .NET SDK | gcc/g++/clang + cmake (+ .NET SDK opt) | -| Snapshot name | `BaseClean` | `BaseClean-Linux` | -| Footprint VM | 6 GB RAM, 80 GB disk | 4 GB RAM, 40 GB disk | -| Boot time | ~30-60 s post-clone | ~10-20 s post-clone (atteso) | +| Aspetto | Windows | Linux | +| ------------------------ | -------------------------------------------- | --------------------------------------------- | +| Immagine di partenza | ISO installer (Deploy ~60-90 min unattended) | Cloud VMDK pre-built (boot + cloud-init ~60 s) | +| Provisioning unattended | `autounattend.xml` (Windows Setup) | cloud-init `user-data` (seed ISO nocloud) | +| Transport host VM | WinRM HTTPS/5986 + PSSession | `ssh.exe` + `scp.exe` (built-in Windows 11) | +| NIC strategia | e1000e install vmxnet3 swap post-Tools | vmxnet3 diretto (driver nativo kernel) | +| Setup script | `.ps1` (PowerShell, via WinRM) | `.sh` (Bash, via SSH) | +| Rilevamento IP | `vmrun getGuestIPAddress` (VMware Tools) | `vmrun getGuestIPAddress` (open-vm-tools) | +| Wait completamento | polling flag file via `vmrun copyFileFromGuestToHost` | polling SSH + `boot-finished` cloud-init | +| CI dirs | `C:\CI\{build,output,scripts}` | `/opt/ci/{build,output,scripts,cache}` | +| Snapshot name | `BaseClean` | `BaseClean-Linux` | --- -## Backlog correlato (TODO.md) +## Riferimenti -- **§6.1 [P2]** Linux Build VM — entry parent -- **§6.4 [P3]** Build matrix `[windows, linux]` nel workflow -- **§6.3 [P3]** Multi-host runner federation (se 4 VM Linux + 4 Windows non bastano) -- **§5.2 [P2]** Modulo `_Transport.psm1` condiviso (prerequisito architetturale) - ---- - -## Domande aperte - -1. **.NET SDK su Linux** — sempre installato o solo se workflow lo richiede? - Decisione: installare **se** workload richiede parità di build. Default off, opt-in via flag. -2. **Image size** — Ubuntu minimal + toolchain ≈ 5 GB. Compact post-snapshot per ridurre footprint VMDK? - Decisione: sì, `dd if=/dev/zero` + `vmware-vdiskmanager -k` (manuale, una tantum). -3. **Pre-warm pool Linux** — boot Linux è veloce, beneficio minore. Decisione: implementare solo se profile dimostra > 30% overhead. -4. **Cloud-init vs script manuale** — cloud-init richiede ISO seed o NoCloud datasource. Più pulito ma overhead di setup. Decisione: script bash diretto (parità con flusso Windows). Cloud-init valutabile in v2. +- [ARCHITECTURE.md](ARCHITECTURE.md) diagramma componenti (aggiornare dopo implementazione) +- [CI-FLOW.md](CI-FLOW.md) flusso pipeline (aggiornare Step 0 prerequisites) +- [HOST-SETUP.md](HOST-SETUP.md) Setup-Host.ps1 (aggiungere step generazione SSH key) +- [TODO.md §6.1](../TODO.md) tracking implementazione