diff --git a/playbook/shopfloor-setup/common/test/A-imaging/run.sh b/playbook/shopfloor-setup/common/test/A-imaging/run.sh new file mode 100755 index 0000000..fa15f65 --- /dev/null +++ b/playbook/shopfloor-setup/common/test/A-imaging/run.sh @@ -0,0 +1,108 @@ +#!/usr/bin/env bash +# A-imaging/run.sh - exercise the shopfloor-setup imaging chain on the win11 +# VM (Shopfloor baseline + per-PC-type stage scripts), stopping before +# PPKG / Intune handoff. Skips actual binary installs by default; orchestration- +# only test. Path B exercises the per-app installs. +# +# Usage: +# ./run.sh # Standard / Machine +# ./run.sh CMM # CMM (no subtype) +# ./run.sh Standard Timeclock # explicit +# +# Env: +# VM_DOMAIN override VM name (default win11) +# SKIP_REVERT=1 skip blank-slate snapshot revert (faster iteration) +# PREINSTALL_PATH UNC to a preinstall payload tree (default unset = skip 00-PreInstall installs) + +set -euo pipefail + +PCTYPE="${1:-Standard}" +PCSUBTYPE="${2:-Machine}" + +HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +TEST_ROOT="$(cd "$HERE/.." && pwd)" +REPO_ROOT="$(cd "$TEST_ROOT/../../../.." && pwd)" + +source "$TEST_ROOT/lib/qga.sh" + +if [[ -t 1 ]]; then + G='\033[32m'; R='\033[31m'; Y='\033[33m'; D='\033[0m' +else + G=''; R=''; Y=''; D='' +fi + +phase() { printf "\n${Y}=== %s ===${D}\n" "$*"; } +ok() { printf "${G}[ OK ]${D} %s\n" "$*"; } +fail() { printf "${R}[FAIL]${D} %s\n" "$*"; FAILED=1; } + +FAILED=0 + +phase "A-imaging.run for PCType=$PCTYPE PCSubType=$PCSUBTYPE" + +if [[ "${SKIP_REVERT:-}" != "1" ]]; then + vm_revert_to_blank_slate +else + log "skipping snapshot revert (SKIP_REVERT=1)" + vm_start_if_needed +fi + +phase "1. stage shopfloor-setup tree on samba share" +# Stage from the live repo into a host-samba-accessible location so the VM +# can robocopy across. +SETUP_STAGE="/home/camp/pxe-images/test-stage-A/shopfloor-setup" +rm -rf "/home/camp/pxe-images/test-stage-A" +mkdir -p "$SETUP_STAGE" +cp -r "$REPO_ROOT/playbook/shopfloor-setup/." "$SETUP_STAGE/" +log "staged $(du -sh "$SETUP_STAGE" | cut -f1) at $SETUP_STAGE" + +# Also stage the A-imaging chain runner (the PS1 we just wrote) so the VM +# can invoke it with parameters. +cp "$HERE/stage-image.ps1" "/home/camp/pxe-images/test-stage-A/stage-image.ps1" +# matrix.json + verify-state.ps1 for post-run state check +cp "$TEST_ROOT/matrix.json" "/home/camp/pxe-images/test-stage-A/matrix.json" +cp "$TEST_ROOT/lib/verify-state.ps1" "/home/camp/pxe-images/test-stage-A/verify-state.ps1" + +vm_mount_share + +phase "2. run imaging chain on VM" +qga_run_ps < C:\Enrollment\shopfloor-setup" +New-Item -ItemType Directory -Force -Path 'C:\Enrollment\shopfloor-setup' | Out-Null +robocopy $SetupSrcPath 'C:\Enrollment\shopfloor-setup' /E /R:2 /W:2 /NFL /NDL /NJH /NJS /NC /NS | Out-Null + +# --- Drop pc-type / pc-subtype / site-config --- +$PCType | Set-Content -Path 'C:\Enrollment\pc-type.txt' -Encoding ascii +$PCSubType | Set-Content -Path 'C:\Enrollment\pc-subtype.txt' -Encoding ascii +@{ + siteName = 'WJ (A-imaging test)' + shopfloorShareRoot = '\\192.168.122.1\pxe-images\tsgwp00525-v2\shared\dt\shopfloor' + common = @{ commonAppsSharePath = '\\192.168.122.1\pxe-images\tsgwp00525-v2\shared\dt\shopfloor\common\apps' } +} | ConvertTo-Json -Depth 5 | Set-Content -Path 'C:\Enrollment\site-config.json' -Encoding ascii + +# --- Stage PreInstall payload if provided --- +if ($PreInstallSrcPath -and (Test-Path $PreInstallSrcPath)) { + Log "copying $PreInstallSrcPath -> C:\PreInstall" + New-Item -ItemType Directory -Force -Path 'C:\PreInstall' | Out-Null + robocopy $PreInstallSrcPath 'C:\PreInstall' /E /R:2 /W:2 /NFL /NDL /NJH /NJS /NC /NS | Out-Null +} else { + Log "no PreInstall payload provided - 00-PreInstall step will skip" +} + +# --- Run stage scripts in order: Shopfloor baseline first, then per-PC-type --- +$setupDir = 'C:\Enrollment\shopfloor-setup' +$stageRan = @() + +function Run-StageScripts { + param([string]$Dir) + if (-not (Test-Path $Dir)) { return } + $scripts = Get-ChildItem $Dir -Filter '*.ps1' -File -ErrorAction SilentlyContinue | + Where-Object { $_.Name -match '^[0-9]{2}-' } | + Sort-Object Name + foreach ($s in $scripts) { + Log "==> $($s.FullName)" + $rc = 0 + & powershell.exe -NoProfile -ExecutionPolicy Bypass -File $s.FullName 2>&1 | ForEach-Object { Write-Host " $_" } + if ($LASTEXITCODE) { $rc = $LASTEXITCODE } + Log " exit $rc" + $script:stageRan += [pscustomobject]@{ Path = $s.FullName; ExitCode = $rc } + } +} + +# 1. Shopfloor baseline scripts (run for every PC type, including Standard) +Run-StageScripts (Join-Path $setupDir 'Shopfloor') + +# 2. Per-PC-type stage scripts. Standard / CMM / Keyence / etc each have their +# own subdir with numbered scripts. Skip "Shopfloor" since that's PCType==Shopfloor. +if ($PCType -ne 'Shopfloor') { + $typeDir = Join-Path $setupDir $PCType + Run-StageScripts $typeDir +} + +# --- Summary --- +Log "=== chain summary ===" +foreach ($r in $stageRan) { + $tag = if ($r.ExitCode -eq 0) { '[ OK ]' } else { '[FAIL]' } + Log " $tag rc=$($r.ExitCode) $($r.Path)" +} + +$failedCount = ($stageRan | Where-Object { $_.ExitCode -ne 0 }).Count +$totalCount = $stageRan.Count +Log "=== A-imaging summary: $($totalCount - $failedCount)/$totalCount stage scripts exited 0 ===" +if ($failedCount -gt 0) { exit 1 } +exit 0