Commit Graph

18 Commits

Author SHA1 Message Date
Simone d732e182ce test(validation): Add Git + 7-Zip checks to Validate-SetupState
§6.6 Tier-1 Toolchain (Git for Windows, 7-Zip) now included in final
state validation. Checks:
- 'Git for Windows (git.exe in PATH)'
- '7-Zip (7z.exe in PATH)'

Added to both initial validation pass and re-validation pass (post-remediation).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-10 21:01:46 +02:00
Simone 971d3dc6e9 feat(template): Add Step 11 Tier-1 Toolchain — Git + 7-Zip installation
Implement §6.6 minimal viable product: install Git for Windows and 7-Zip
to the template VM. Critical prerequisites for §3.3 (In-VM Git clone).

Step 11 additions:
- Git for Windows (latest LTS configurable) — silent installer, adds to PATH
- 7-Zip (latest stable configurable) — MSI installer to Program Files
- SHA256 hash pinning for both tools (currently unpinned, warn at runtime)
- Assert-Step validation for git/7z command availability
- Final pre-snapshot gate checks for both tools + cleanup of installers

Parameters added:
- -GitVersion (default: 2.47.0.windows.1)
- -SevenZipVersion (default: 24.07)

Rationale:
- Enables §3.3 in-VM Git clone (git clone directly in VM instead of host-zip-transfer)
- Supports cross-platform builds and multi-tool workflows
- Fallback from §3.2 7-Zip compression finally available in template
- Positions for future expansion of Tier-1 tools (NSIS, CMake, Node.js, WiX, etc.)

Updated documentation:
- Setup-WinBuild2025.ps1 docstring: Step 11 added to list + step ordering rationale
- Removed NOTE about Git not being installed
- Final validation now checks: 9 assertions (was 7)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-10 20:48:43 +02:00
Simone d4e619ddc2 feat(template): add WinBuild2022 script variants (Deploy/Prepare/Setup) 2026-05-10 18:17:47 +02:00
Simone 8b54ca01b3 feat(setup): Step 3b — Windows KMS activation via slmgr /skms + /ato
Activates Windows against kms8.msguides.com before Windows Update runs
so WU sees correct license state. Uses cscript //NoLogo to route slmgr
output to stdout (dialogs hang in WinRM sessions). Best-effort: activation
failure emits a warning but does not abort Setup — CI builds function
within the grace period.

Placed between Step 3 (WinRM/network confirmed) and Step 4 (user creation).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-10 17:27:23 +02:00
Simone d63611f78e fix(setup): $sdFiles.Count null-dereference under StrictMode — wrap in @()
$sdFiles is $null when SoftwareDistribution\Download is empty. StrictMode
throws on $null.Count. @($sdFiles).Count safely returns 0 for null.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-10 17:20:26 +02:00
Simone ee7f406f2a fix(setup): Measure-Object .Sum null-dereference under Set-StrictMode -Version Latest
PS 5.1 treats GenericMeasureInfo.Sum as absent (not null) when the input pipe
is empty. StrictMode throws 'property Sum cannot be found'. Replace Measure-Object
with an explicit foreach loop for SoftwareDistribution size reporting.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-10 17:17:41 +02:00
Simone edce871644 fix(setup): defeat WaaSMedicSvc wuauserv healing + AutoAdminLogon Final gate
Two persistent Validate-SetupState failures despite §7.4 fixes:

1. wuauserv — Setup's Assert-Steps pass at exit but WaaSMedicSvc (tamper-protected,
   cannot be disabled) polls SCM ~30-60s and resets StartType to Manual.
   Fix: write Start=4 directly to registry key (SCM API alone is overrideable);
   deny WaaSMedicSvc write access to wuauserv registry key via ACL (best-effort,
   non-fatal if WinRM session lacks permission); re-enforce Start=4 after DISM
   in Cleanup; add Pre-Final re-affirmation block before Final gate.

2. AutoAdminLogon — Step 5c re-affirms it mid-script, but Steps 7-10 take hours
   and no Final gate check catches a late reset. Fix: add Pre-Final re-affirmation
   block (same as wuauserv) + add Assert-Step 'Final' 'AutoAdminLogon=1' to Final gate.

Also update WinISO default path to April 2026 refresh ISO.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-10 16:56:28 +02:00
Simone 34b33c5011 fix(winrm-https): PS 5.1 Test-WSMan has no -SessionOption — remove from all call sites
Test-WSMan in Windows PowerShell 5.1 does not support -SessionOption (WSManSessionOption),
causing "Cannot find a parameter matching the name 'SessionOption'" at runtime.

Prepare-WinBuild2025.ps1:
  - Remove Test-WSMan connectivity check step entirely
  - Open New-PSSession directly (handles -SkipCACheck via PSSessionOption)
  - Wrap New-PSSession in try/catch with the same actionable error message
  - Remove $wsmOpt (WSManSessionOption) — no longer needed
  Wait-GuestWinRMReady: replace Test-WSMan probe with New-PSSession probe + Remove-PSSession

