refactor(template): rename Setup-TemplateVM.ps1 -> Setup-WinBuild2025.ps1

- git mv Setup-TemplateVM.ps1 Setup-WinBuild2025.ps1
- git mv Prepare-TemplateSetup.ps1 -> Prepare-WinBuild2025.ps1 (name already in place)
- Updated all references across the workspace:
    template/Prepare-WinBuild2025.ps1 (script copy, assertions, comments)
    template/Setup-WinBuild2025.ps1 (self-references in docblock and final message)
    README.md (directory tree)
    TODO.md (all inline links and task descriptions)
    docs/WINDOWS-TEMPLATE-SETUP.md (table, step descriptions, phase header, troubleshooting)
    docs/LINUX-TEMPLATE-SETUP.md (Windows equivalent reference)
This commit is contained in:
Simone
2026-05-09 23:28:36 +02:00
parent 0f21e61668
commit 644258f59c
6 changed files with 60 additions and 60 deletions
+3 -3
View File
@@ -72,8 +72,8 @@ Ogni build gira in una VM Windows Server 2025 **usa e getta**, ripristinata dall
│ └── Remove-BuildVM.ps1 # Stop + rimozione VM clone │ └── Remove-BuildVM.ps1 # Stop + rimozione VM clone
├── template/ ├── template/
│ ├── Prepare-TemplateSetup.ps1 # Provisioning automatico template VM (HOST-side) │ ├── Prepare-WinBuild2025.ps1 # Provisioning automatico template VM (HOST-side)
│ └── Setup-TemplateVM.ps1 # Installazione toolchain nella VM (GUEST-side) │ └── Setup-WinBuild2025.ps1 # Installazione toolchain nella VM (GUEST-side)
├── gitea/ ├── gitea/
│ ├── workflows/ │ ├── workflows/
@@ -103,7 +103,7 @@ Ogni build gira in una VM Windows Server 2025 **usa e getta**, ripristinata dall
```powershell ```powershell
# Dalla directory template/, dopo aver installato Windows Server 2025 nella VM # Dalla directory template/, dopo aver installato Windows Server 2025 nella VM
# e annotato il suo IP DHCP su VMnet8: # e annotato il suo IP DHCP su VMnet8:
.\Prepare-TemplateSetup.ps1 -VMIPAddress 192.168.79.x -SkipWindowsUpdate .\Prepare-WinBuild2025.ps1 -VMIPAddress 192.168.79.x -SkipWindowsUpdate
``` ```
Poi spegni la VM e prendi lo snapshot con nome esatto **`BaseClean`**. Poi spegni la VM e prendi lo snapshot con nome esatto **`BaseClean`**.
+14 -14
View File
@@ -8,7 +8,7 @@
> >
> **Doc di setup operativi**: > **Doc di setup operativi**:
> - [docs/HOST-SETUP.md](docs/HOST-SETUP.md) — bootstrap macchina host (Setup-Host.ps1) > - [docs/HOST-SETUP.md](docs/HOST-SETUP.md) — bootstrap macchina host (Setup-Host.ps1)
> - [docs/WINDOWS-TEMPLATE-SETUP.md](docs/WINDOWS-TEMPLATE-SETUP.md) — provisioning template Windows (Prepare + Setup-TemplateVM) > - [docs/WINDOWS-TEMPLATE-SETUP.md](docs/WINDOWS-TEMPLATE-SETUP.md) — provisioning template Windows (Prepare + Setup-WinBuild2025)
> - [docs/LINUX-TEMPLATE-SETUP.md](docs/LINUX-TEMPLATE-SETUP.md) — bozza/TODO template Linux (non implementato) > - [docs/LINUX-TEMPLATE-SETUP.md](docs/LINUX-TEMPLATE-SETUP.md) — bozza/TODO template Linux (non implementato)
> >
> - **P0** — sicurezza o affidabilità: affrontare prima di estendere il sistema > - **P0** — sicurezza o affidabilità: affrontare prima di estendere il sistema
@@ -84,17 +84,17 @@
- [x] Dall'host, esegui: - [x] Dall'host, esegui:
```powershell ```powershell
cd n:\Code\Workspace\Local-CI-CD-System\template cd n:\Code\Workspace\Local-CI-CD-System\template
.\Prepare-TemplateSetup.ps1 -VMIPAddress 192.168.79.128 -SkipWindowsUpdate .\Prepare-WinBuild2025.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. Installa: WinRM config, utente `ci_build`, .NET SDK 10.0, VS Build Tools 2026, Python 3.13.3.
Lo script esegue validazione automatica ad ogni passaggio (`Assert-Step`): Lo script esegue validazione automatica ad ogni passaggio (`Assert-Step`):
- Pre-flight: IP ottetti 0-255, TCP/5985 raggiungibile, Setup-TemplateVM.ps1 presente - Pre-flight: IP ottetti 0-255, TCP/5985 raggiungibile, Setup-WinBuild2025.ps1 presente
- Host WinRM: AllowUnencrypted, TrustedHosts - Host WinRM: AllowUnencrypted, TrustedHosts
- Guest prep: `C:\CI` esiste, file copiato, size match - Guest prep: `C:\CI` esiste, file copiato, size match
- Post-setup remoto (9 check): WinRM, user+admin, UAC, firewall, .NET, Python, MSBuild, CI dirs - 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**. Se qualsiasi check fallisce → script termina con errore → **non prendere lo snapshot**.
- [x] Setup completato con successo (VS Build Tools 2026 exit code 0). - [x] Setup completato con successo (VS Build Tools 2026 exit code 0).
- [x] `Setup-TemplateVM.ps1` ora esegue validazione `Assert-Step` dopo ogni step interno - [x] `Setup-WinBuild2025.ps1` ora esegue validazione `Assert-Step` dopo ogni step interno
(WinRM, Firewall, User, UAC, Dirs, Defender, .NET, Python, VS Build Tools, Toolchain, (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) Cleanup, Final pre-snapshot gate) — throws se qualsiasi check fallisce (2026-05-09)
@@ -103,7 +103,7 @@
- [x] Spegni la VM: Start → Shut down - [x] Spegni la VM: Start → Shut down
- [x] Prendi snapshot: VM → Snapshot → Take Snapshot - [x] Prendi snapshot: VM → Snapshot → Take Snapshot
**Nome esatto: `BaseClean`** **Nome esatto: `BaseClean`**
**Prerequisito: `Prepare-TemplateSetup.ps1` deve essere uscito con exit 0** — tutti **Prerequisito: `Prepare-WinBuild2025.ps1` deve essere uscito con exit 0** — tutti
gli `Assert-Step` passati, incluso il Final pre-snapshot gate nel guest. gli `Assert-Step` passati, incluso il Final pre-snapshot gate nel guest.
- [x] Lascia la VM spenta — non modificarla mai più dopo questo snapshot - [x] Lascia la VM spenta — non modificarla mai più dopo questo snapshot
@@ -150,7 +150,7 @@
## 1. Sicurezza & hardening ## 1. Sicurezza & hardening
### 1.1 [P0] Migrare WinRM da HTTP/Basic a HTTPS/5986 ### 1.1 [P0] Migrare WinRM da HTTP/Basic a HTTPS/5986
File: [template/Setup-TemplateVM.ps1:179-198](template/Setup-TemplateVM.ps1), [scripts/Invoke-RemoteBuild.ps1:82-91](scripts/Invoke-RemoteBuild.ps1). File: [template/Setup-WinBuild2025.ps1:179-198](template/Setup-WinBuild2025.ps1), [scripts/Invoke-RemoteBuild.ps1:82-91](scripts/Invoke-RemoteBuild.ps1).
**Motivazione**: la combo `AllowUnencrypted=true` + `Auth/Basic=true` invia credenziali del **Motivazione**: la combo `AllowUnencrypted=true` + `Auth/Basic=true` invia credenziali del
`ci_build` (admin) in chiaro su VMnet8. Anche in lab isolato, l'host può essere compromesso `ci_build` (admin) in chiaro su VMnet8. Anche in lab isolato, l'host può essere compromesso
@@ -160,7 +160,7 @@ manca solo l'esecuzione.
**Azioni**: **Azioni**:
- [ ] Generare cert self-signed nel template *prima* dello snapshot. - [ ] Generare cert self-signed nel template *prima* dello snapshot.
- [ ] Sostituire `New-PSSession -ComputerName $ip` con `-UseSSL -Port 5986` in `Invoke-RemoteBuild.ps1` e `Get-BuildArtifacts.ps1`. - [ ] Sostituire `New-PSSession -ComputerName $ip` con `-UseSSL -Port 5986` in `Invoke-RemoteBuild.ps1` e `Get-BuildArtifacts.ps1`.
- [ ] Rimuovere `AllowUnencrypted=true` dal `Setup-TemplateVM.ps1`. - [ ] Rimuovere `AllowUnencrypted=true` dal `Setup-WinBuild2025.ps1`.
- [ ] Tenere `-SkipCACheck` lato host: per cert lab self-signed è accettabile, ma documentare la motivazione inline. - [ ] Tenere `-SkipCACheck` lato host: per cert lab self-signed è accettabile, ma documentare la motivazione inline.
- [ ] Regole firewall — limitare WinRM alla subnet build VM (`192.168.79.0/24` — VMnet8 NAT). - [ ] Regole firewall — limitare WinRM alla subnet build VM (`192.168.79.0/24` — VMnet8 NAT).
@@ -173,7 +173,7 @@ Set-Item WSMan:\localhost\Client\TrustedHosts -Value '192.168.79.*' -Force -Conc
``` ```
### 1.3 [P0] Pinning hash SHA256 degli installer ### 1.3 [P0] Pinning hash SHA256 degli installer
File: [template/Setup-TemplateVM.ps1:332-399](template/Setup-TemplateVM.ps1), [template/Setup-TemplateVM.ps1:401-502](template/Setup-TemplateVM.ps1). File: [template/Setup-WinBuild2025.ps1:332-399](template/Setup-WinBuild2025.ps1), [template/Setup-WinBuild2025.ps1:401-502](template/Setup-WinBuild2025.ps1).
**Motivazione**: Python, `dotnet-install.ps1`, `vs_buildtools.exe` vengono scaricati senza **Motivazione**: Python, `dotnet-install.ps1`, `vs_buildtools.exe` vengono scaricati senza
verifica integrità. Un MITM nella rete dell'host (anche temporaneo) può iniettare binari verifica integrità. Un MITM nella rete dell'host (anche temporaneo) può iniettare binari
@@ -206,7 +206,7 @@ Quando arriva il momento di implementare il clone in-VM (vedi §3.3 / sezione "I
- [ ] Aggiungere un grep automatico nei log job: se il PAT compare grezzo, fallire la build. - [ ] Aggiungere un grep automatico nei log job: se il PAT compare grezzo, fallire la build.
### 1.6 [P2] Defender + Firewall + UAC tutti disattivati nel template — documentare il modello di minaccia ### 1.6 [P2] Defender + Firewall + UAC tutti disattivati nel template — documentare il modello di minaccia
File: [template/Setup-TemplateVM.ps1:200-329](template/Setup-TemplateVM.ps1). File: [template/Setup-WinBuild2025.ps1:200-329](template/Setup-WinBuild2025.ps1).
Attualmente: `Set-NetFirewallProfile ... -Enabled False`, `EnableLUA=0`, `DisableAntiSpyware=1`, Attualmente: `Set-NetFirewallProfile ... -Enabled False`, `EnableLUA=0`, `DisableAntiSpyware=1`,
`DisableRealtimeMonitoring=1`, `LocalAccountTokenFilterPolicy=1`. `DisableRealtimeMonitoring=1`, `LocalAccountTokenFilterPolicy=1`.
@@ -481,7 +481,7 @@ e centralizza retry/log.
File: [gitea/workflows/lint.yml](gitea/workflows/lint.yml) (già esiste). File: [gitea/workflows/lint.yml](gitea/workflows/lint.yml) (già esiste).
Aggiungere regole specifiche progetto (`PSScriptAnalyzerSettings.psd1` in root): Aggiungere regole specifiche progetto (`PSScriptAnalyzerSettings.psd1` in root):
- `PSAvoidUsingPlainTextForPassword` — rilevante per `Setup-TemplateVM.ps1:55`. - `PSAvoidUsingPlainTextForPassword` — rilevante per `Setup-WinBuild2025.ps1:55`.
- `PSAvoidUsingInvokeExpression`. - `PSAvoidUsingInvokeExpression`.
- `PSUseShouldProcessForStateChangingFunctions`. - `PSUseShouldProcessForStateChangingFunctions`.
- Regole custom: vietare hardcoded `F:\CI\` fuori da config (forzare param/env). - Regole custom: vietare hardcoded `F:\CI\` fuori da config (forzare param/env).
@@ -566,7 +566,7 @@ VM avviata → WinRM: git clone --recurse-submodules https://<token>@gitea/...
**Punti chiave:** **Punti chiave:**
- Il PAT **non deve essere nello snapshot** — viene iniettato a runtime come env var via WinRM - 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 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 - Git deve essere installato nel template (`Setup-WinBuild2025.ps1`) — ora è assente per design
- L'implementazione deve essere **non-breaking**: nuovo switch opt-in `-UseGitClone` in `Invoke-CIJob.ps1` - 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 - 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) tutto l'overhead di zip/transfer (rilevante su repo grandi o con molti submoduli)
@@ -574,7 +574,7 @@ VM avviata → WinRM: git clone --recurse-submodules https://<token>@gitea/...
### Task ### Task
- [ ] **Setup-TemplateVM.ps1 — installare Git for Windows** - [ ] **Setup-WinBuild2025.ps1 — installare Git for Windows**
- [ ] Scaricare e installare Git for Windows (installer silenzioso da git-scm.com) - [ ] Scaricare e installare Git for Windows (installer silenzioso da git-scm.com)
```powershell ```powershell
$gitUrl = 'https://github.com/git-for-windows/git/releases/download/v2.47.1.windows.1/Git-2.47.1-64-bit.exe' $gitUrl = 'https://github.com/git-for-windows/git/releases/download/v2.47.1.windows.1/Git-2.47.1-64-bit.exe'
@@ -582,9 +582,9 @@ VM avviata → WinRM: git clone --recurse-submodules https://<token>@gitea/...
``` ```
- [ ] Aggiungere `C:\Program Files\Git\cmd` al PATH di sistema nella VM - [ ] Aggiungere `C:\Program Files\Git\cmd` al PATH di sistema nella VM
- [ ] Verificare: `git --version` ritorna exit 0 nella VM - [ ] Verificare: `git --version` ritorna exit 0 nella VM
- [ ] Rimuovere il commento "Git is NOT installed" dal docblock di Setup-TemplateVM.ps1 - [ ] Rimuovere il commento "Git is NOT installed" dal docblock di Setup-WinBuild2025.ps1
- [ ] **Setup-TemplateVM.ps1 — altri tool utili** - [ ] **Setup-WinBuild2025.ps1 — altri tool utili**
- [ ] **7-Zip**: installer silenzioso — molto più veloce di `Compress-Archive`/`Expand-Archive` - [ ] **7-Zip**: installer silenzioso — molto più veloce di `Compress-Archive`/`Expand-Archive`
per archivi grandi (es. npm/NuGet cache warm). Necessario anche per §3.2. per archivi grandi (es. npm/NuGet cache warm). Necessario anche per §3.2.
- [ ] **curl.exe**: già presente in Windows 11/Server 2025 (v7.x) — verificare disponibilità - [ ] **curl.exe**: già presente in Windows 11/Server 2025 (v7.x) — verificare disponibilità
+2 -2
View File
@@ -150,7 +150,7 @@ Dentro la VM, come `ci_build`:
sudo systemctl restart sshd sudo systemctl restart sshd
``` ```
### Fase C — Setup-LinuxTemplateVM.sh (script equivalente a Setup-TemplateVM.ps1) ### Fase C — Setup-LinuxTemplateVM.sh (script equivalente a Setup-WinBuild2025.ps1)
Da creare: `template/Setup-LinuxTemplateVM.sh` con `set -euo pipefail` + `assert_step()` helper. Da creare: `template/Setup-LinuxTemplateVM.sh` con `set -euo pipefail` + `assert_step()` helper.
@@ -226,7 +226,7 @@ Da creare: `template/Setup-LinuxTemplateVM.sh` con `set -euo pipefail` + `assert
### Fase D — Prepare-LinuxTemplateSetup.ps1 (orchestratore host-side) ### Fase D — Prepare-LinuxTemplateSetup.ps1 (orchestratore host-side)
Equivalente di `Prepare-TemplateSetup.ps1` per Linux. Usa SSH invece di WinRM. Equivalente di `Prepare-WinBuild2025.ps1` per Linux. Usa SSH invece di WinRM.
- [ ] **Pre-flight host**: - [ ] **Pre-flight host**:
- SSH key esiste (`F:\CI\keys\ci_linux`) - SSH key esiste (`F:\CI\keys\ci_linux`)
+14 -14
View File
@@ -13,10 +13,10 @@ credenziali archiviate, ISO Windows Server presente).
| Script | Dove gira | Scopo | | Script | Dove gira | Scopo |
| ---------------------------------------- | --------------- | -------------------------------------------------- | | ---------------------------------------- | --------------- | -------------------------------------------------- |
| `template/Prepare-TemplateSetup.ps1` | **Host** | Orchestratore: copia + esegue lo script in VM | | `template/Prepare-WinBuild2025.ps1` | **Host** | Orchestratore: copia + esegue lo script in VM |
| `template/Setup-TemplateVM.ps1` | **Dentro VM** | Provisioning effettivo (firewall, defender, tool) | | `template/Setup-WinBuild2025.ps1` | **Dentro VM** | Provisioning effettivo (firewall, defender, tool) |
`Prepare-TemplateSetup.ps1` apre una WinRM session, copia `Setup-TemplateVM.ps1` in `Prepare-WinBuild2025.ps1` apre una WinRM session, copia `Setup-WinBuild2025.ps1` in
`C:\CI\`, lo esegue, raccoglie l'exit code, valida lo stato del guest. `C:\CI\`, lo esegue, raccoglie l'exit code, valida lo stato del guest.
--- ---
@@ -93,25 +93,25 @@ Dall'host (PowerShell elevato):
```powershell ```powershell
cd N:\Code\Workspace\Local-CI-CD-System\template cd N:\Code\Workspace\Local-CI-CD-System\template
# Provisioning completo + registrazione credenziali automatica: # Provisioning completo + registrazione credenziali automatica:
.\Prepare-TemplateSetup.ps1 -VMIPAddress 192.168.79.128 -StoreCredential .\Prepare-WinBuild2025.ps1 -VMIPAddress 192.168.79.128 -StoreCredential
# Se WU già applicato in precedenza: # Se WU già applicato in precedenza:
.\Prepare-TemplateSetup.ps1 -VMIPAddress 192.168.79.128 -SkipWindowsUpdate -StoreCredential .\Prepare-WinBuild2025.ps1 -VMIPAddress 192.168.79.128 -SkipWindowsUpdate -StoreCredential
``` ```
### Cosa fa `Prepare-TemplateSetup.ps1` — passo per passo ### Cosa fa `Prepare-WinBuild2025.ps1` — passo per passo
Ogni step ha validazione `Assert-Step` (throw on failure, `[OK]` su pass): Ogni step ha validazione `Assert-Step` (throw on failure, `[OK]` su pass):
1. **Pre-flight**: script dir presente, `Setup-TemplateVM.ps1` presente, IP ottetti 0-255, TCP/5985 reachable 1. **Pre-flight**: script dir presente, `Setup-WinBuild2025.ps1` presente, IP ottetti 0-255, TCP/5985 reachable
2. **Configura host WinRM client**: `AllowUnencrypted=true`, aggiunge `$VMIPAddress` ai `TrustedHosts` 2. **Configura host WinRM client**: `AllowUnencrypted=true`, aggiunge `$VMIPAddress` ai `TrustedHosts`
- Salva valori precedenti, ripristinati nel `finally` (host posture invariata) - Salva valori precedenti, ripristinati nel `finally` (host posture invariata)
3. **Validazione host WinRM**: `AllowUnencrypted=true`, `TrustedHosts` include IP 3. **Validazione host WinRM**: `AllowUnencrypted=true`, `TrustedHosts` include IP
4. **Test connettività**: `Test-WSMan -Authentication Basic` con credenziali admin 4. **Test connettività**: `Test-WSMan -Authentication Basic` con credenziali admin
5. **Apre PSSession** verso la VM 5. **Apre PSSession** verso la VM
6. **Crea `C:\CI`** in guest, valida creazione 6. **Crea `C:\CI`** in guest, valida creazione
7. **Copia `Setup-TemplateVM.ps1`** in `C:\CI\Setup-TemplateVM.ps1`, valida size match 7. **Copia `Setup-WinBuild2025.ps1`** in `C:\CI\Setup-WinBuild2025.ps1`, valida size match
8. **Esegue `Setup-TemplateVM.ps1`** dentro la VM (vedi Fase C) 8. **Esegue `Setup-WinBuild2025.ps1`** dentro la VM (vedi Fase C)
9. **Gestisce reboot 3010**: se WU richiede reboot, riavvia VM e suggerisce re-run con `-SkipWindowsUpdate` 9. **Gestisce reboot 3010**: se WU richiede reboot, riavvia VM e suggerisce re-run con `-SkipWindowsUpdate`
10. **Post-setup remote validation** (9 check via singola `Invoke-Command`): 10. **Post-setup remote validation** (9 check via singola `Invoke-Command`):
- WinRM Running - WinRM Running
@@ -134,13 +134,13 @@ Ogni step ha validazione `Assert-Step` (throw on failure, `[OK]` su pass):
| `-BuildPassword` | (prompt) | Password per `ci_build` — mai hard-codare | | `-BuildPassword` | (prompt) | Password per `ci_build` — mai hard-codare |
| `-BuildUsername` | ci_build | Account CI dentro la VM | | `-BuildUsername` | ci_build | Account CI dentro la VM |
| `-DotNetSdkVersion` | 10.0 | Channel .NET SDK | | `-DotNetSdkVersion` | 10.0 | Channel .NET SDK |
| `-SkipWindowsUpdate` | (off) | Pass-through a Setup-TemplateVM.ps1 | | `-SkipWindowsUpdate` | (off) | Pass-through a Setup-WinBuild2025.ps1 |
| `-StoreCredential` | (off) | Registra `BuildUsername`/`BuildPassword` in Windows Credential Manager | | `-StoreCredential` | (off) | Registra `BuildUsername`/`BuildPassword` in Windows Credential Manager |
| `-CredentialTarget` | BuildVMGuest | Target Credential Manager (deve corrispondere a quanto usato da Invoke-CIJob) | | `-CredentialTarget` | BuildVMGuest | Target Credential Manager (deve corrispondere a quanto usato da Invoke-CIJob) |
--- ---
## Fase C — Cosa fa `Setup-TemplateVM.ps1` (dentro la VM) ## Fase C — Cosa fa `Setup-WinBuild2025.ps1` (dentro la VM)
Eseguito automaticamente da Prepare in Fase B. Ordine ottimizzato per ridurre overhead: Eseguito automaticamente da Prepare in Fase B. Ordine ottimizzato per ridurre overhead:
tutti i tweak UI/registro sono raggruppati **prima** di Windows Update (operazione lenta). tutti i tweak UI/registro sono raggruppati **prima** di Windows Update (operazione lenta).
@@ -208,7 +208,7 @@ Final Pre-snapshot gate — 7 check cross-cutting + no installer leftover
## Fase D — Snapshot ## Fase D — Snapshot
**Solo se `Prepare-TemplateSetup.ps1` exit 0** (tutti gli `Assert-Step` passati): **Solo se `Prepare-WinBuild2025.ps1` exit 0** (tutti gli `Assert-Step` passati):
1. **Spegni la VM**: Start → Shut down (graceful, non hard-stop) 1. **Spegni la VM**: Start → Shut down (graceful, non hard-stop)
2. **Take snapshot** in VMware Workstation: 2. **Take snapshot** in VMware Workstation:
@@ -247,7 +247,7 @@ toolchain (.NET, VS Build Tools, Python).
**Procedura**: **Procedura**:
1. Power on della template VM (NIC: VMnet8 NAT) 1. Power on della template VM (NIC: VMnet8 NAT)
2. Riattiva: `slmgr /ato` 2. Riattiva: `slmgr /ato`
3. Re-run `Prepare-TemplateSetup.ps1` per applicare update toolchain (passare flag opportuni) 3. Re-run `Prepare-WinBuild2025.ps1` per applicare update toolchain (passare flag opportuni)
4. Shut down + nuovo snapshot **versionato**: `BaseClean_<yyyyMMdd>` (TODO §2.5) 4. Shut down + nuovo snapshot **versionato**: `BaseClean_<yyyyMMdd>` (TODO §2.5)
5. Aggiorna `GITEA_CI_SNAPSHOT_NAME` env var in `runner/config.yaml` 5. Aggiorna `GITEA_CI_SNAPSHOT_NAME` env var in `runner/config.yaml`
6. Tieni i 2 snapshot più recenti, cancella vecchi dopo 1 settimana di uso pulito 6. Tieni i 2 snapshot più recenti, cancella vecchi dopo 1 settimana di uso pulito
@@ -259,7 +259,7 @@ toolchain (.NET, VS Build Tools, Python).
| Sintomo | Diagnosi / Fix | | Sintomo | Diagnosi / Fix |
| ------------------------------------------- | ----------------------------------------------------------------------- | | ------------------------------------------- | ----------------------------------------------------------------------- |
| `Cannot reach $VMIPAddress via WinRM` | VM non avviata, WinRM non abilitato, IP errato — verifica con ipconfig | | `Cannot reach $VMIPAddress via WinRM` | VM non avviata, WinRM non abilitato, IP errato — verifica con ipconfig |
| `Setup-TemplateVM.ps1 exited with code 3010`| Reboot richiesto post-WU. Re-run con `-SkipWindowsUpdate` | | `Setup-WinBuild2025.ps1 exited with code 3010`| Reboot richiesto post-WU. Re-run con `-SkipWindowsUpdate` |
| `[Defender] Validation failed: GPO key` | Defender riattivato da Windows Update — disabilita via gpedit + reboot | | `[Defender] Validation failed: GPO key` | Defender riattivato da Windows Update — disabilita via gpedit + reboot |
| `VS Build Tools installation timed out` | Network slow o cache corrotta. Re-run con cache pulita (`C:\ProgramData\Microsoft\VisualStudio\Packages`) | | `VS Build Tools installation timed out` | Network slow o cache corrotta. Re-run con cache pulita (`C:\ProgramData\Microsoft\VisualStudio\Packages`) |
| `Python version match` fail | `$PythonVersion` ≠ versione installata. Aggiorna param o reinstalla | | `Python version match` fail | `$PythonVersion` ≠ versione installata. Aggiorna param o reinstalla |
@@ -1,7 +1,7 @@
#Requires -Version 5.1 #Requires -Version 5.1
<# <#
.SYNOPSIS .SYNOPSIS
HOST-side script: delivers and runs Setup-TemplateVM.ps1 inside the template VM. HOST-side script: delivers and runs Setup-WinBuild2025.ps1 inside the template VM.
.DESCRIPTION .DESCRIPTION
Automates the template VM provisioning from the host machine: Automates the template VM provisioning from the host machine:
@@ -11,8 +11,8 @@
4. Tests WinRM connectivity (Test-WSMan) fails fast with actionable message 4. Tests WinRM connectivity (Test-WSMan) fails fast with actionable message
5. Opens PSSession to the VM 5. Opens PSSession to the VM
6. Ensures C:\CI exists on guest; validates creation 6. Ensures C:\CI exists on guest; validates creation
7. Copies Setup-TemplateVM.ps1 into the VM; validates file present + size match 7. Copies Setup-WinBuild2025.ps1 into the VM; validates file present + size match
8. Runs Setup-TemplateVM.ps1 inside the VM with the given parameters 8. Runs Setup-WinBuild2025.ps1 inside the VM with the given parameters
(Setup performs per-step validation internally aborts on any failure) (Setup performs per-step validation internally aborts on any failure)
9. Handles the reboot-required case (exit 3010) and optionally re-runs 9. Handles the reboot-required case (exit 3010) and optionally re-runs
10. Post-setup remote validation: 9 guest-state checks via a single Invoke-Command 10. Post-setup remote validation: 9 guest-state checks via a single Invoke-Command
@@ -67,13 +67,13 @@
.PARAMETER BuildUsername .PARAMETER BuildUsername
Local username for the CI build account inside the VM. Default: ci_build. Local username for the CI build account inside the VM. Default: ci_build.
Passed through to Setup-TemplateVM.ps1 and used in post-setup validation. Passed through to Setup-WinBuild2025.ps1 and used in post-setup validation.
.PARAMETER DotNetSdkVersion .PARAMETER DotNetSdkVersion
.NET SDK channel to install in the VM. Default: 10.0 (matches host SDK). .NET SDK channel to install in the VM. Default: 10.0 (matches host SDK).
.PARAMETER SkipWindowsUpdate .PARAMETER SkipWindowsUpdate
Pass through to Setup-TemplateVM.ps1 to skip the Windows Update step. Pass through to Setup-WinBuild2025.ps1 to skip the Windows Update step.
.PARAMETER SnapshotName .PARAMETER SnapshotName
Name of the snapshot to create. Default: BaseClean (case-sensitive used by New-BuildVM.ps1). Name of the snapshot to create. Default: BaseClean (case-sensitive used by New-BuildVM.ps1).
@@ -94,21 +94,21 @@
.EXAMPLE .EXAMPLE
# Fully automated — VMX path only (power-on + IP detection + snapshot automatic): # Fully automated — VMX path only (power-on + IP detection + snapshot automatic):
.\Prepare-TemplateSetup.ps1 ` .\Prepare-WinBuild2025.ps1 `
-VMXPath 'F:\CI\Templates\WinBuild\WinBuild.vmx' ` -VMXPath 'F:\CI\Templates\WinBuild\WinBuild.vmx' `
-BuildPassword 'StrongCIPass!2026' -StoreCredential -BuildPassword 'StrongCIPass!2026' -StoreCredential
# Skip Windows Update (already applied): # Skip Windows Update (already applied):
.\Prepare-TemplateSetup.ps1 ` .\Prepare-WinBuild2025.ps1 `
-VMXPath 'F:\CI\Templates\WinBuild\WinBuild.vmx' ` -VMXPath 'F:\CI\Templates\WinBuild\WinBuild.vmx' `
-SkipWindowsUpdate -StoreCredential -SkipWindowsUpdate -StoreCredential
# Explicit IP (manual start, no VMware Tools required for IP detection): # Explicit IP (manual start, no VMware Tools required for IP detection):
.\Prepare-TemplateSetup.ps1 -VMIPAddress 192.168.79.130 ` .\Prepare-WinBuild2025.ps1 -VMIPAddress 192.168.79.130 `
-BuildPassword 'StrongCIPass!2026' -StoreCredential -BuildPassword 'StrongCIPass!2026' -StoreCredential
# Both supplied — uses VMXPath for power-on/snapshot, explicit IP skips getGuestIPAddress: # Both supplied — uses VMXPath for power-on/snapshot, explicit IP skips getGuestIPAddress:
.\Prepare-TemplateSetup.ps1 ` .\Prepare-WinBuild2025.ps1 `
-VMXPath 'F:\CI\Templates\WinBuild\WinBuild.vmx' -VMIPAddress 192.168.79.130 ` -VMXPath 'F:\CI\Templates\WinBuild\WinBuild.vmx' -VMIPAddress 192.168.79.130 `
-BuildPassword 'StrongCIPass!2026' -StoreCredential -BuildPassword 'StrongCIPass!2026' -StoreCredential
#> #>
@@ -217,8 +217,8 @@ $scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
# Pre-flight validation # Pre-flight validation
Assert-Step 'PreFlight' 'script directory resolved' { Test-Path $scriptDir -PathType Container } Assert-Step 'PreFlight' 'script directory resolved' { Test-Path $scriptDir -PathType Container }
Assert-Step 'PreFlight' 'Setup-TemplateVM.ps1 present alongside this script' { Assert-Step 'PreFlight' 'Setup-WinBuild2025.ps1 present alongside this script' {
Test-Path (Join-Path $scriptDir 'Setup-TemplateVM.ps1') -PathType Leaf Test-Path (Join-Path $scriptDir 'Setup-WinBuild2025.ps1') -PathType Leaf
} }
Assert-Step 'PreFlight' "VMIPAddress octets in 0..255" { Assert-Step 'PreFlight' "VMIPAddress octets in 0..255" {
$parts = $VMIPAddress.Split('.') | ForEach-Object { [int]$_ } $parts = $VMIPAddress.Split('.') | ForEach-Object { [int]$_ }
@@ -331,9 +331,9 @@ $session = New-PSSession `
-ErrorAction Stop -ErrorAction Stop
try { try {
# ── Copy Setup-TemplateVM.ps1 into the VM ───────────────────────────────── # ── Copy Setup-WinBuild2025.ps1 into the VM ───────────────────────────────
$setupScript = Join-Path $scriptDir 'Setup-TemplateVM.ps1' $setupScript = Join-Path $scriptDir 'Setup-WinBuild2025.ps1'
$guestScriptPath = 'C:\CI\Setup-TemplateVM.ps1' $guestScriptPath = 'C:\CI\Setup-WinBuild2025.ps1'
Write-Host "[Prepare] Ensuring C:\CI exists on guest..." Write-Host "[Prepare] Ensuring C:\CI exists on guest..."
Invoke-Command -Session $session -ScriptBlock { Invoke-Command -Session $session -ScriptBlock {
@@ -345,7 +345,7 @@ try {
Invoke-Command -Session $session -ScriptBlock { Test-Path 'C:\CI' -PathType Container } Invoke-Command -Session $session -ScriptBlock { Test-Path 'C:\CI' -PathType Container }
} }
Write-Host "[Prepare] Copying Setup-TemplateVM.ps1 -> guest $guestScriptPath (UTF-8 BOM)..." Write-Host "[Prepare] Copying Setup-WinBuild2025.ps1 -> guest $guestScriptPath (UTF-8 BOM)..."
# Do NOT use Copy-Item -ToSession: it binary-copies the file. # Do NOT use Copy-Item -ToSession: it binary-copies the file.
# If the source file has no UTF-8 BOM, PowerShell 5.1 on the guest reads it as # If the source file has no UTF-8 BOM, PowerShell 5.1 on the guest reads it as
# Windows-1252, misinterpreting multi-byte UTF-8 sequences (e.g. em dash U+2014 # Windows-1252, misinterpreting multi-byte UTF-8 sequences (e.g. em dash U+2014
@@ -375,7 +375,7 @@ try {
[int64]$remoteSize -ge ([int64]$hostSize - 6) -and [int64]$remoteSize -le ([int64]$hostSize + 6) [int64]$remoteSize -ge ([int64]$hostSize - 6) -and [int64]$remoteSize -le ([int64]$hostSize + 6)
} }
# ── Build argument list for Setup-TemplateVM.ps1 ───────────────────────── # ── Build argument list for Setup-WinBuild2025.ps1 ───────────────────────
$setupArgs = @{ $setupArgs = @{
BuildPassword = $BuildPassword BuildPassword = $BuildPassword
BuildUsername = $BuildUsername BuildUsername = $BuildUsername
@@ -384,8 +384,8 @@ try {
if ($SkipWindowsUpdate) { $setupArgs['SkipWindowsUpdate'] = $true } if ($SkipWindowsUpdate) { $setupArgs['SkipWindowsUpdate'] = $true }
if ($SkipCleanup) { $setupArgs['SkipCleanup'] = $true } if ($SkipCleanup) { $setupArgs['SkipCleanup'] = $true }
# ── Run Setup-TemplateVM.ps1 inside the VM ──────────────────────────────── # ── Run Setup-WinBuild2025.ps1 inside the VM ──────────────────────────────
Write-Host "[Prepare] Running Setup-TemplateVM.ps1 inside VM (this will take a while)..." Write-Host "[Prepare] Running Setup-WinBuild2025.ps1 inside VM (this will take a while)..."
Write-Host "[Prepare] Output from guest:" Write-Host "[Prepare] Output from guest:"
Write-Host "------------------------------------------------------------" Write-Host "------------------------------------------------------------"
@@ -412,7 +412,7 @@ try {
Write-Host "" Write-Host ""
Write-Warning "*** REBOOT REQUIRED after Windows Update. ***" Write-Warning "*** REBOOT REQUIRED after Windows Update. ***"
Write-Warning " The VM will reboot. Wait for it to come back up, then run:" Write-Warning " The VM will reboot. Wait for it to come back up, then run:"
Write-Warning " .\Prepare-TemplateSetup.ps1 -VMIPAddress $VMIPAddress -SkipWindowsUpdate" Write-Warning " .\Prepare-WinBuild2025.ps1 -VMIPAddress $VMIPAddress -SkipWindowsUpdate"
# Reboot the VM # Reboot the VM
Write-Host "[Prepare] Sending reboot command to VM..." Write-Host "[Prepare] Sending reboot command to VM..."
@@ -421,7 +421,7 @@ try {
} }
if ($result -ne 0) { if ($result -ne 0) {
throw "Setup-TemplateVM.ps1 exited with code $result" throw "Setup-WinBuild2025.ps1 exited with code $result"
} }
# ── Post-setup remote validation ────────────────────────────────────────── # ── Post-setup remote validation ──────────────────────────────────────────
@@ -598,7 +598,7 @@ try {
} }
else { else {
Write-Host " 3. Store CI credentials on this HOST (run in elevated PowerShell):" Write-Host " 3. Store CI credentials on this HOST (run in elevated PowerShell):"
Write-Host " .\Prepare-TemplateSetup.ps1 -VMIPAddress $VMIPAddress -StoreCredential" Write-Host " .\Prepare-WinBuild2025.ps1 -VMIPAddress $VMIPAddress -StoreCredential"
Write-Host " (or manually:)" Write-Host " (or manually:)"
Write-Host " New-StoredCredential -Target '$CredentialTarget' ``" Write-Host " New-StoredCredential -Target '$CredentialTarget' ``"
Write-Host " -UserName '$BuildUsername' -Password '<your-build-password>' ``" Write-Host " -UserName '$BuildUsername' -Password '<your-build-password>' ``"
@@ -93,7 +93,7 @@
Local username for the CI build account. Default: ci_build. Local username for the CI build account. Default: ci_build.
.PARAMETER BuildPassword .PARAMETER BuildPassword
Password for the build account. Mandatory supplied by Prepare-TemplateSetup.ps1 Password for the build account. Mandatory supplied by Prepare-WinBuild2025.ps1
(which prompts interactively). Store the same value in Windows Credential Manager (which prompts interactively). Store the same value in Windows Credential Manager
on the HOST as target "BuildVMGuest". on the HOST as target "BuildVMGuest".
@@ -107,10 +107,10 @@
Skip the Windows Update step (useful if updates were already applied). Skip the Windows Update step (useful if updates were already applied).
.NOTES .NOTES
Invoke via Prepare-TemplateSetup.ps1 from the HOST (recommended), or Invoke via Prepare-WinBuild2025.ps1 from the HOST (recommended), or
run manually from an elevated PowerShell session INSIDE the VM: run manually from an elevated PowerShell session INSIDE the VM:
Set-ExecutionPolicy Bypass -Scope Process -Force Set-ExecutionPolicy Bypass -Scope Process -Force
.\Setup-TemplateVM.ps1 -BuildPassword 'YourPassword' .\Setup-WinBuild2025.ps1 -BuildPassword 'YourPassword'
#> #>
[CmdletBinding()] [CmdletBinding()]
param( param(
@@ -118,7 +118,7 @@ param(
[string] $BuildUsername = 'ci_build', [string] $BuildUsername = 'ci_build',
# Password for the build account. # Password for the build account.
# Must be supplied by the caller (Prepare-TemplateSetup.ps1 prompts interactively). # Must be supplied by the caller (Prepare-WinBuild2025.ps1 prompts interactively).
# Store the same password in Windows Credential Manager on the HOST as target "BuildVMGuest". # Store the same password in Windows Credential Manager on the HOST as target "BuildVMGuest".
[Parameter(Mandatory)] [Parameter(Mandatory)]
[string] $BuildPassword, [string] $BuildPassword,
@@ -1125,8 +1125,8 @@ Write-Host "All pre-snapshot checks passed." -ForegroundColor Green
# ── Done ────────────────────────────────────────────────────────────────────── # ── Done ──────────────────────────────────────────────────────────────────────
Write-Host "" Write-Host ""
Write-Host "Setup-TemplateVM.ps1 complete. All Assert-Step checks passed." -ForegroundColor Green Write-Host "Setup-WinBuild2025.ps1 complete. All Assert-Step checks passed." -ForegroundColor Green
# Full next-steps banner is printed by Prepare-TemplateSetup.ps1 on the host. # Full next-steps banner is printed by Prepare-WinBuild2025.ps1 on the host.
# If running this script standalone (manually inside the VM), follow the steps # If running this script standalone (manually inside the VM), follow the steps
# in docs/WINDOWS-TEMPLATE-SETUP.md (shut down → snapshot BaseClean → power off). # in docs/WINDOWS-TEMPLATE-SETUP.md (shut down → snapshot BaseClean → power off).
Write-Host "" Write-Host ""