Private/DockerStackHelpers.ps1
|
# DockerStackHelpers.ps1 # Helpers de Publish-DockerStack: lectura/validación de stack.yaml e identidad de release. # Comparten estilo con PublishHelpers.ps1 (Get-ReleaseId, Test-CleanWorktree). <# .SYNOPSIS Lee y valida stack.yaml (+ presencia de .env) y devuelve la configuración normalizada. .DESCRIPTION Fuente única de verdad de la configuración de un stack Docker Compose. Valida lo mínimo para fallar temprano (server real, nombre, modo de build, imagen en transfer) y normaliza health/postDeploy/include a formas estables que el cmdlet consume sin volver a chequear. .PARAMETER ProjectRoot Directorio donde viven stack.yaml, el compose y .env. .EXAMPLE $cfg = Get-DockerStackConfig -ProjectRoot (Get-Location).Path #> function Get-DockerStackConfig { [CmdletBinding()] param( [Parameter(Mandatory = $true)] [string]$ProjectRoot ) $stackYaml = Join-Path $ProjectRoot 'stack.yaml' if (-not (Test-Path $stackYaml)) { throw "No se encontró stack.yaml en $ProjectRoot. Ejecute 'Publish-DockerStack -Init' primero." } if (-not (Test-Path (Join-Path $ProjectRoot '.env'))) { throw "No se encontró .env en $ProjectRoot. Cree el archivo con las variables/secretos del stack (Publish-DockerStack -Init lo genera)." } $y = (Get-Content $stackYaml -Raw) | ConvertFrom-Yaml $server = if ($y.server) { [string]$y.server } else { $null } if (-not $server) { throw "stack.yaml: falta 'server' (alias en ~/.ssh/config)." } if ($server -eq 'your-ssh-alias') { throw "stack.yaml contiene el valor de ejemplo 'your-ssh-alias'. Cambie 'server' por el alias SSH real." } $stack = $y.stack if (-not $stack -or -not $stack.name) { throw "stack.yaml: falta 'stack.name'." } $name = [string]$stack.name $composeFile = if ($stack.composeFile) { [string]$stack.composeFile } else { 'docker-compose.yml' } $version = if ($stack.version) { [string]$stack.version } else { '0.0.0' } $build = if ($stack.build) { [string]$stack.build } else { 'server' } if ($build -notin @('server', 'transfer', 'none')) { throw "stack.yaml: 'stack.build' = '$build' no soportado. Use server | transfer | none." } $image = if ($stack.image) { [string]$stack.image } else { $null } if ($build -eq 'transfer' -and -not $image) { throw "stack.yaml: build:transfer requiere 'stack.image' (imagen a serializar con docker save/load)." } # include -> array de strings (rutas relativas) $include = @() if ($y.include) { $include = @($y.include | ForEach-Object { [string]$_ }) } # health -> modo url/container (url tiene precedencia) o ninguno $healthMode = $null; $healthTarget = $null $healthRetries = 30; $healthInterval = 4 if ($y.health) { if ($y.health.retries) { $healthRetries = [int]$y.health.retries } if ($y.health.interval) { $healthInterval = [int]$y.health.interval } if ($y.health.url) { $healthMode = 'url'; $healthTarget = [string]$y.health.url } elseif ($y.health.container) { $healthMode = 'container'; $healthTarget = [string]$y.health.container } } # postDeploy -> array de strings $postDeploy = @() if ($y.postDeploy) { $postDeploy = @($y.postDeploy | ForEach-Object { [string]$_ }) } return [pscustomobject]@{ Server = $server Name = $name Version = $version ComposeFile = $composeFile Build = $build Image = $image Include = $include HealthMode = $healthMode HealthTarget = $healthTarget HealthRetries = $healthRetries HealthInterval = $healthInterval PostDeploy = $postDeploy } } <# .SYNOPSIS Compone el identificador de release del stack: v{version}+{gitSha} (coherente con ADR 0003). .DESCRIPTION Usa el sha corto de git para identificar unívocamente cada despliegue. A diferencia de Publish-NodeApi (build:false), aquí se empaqueta el árbol de trabajo, por lo que un árbol sucio no es un error: se marca el release con '-dirty' y se avisa (salvo -AllowDirty). Sin repo git, cae a 'v{version}'. .PARAMETER ProjectRoot Directorio del stack (dentro del repo git). .PARAMETER Version Versión declarada en stack.yaml (stack.version). .PARAMETER AllowDirty Silencia el aviso de árbol sucio. .EXAMPLE $release = Get-DockerStackRelease -ProjectRoot $cwd -Version '0.1.0' #> function Get-DockerStackRelease { [CmdletBinding()] param( [Parameter(Mandatory = $true)] [string]$ProjectRoot, [Parameter(Mandatory = $true)] [string]$Version, [switch]$AllowDirty ) $sha = (& git -C $ProjectRoot rev-parse --short HEAD 2>$null) if ($LASTEXITCODE -ne 0 -or -not $sha) { return "v$Version" } if (-not (Test-CleanWorktree -Path $ProjectRoot)) { if (-not $AllowDirty) { Write-Warning "Árbol de git sucio: el release se marca '+$sha-dirty'. Use -AllowDirty para silenciar este aviso." } $sha = "$sha-dirty" } return (Get-ReleaseId -Version $Version -ShortSha $sha) } |