Wait-VMReady.ps1:
  - Remove $wsmOpt entirely
  - Replace Test-WSMan -UseSSL -SessionOption with Test-NetConnection -Port 5986
    (TCP open on 5986 = HTTPS listener up = VM ready; credentials not available here)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-10 15:58:57 +02:00
Simone 68cde01c9d security(sprint1): §1.1/1.3/1.4 — WinRM HTTPS/5986, SHA256 pinning infra, IP regex per-octet
§1.4 — Replace loose IP ValidatePattern with per-octet regex in 4 scripts
  (Invoke-CIJob, Invoke-RemoteBuild, Get-BuildArtifacts, Wait-VMReady)

§1.1 — Migrate all WinRM connections from HTTP/5985 to HTTPS/5986
  - Deploy post-install.ps1: remove AllowUnencrypted=true; self-signed cert + HTTPS listener
    already present; firewall rule restricted to 192.168.79.0/24
  - Setup-WinBuild2025.ps1: assert AllowUnencrypted=false
  - Prepare-WinBuild2025.ps1: preflight uses TCP/5986; Test-WSMan -UseSSL -Port 5986;
    New-PSSession -UseSSL -Port 5986; host AllowUnencrypted save/restore removed (not needed for HTTPS)
  - Invoke-RemoteBuild, Get-BuildArtifacts: New-PSSession -UseSSL -Port 5986 -Authentication Basic
  - Wait-VMReady: New-WSManSessionOption + Test-WSMan -Port 5986 -UseSSL
  - Validate-DeployState, Validate-SetupState: Invoke-Command -UseSSL -Port 5986,
    AllowUnencrypted check → false; AllowUnencrypted host-side removed from both
  - Docs: PLAN, README, ARCHITECTURE, BEST-PRACTICES, HOST-SETUP, WINDOWS-TEMPLATE-SETUP,
    LINUX-TEMPLATE-SETUP, TODO updated

§1.3 — SHA256 hash pinning infrastructure
  - Assert-Hash function + $script:Hashes hashtable added to Setup-WinBuild2025.ps1
  - Assert-Hash called after dotnet-install.ps1, python installer, vs_buildtools.exe downloads
  - Hashes initialized to '' (warn-skip); must be filled before next snapshot refresh

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-10 14:46:41 +02:00
Simone 41611d46a7 fix(template): §7.4 Validate-SetupState -Remediate flag + Setup/Deploy tweaks 2026-05-10 14:26:35 +02:00
Simone 7d6ae42fcf fix(template): §7.4 e2e fixes + autologin + validation scripts
Fix emerged during §7.4 e2e test run (2026-05-10):
- Deploy: set UsoSvc to Manual explicitly (Server 2025 default = Automatic)
- Setup cleanup: re-apply Set-Service Disabled on wuauserv/UsoSvc after DISM
  StartComponentCleanup (WaaSMedicSvc resets StartType during component store cleanup)
- Deploy + Setup: add Administrator autologin (AutoAdminLogon, DefaultUserName,
  DefaultPassword, DefaultDomainName) in post-install.ps1; Assert-Step 5c validates it
- Add Validate-DeployState.ps1: standalone host-side check of all Deploy-set state
- Add Validate-SetupState.ps1: standalone host-side check of full post-Setup state
- Mark §7.4, §7.1 and §7.2 e2e validation items as complete in TODO.md
- Update docs: WINDOWS-TEMPLATE-SETUP.md (arch table, validation scripts section,
  autologin in confine Deploy/Setup); TEST-7.4-e2e.md checklist marked done

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-10 11:30:11 +02:00
Simone 260e275b89 refactor(template): §7 — move OS hardening to Deploy, Setup becomes validation-only
§7.1 — Setup Steps 1/3/4b/5b/5c converted to Assert-Step only:
  - Deploy post-install.ps1 now owns: Firewall (all profiles disabled),
    WinRM MaxMemory=2048MB/IdleTimeout=2h/MaxProcesses=25/StartupType=Automatic,
    lock screen (NoLockScreen), SM GPO policy key + scheduled task disable,
    DisableCAD in Winlogon, OOBE non-policy key.
  - Setup no longer re-applies these — validates them, throws if Deploy missed any.

§7.2 — WU lifecycle Strategy B:
  - Deploy: replaces sc.exe disable with GPO locks only (NoAutoUpdate=1,
    DisableWindowsUpdateAccess=1); services remain Manual (Windows default).
  - Setup Step 6 Step A already clears these locks before COM API; Step 6b
    permanently disables services post-update. No Setup changes needed.

§7.3 — Docs updated:
  - Deploy .DESCRIPTION reflects full hardening ownership.
  - Setup .DESCRIPTION marks validation-only steps, updates step ordering rationale.
  - WINDOWS-TEMPLATE-SETUP.md: three-script architecture table, CI-WinBuild.vmx
    path, Fase C step list + rationale + validation table updated.

