Private/Resolve-ParallelRunProfile.ps1
|
function Resolve-ParallelRunProfile { <# .SYNOPSIS Parses and validates a ParallelRun JSON profile, returning fully-resolved service definitions (name, inner shell command, working directory, color) ready to launch. .DESCRIPTION Kept separate from Invoke-ParallelRun so the parsing/validation/resolution logic (relative-cwd handling, color assignment, env-var folding) can be unit tested without spawning any processes. #> [CmdletBinding()] param( [Parameter(Mandatory)] [string]$ProfilePath ) if (-not (Test-Path $ProfilePath)) { throw "Profile not found: $ProfilePath" } $resolvedPath = (Resolve-Path $ProfilePath).Path $profileDir = Split-Path $resolvedPath -Parent $config = Get-Content $resolvedPath -Raw | ConvertFrom-Json if (-not $config.services -or $config.services.Count -eq 0) { throw "Profile has no 'services' array — see examples/profile.example.json." } # Default palette; a service can pin its own color in the profile (e.g. to keep a # service's color stable across profiles that add/remove other services). $palette = @('Cyan', 'Green', 'Yellow', 'Magenta', 'Blue', 'DarkCyan', 'DarkYellow', 'DarkGreen', 'Red') $services = [System.Collections.Generic.List[object]]::new() $i = 0 foreach ($s in $config.services) { if (-not $s.name -or -not $s.command) { throw "Every service needs a 'name' and a 'command'." } # Relative `cwd`s resolve against the profile file's own folder, not wherever # Invoke-ParallelRun happens to be called from — keeps profiles portable. $cwd = if ([string]::IsNullOrWhiteSpace($s.cwd)) { $profileDir } elseif ([System.IO.Path]::IsPathRooted($s.cwd)) { $s.cwd } else { [System.IO.Path]::GetFullPath((Join-Path $profileDir $s.cwd)) } $services.Add([pscustomobject]@{ Name = $s.name Cwd = $cwd Inner = New-ParallelRunInnerCommand -Command $s.command -Cwd $cwd -EnvVars $s.env Color = if ($s.color) { $s.color } else { $palette[$i % $palette.Count] } }) $i++ } [pscustomobject]@{ Name = $config.name ProfileDir = $profileDir ProfileName = [System.IO.Path]::GetFileNameWithoutExtension($resolvedPath) Services = $services } } |