function Get-ApplicationVersionPlan { param([string]$Path) $content = Get-Content $Path -Raw -Encoding UTF8 $selection = [string]$env:UPDATE_SERVICES $selected = @($selection.Trim() -split '\s+' | Where-Object { $_ }) $mapping = @( @('easyai-server','SERVER_VERSION','UPDATE_SERVER_VERSION','registry.cn-shanghai.aliyuncs.com/comfy-ai/comfy-server'), @('easyai-web','WEB_VERSION','UPDATE_WEB_VERSION','registry.cn-shanghai.aliyuncs.com/comfy-ai/one-ai'), @('ws-gateway','WS_GATEWAY_VERSION','UPDATE_GATEWAY_VERSION','registry.cn-shanghai.aliyuncs.com/easyaigc/wsgateway'), @('model-conversion-worker','MODEL_CONVERSION_WORKER_VERSION','UPDATE_WORKER_VERSION','registry.cn-shanghai.aliyuncs.com/easyaigc/model-conversion-worker'), @('easyai-updater','UPDATER_VERSION','UPDATE_UPDATER_VERSION','registry.cn-shanghai.aliyuncs.com/easyaigc/easyai-updater'), @('easyai-asg','ASG_VERSION','UPDATE_ASG_VERSION','registry.cn-shanghai.aliyuncs.com/easyaigc/agent-governance'), @('agent-memory','AMS_VERSION','UPDATE_AMS_VERSION','registry.cn-shanghai.aliyuncs.com/easyaigc/agent-memory') ) $plan = @() foreach ($item in $mapping) { $service,$key,$option,$image = $item $value = [Environment]::GetEnvironmentVariable($option) $isSelected = $selected.Count -eq 0 -or $service -in $selected if ($value -and -not $isSelected) { throw "$option 要求在 UPDATE_SERVICES 中指定 $service" } if (-not $isSelected) { continue } if (-not $value) { $value = $env:UPDATE_RELEASE_VERSION } if (-not $value) { $value = Get-EnvValue $content $key } if (-not $value) { $value = Get-EnvValue $content 'VERSION' } $pattern = '^\d+\.\d+\.\d+\.\d{8}(\.\d+)?$' if ($service -eq 'easyai-web') { $pattern = '^\d+\.\d+\.\d+\.\d{8}(\.\d+)?(-no-ssr|-hmg-ai|-easyai|-chinacuc)?$' } if (-not $value -or $value -notmatch $pattern) { throw "$service 缺少固定版本;请指定 $option / UPDATE_RELEASE_VERSION,latest/dev 等浮动标签不能用于应用更新" } $plan += [PSCustomObject]@{ Service=$service; Key=$key; Version=$value; Image=$image } } if ($env:UPDATE_RELEASE_VERSION -and ($selected.Count -eq 0 -or ('easyai-server' -in $selected -and 'easyai-web' -in $selected))) { $oldDefault = Get-EnvValue $content 'VERSION' foreach ($item in $mapping) { $service,$key,$option,$image = $item if ($selected.Count -gt 0 -and $service -notin $selected -and -not (Get-EnvValue $content $key) -and $oldDefault) { $plan += [PSCustomObject]@{ Service=''; Key=$key; Version=$oldDefault; Image='' } } } $plan += [PSCustomObject]@{ Service=''; Key='VERSION'; Version=$env:UPDATE_RELEASE_VERSION; Image='' } } return $plan } function Set-ApplicationVersions { param([string]$Path, [object[]]$Plan) $content = Get-Content $Path -Raw -Encoding UTF8 foreach ($item in $Plan) { $content = Set-EnvValue $content $item.Key $item.Version } [System.IO.File]::WriteAllText($Path, $content, [System.Text.UTF8Encoding]::new($false)) foreach ($item in $Plan) { Write-Host "📌 已持久化应用版本: $($item.Key)=$($item.Version)" } } function Test-ApplicationVersionImages { param([object[]]$Plan, [string[]]$ComposeCommand) foreach ($item in $Plan) { if (-not $item.Service) { continue } $args = @($ComposeCommand | Select-Object -Skip 1) + @('config','--format','json',$item.Service) $executable = $ComposeCommand[0] $configuration = & $executable @args if ($LASTEXITCODE -ne 0) { throw '无法读取应用的有效镜像定义;尚未拉取或重建服务' } try { # Compose includes dependencies even when a service is selected. # Keep the configuration in memory; do not log its environment. $resolved = ($configuration -join "`n") | ConvertFrom-Json -ErrorAction Stop $actual = $resolved.services.PSObject.Properties[$item.Service].Value.image } catch { throw '无法读取应用的有效镜像定义;尚未拉取或重建服务' } if ("$actual".Trim() -ne "$($item.Image):$($item.Version)") { throw "$($item.Service) 的有效镜像未使用环境中的固定版本;请通过部署仓库的受控迁移恢复镜像定义,尚未拉取或重建服务" } } }