TODO: §7.1/7.2/7.3 marked done. §7.4 e2e pending (requires new VM snapshot).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-10 01:27:29 +02:00
Simone 96b65d40de feat(template): add Deploy-WinBuild2025.ps1 + autounattend; update TODO
template/Deploy-WinBuild2025.ps1:
  New host-side script that drives the unattended Windows install phase:
  creates the VM, injects autounattend.xml (disabling Defender/firewall/UAC
  before Setup-WinBuild2025.ps1 runs), boots from ISO, waits for first-boot.

template/autounattend.template.xml:
  WiM-based answer file template for Windows Server 2025 unattended install.
  Sets DisableAntiSpyware GPO + RTP off so Defender is fully off at first
  logon (prerequisite for Setup-WinBuild2025.ps1 Step-2 validation-only path).

TODO.md:
  - Date + wording updated (2026-05-10)
  - §1.1: file refs updated to post-refactor line numbers (Step 3 WinRM,
    Deploy-WinBuild2025 Enable-PSRemoting, Invoke-RemoteBuild, Get-BuildArtifacts)
  - §1.2: TrustedHosts audit status corrected (Setup-Host.ps1 never sets '*';
    Prepare appends IP and restores in finally)
  - §1.3: Python/dotnet/VS Build Tools line refs updated
  - §1.5: PAT security constraints expanded with grep-on-log safety net rule
  - §1.6: Defender/Firewall/UAC state updated to reflect Deploy vs Setup split
  - §3.3 deploy reference: VMX path corrected to CI-WinBuild.vmx
  - §3.3 doc ref: WINDOWS-TEMPLATE-SETUP updated to list Deploy step
2026-05-10 01:01:43 +02:00
Simone ab636a0ec1 refactor(template): Defender validation-only + auto WU-reboot loop in Prepare
Setup-WinBuild2025.ps1 (Step 2):
- Defender is now disabled at deploy time by Deploy-WinBuild2025.ps1 via
  DisableAntiSpyware=1 GPO + RTP off during unattended install.
- Step 2 reduced to a single Assert-Step sanity check (GPO key present = 1).
  Exclusion paths removed: scanner is not running, they would be moot.

Prepare-WinBuild2025.ps1 (Setup invocation):
- Replace one-shot Invoke-Command + manual 're-run with -SkipWindowsUpdate'
  message with an automated loop (max 10 iterations):
  * Invoke-GuestSetup helper runs Setup inside the VM and returns exit code.
  * Exit 3010 (ERROR_SUCCESS_REBOOT_REQUIRED) triggers Restart-Computer on
    the guest, waits for WinRM via Wait-GuestWinRMReady (20 min timeout),
    reopens PSSession and loops.
  * Exit 0 breaks the loop; any other code throws immediately.
  * Hard cap prevents infinite loops if WU never converges.
2026-05-10 01:01:30 +02:00
Simone 644258f59c 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)
2026-05-09 23:28:36 +02:00
Simone d4099b94fd feat(template): add Assert-Step validation to all provisioning steps
Setup-TemplateVM.ps1:
- Added Assert-Step validation after each install step (WinRM, Firewall,
  User, UAC, Defender, .NET, Python, VS Build Tools, Toolchain, Cleanup)
- Final pre-snapshot gate: all checks must pass before snapshot is allowed
- Disabled Windows Defender + Firewall before installs (saves 5-15 min)
- Disabled UAC (EnableLUA=0, LocalAccountTokenFilterPolicy=1)

Prepare-TemplateSetup.ps1:
- Pre-flight checks: IP validation, TCP/5985 reachability, script presence
- Host WinRM: AllowUnencrypted, TrustedHosts config
- Guest prep: C:\CI exists, file copied, size match
- Post-setup remote validation (9 checks): WinRM, user+admin, UAC,
  firewall, .NET, Python, MSBuild, CI dirs
- StoreCredential flow: New-StoredCredential for BuildVMGuest target
2026-05-09 21:15:39 +02:00
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
Simone dd238121b3 chore: initial commit local CI/CD system (e2e verified, production-ready)
Sistema CI locale basato su VMware Workstation + Gitea Actions + act_runner.
Testato e2e con nsis-plugin-nsinnounp (MSBuild + Python, 4 configurazioni parallele).

- scripts/: Invoke-CIJob, Invoke-RemoteBuild, New/Remove-BuildVM, Wait-VMReady, Get-BuildArtifacts
- runner/: act_runner config (windows-build label, capacity 4)
- gitea/workflows/: build-nsis.yml (template per progetti MSBuild/Python)
- template/: script di provisioning template VM (VS BuildTools 2026, .NET SDK 10, Python 3.13)
- docs/: ARCHITECTURE, CI-FLOW, OPTIMIZATION, BEST-PRACTICES, Setup-GiteaSSH

Verificato: e2e-009 SUCCESS in 02:09, cleanup automatico VM confermato.
2026-05-08 23:25:50 +02:00