#!/bin/bash # 仅规划/持久化已选应用的固定版本;由 update.sh 调用,不编辑 Compose。 APPLICATION_VERSION_MAP='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' application_selected() { [ -z "${UPDATE_SERVICES:-}" ] || [[ " ${UPDATE_SERVICES} " == *" $1 "* ]] } plan_application_versions() { local file="$1" service key option image value suffix base old_default APPLICATION_VERSION_WRITES=() while read -r service key option image; do value="${!option:-}" if [ -n "$value" ] && ! application_selected "$service"; then echo "❌ $option 要求在 UPDATE_SERVICES 中指定 $service;尚未修改环境或容器" >&2 return 1 fi application_selected "$service" || continue if [ -z "$value" ] && [ -n "${UPDATE_RELEASE_VERSION:-}" ]; then value="$UPDATE_RELEASE_VERSION"; fi if [ -z "$value" ]; then value="$(read_env_value "$file" "$key")"; fi if [ -z "$value" ]; then value="$(read_env_value "$file" VERSION)"; fi suffix='' if [ "$service" = easyai-web ]; then suffix='(-no-ssr|-hmg-ai|-easyai|-chinacuc)?'; fi if ! [[ "$value" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]{8}(\.[0-9]+)?${suffix}$ ]]; then echo "❌ $service 缺少固定版本:请指定 $option 或 UPDATE_RELEASE_VERSION,或在 .env 保留有效 $key;latest/dev 等浮动标签不能用于应用更新" >&2 return 1 fi APPLICATION_VERSION_WRITES+=("$key=$value") done <<< "$APPLICATION_VERSION_MAP" if [ -n "${UPDATE_RELEASE_VERSION:-}" ] && application_selected easyai-server && application_selected easyai-web; then # VERSION 仍保留兼容入口;改变它前先冻结未选中服务的旧继承值。 old_default="$(read_env_value "$file" VERSION)" while read -r service key option image; do application_selected "$service" && continue value="$(read_env_value "$file" "$key")" if [ -z "$value" ] && [ -n "$old_default" ]; then APPLICATION_VERSION_WRITES+=("$key=$old_default"); fi done <<< "$APPLICATION_VERSION_MAP" APPLICATION_VERSION_WRITES+=("VERSION=$UPDATE_RELEASE_VERSION") fi } apply_application_versions() { local file="$1" entry temporary temporary="$(mktemp "${file}.versions.XXXXXX")" cp "$file" "$temporary" chmod 600 "$temporary" for entry in "${APPLICATION_VERSION_WRITES[@]}"; do write_env_value "$temporary" "${entry%%=*}" "${entry#*=}" done mv "$temporary" "$file" for entry in "${APPLICATION_VERSION_WRITES[@]}"; do echo "📌 已持久化应用版本: $entry"; done } verify_application_version_images() { local file="$1" compose="$2" service key option image version actual configuration while read -r service key option image; do application_selected "$service" || continue version="$(read_env_value "$file" "$key")" # --images SERVICE includes dependency images on Compose 5. Read the # selected service from normalized config instead of comparing the list. configuration="$(sudo $compose config --format json "$service")" || return 1 actual="$(printf '%s' "$configuration" | python3 -c ' import json, sys try: image = json.load(sys.stdin)["services"][sys.argv[1]]["image"] if not isinstance(image, str): raise ValueError() print(image) except (ValueError, KeyError, TypeError): raise SystemExit("无法读取应用的有效镜像定义;尚未拉取或重建服务") ' "$service")" || return 1 if [ "$actual" != "$image:$version" ]; then echo "❌ $service 的有效镜像未使用 .env 中的固定版本 $key=$version;请通过部署仓库的受控迁移恢复镜像定义,尚未拉取或重建服务" >&2 return 1 fi done <<< "$APPLICATION_VERSION_MAP" }