forked from wangbo/easyai
fix(deploy): 随部署仓库下发正式更新清单
This commit is contained in:
@@ -183,6 +183,8 @@ update.sh 脚本用于自动更新 EasyAI 应用,包含以下功能:
|
||||
|
||||
更新执行器 `easyai-updater` 由 Watchtower 单独守护,默认每 24 小时检查并更新自身。它的任务状态保存在宿主机 `data/update-state` 中,自身更新或意外重启后会继续恢复未完成任务;Watchtower 不再接管三个核心服务,因此页面任务结果不会与后台静默替换相互冲突。
|
||||
|
||||
受控更新使用仓库内的 `system-update/release-manifest.json` 作为稳定发布清单,Compose 会以只读方式挂载给 updater。发布新正式镜像时必须同步更新清单中的不可变摘要、镜像大小和版本标识;服务器执行 `update.sh` 拉取部署仓库后即可获得清单,不需要手工向运行目录复制文件。
|
||||
|
||||
存量部署无需手工编辑 `.env`。更新脚本会从 `scripts/update-env.d/010-managed-system-update.env` 应用以下缺省值:
|
||||
|
||||
```dotenv
|
||||
|
||||
+2
-1
@@ -338,10 +338,11 @@ services:
|
||||
- UPDATE_HEALTH_TIMEOUT_MS=${UPDATE_HEALTH_TIMEOUT_MS:-300000}
|
||||
- DOCKER_CONFIG_FILE=/run/secrets/docker-config.json
|
||||
- UPDATE_STATE_DIR=/var/lib/easyai-updater
|
||||
- UPDATE_MANIFEST_FILE=/var/lib/easyai-updater/release-manifest.json
|
||||
- UPDATE_MANIFEST_FILE=/etc/easyai-updater/release-manifest.json
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
- ${DOCKER_CONFIG_FILE:-/root/.docker/config.json}:/run/secrets/docker-config.json:ro
|
||||
- ./system-update/release-manifest.json:/etc/easyai-updater/release-manifest.json:ro
|
||||
- ./data/update-state:/var/lib/easyai-updater
|
||||
tmpfs:
|
||||
- /tmp:mode=1777
|
||||
|
||||
@@ -17,6 +17,7 @@ cp \
|
||||
"$REPO_ROOT/easyai-proxy.conf.sample" \
|
||||
"$TMP_DIR/"
|
||||
mkdir -p "$TMP_DIR/scripts"
|
||||
mkdir -p "$TMP_DIR/system-update"
|
||||
cp \
|
||||
"$REPO_ROOT/scripts/init-security-env.sh" \
|
||||
"$REPO_ROOT/scripts/init-security-origin.sh" \
|
||||
@@ -24,6 +25,7 @@ cp \
|
||||
"$REPO_ROOT/scripts/init-server-http-bind-ip.sh" \
|
||||
"$REPO_ROOT/scripts/check-redis-persistence.sh" \
|
||||
"$TMP_DIR/scripts/"
|
||||
cp "$REPO_ROOT/system-update/release-manifest.json" "$TMP_DIR/system-update/"
|
||||
|
||||
cd "$TMP_DIR"
|
||||
|
||||
@@ -166,6 +168,7 @@ mounts = {(item.get("source"), item.get("target")) for item in updater.get("volu
|
||||
assert ("/var/run/docker.sock", "/var/run/docker.sock") in mounts, mounts
|
||||
assert any(target == "/var/lib/easyai-updater" for _, target in mounts), mounts
|
||||
assert any(target == "/run/secrets/docker-config.json" for _, target in mounts), mounts
|
||||
assert any(target == "/etc/easyai-updater/release-manifest.json" for _, target in mounts), mounts
|
||||
|
||||
server_env = server.get("environment") or {}
|
||||
updater_env = updater.get("environment") or {}
|
||||
@@ -176,6 +179,7 @@ assert server_env.get("SYSTEM_UPDATE_MODE") == "managed", server_env.get("SYSTEM
|
||||
assert str(server_env.get("EASYAI_DEPLOYMENT_SCHEMA_VERSION")) == "2"
|
||||
assert str(updater_env.get("UPDATE_HEALTH_TIMEOUT_MS")) == "300000"
|
||||
assert updater_env.get("DOCKER_CONFIG_FILE") == "/run/secrets/docker-config.json"
|
||||
assert updater_env.get("UPDATE_MANIFEST_FILE") == "/etc/easyai-updater/release-manifest.json"
|
||||
assert updater.get("labels", {}).get("com.centurylinklabs.watchtower.enable") == "true"
|
||||
assert watchtower.get("environment", {}).get("WATCHTOWER_POLL_INTERVAL") == "86400"
|
||||
assert watchtower.get("environment", {}).get("WATCHTOWER_CLEANUP") == "true"
|
||||
@@ -185,6 +189,33 @@ for service in ("easyai-server", "ws-gateway", "easyai-web"):
|
||||
labels = services[service].get("labels") or {}
|
||||
assert labels.get("com.centurylinklabs.watchtower.enable") == "false", (service, labels)
|
||||
'
|
||||
|
||||
python3 - <<'PY'
|
||||
import json
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
manifest = json.loads(Path("system-update/release-manifest.json").read_text())
|
||||
assert manifest["schemaVersion"] == 1
|
||||
assert manifest["channel"] == "stable"
|
||||
assert manifest["platform"] == "linux/amd64"
|
||||
assert manifest["managedUpdateAllowed"] is True
|
||||
assert manifest["rollbackSafe"] is True
|
||||
assert manifest["minimumUpdaterVersion"] == "1.0.0"
|
||||
assert manifest["minimumDeploymentSchemaVersion"] == 2
|
||||
assert int(manifest["requiredFreeBytes"]) > 0
|
||||
components = {item["key"]: item for item in manifest["components"]}
|
||||
assert set(components) == {"server-main", "ws-gateway", "web"}
|
||||
expected_images = {
|
||||
"server-main": "registry.cn-shanghai.aliyuncs.com/comfy-ai/comfy-server",
|
||||
"ws-gateway": "registry.cn-shanghai.aliyuncs.com/easyaigc/wsgateway",
|
||||
"web": "registry.cn-shanghai.aliyuncs.com/comfy-ai/one-ai",
|
||||
}
|
||||
for key, image in expected_images.items():
|
||||
assert components[key]["image"] == image
|
||||
assert re.fullmatch(r"sha256:[a-f0-9]{64}", components[key]["digest"])
|
||||
assert int(components[key]["imageSizeBytes"]) > 0
|
||||
PY
|
||||
}
|
||||
|
||||
assert_legacy_update_contract() {
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
{
|
||||
"schemaVersion": 1,
|
||||
"channel": "stable",
|
||||
"releaseId": "managed-update-20260927",
|
||||
"productVersion": "3.18.0.20260927",
|
||||
"platform": "linux/amd64",
|
||||
"publishedAt": "2026-09-27T11:15:00+08:00",
|
||||
"managedUpdateAllowed": true,
|
||||
"scheduledUpdateAllowed": true,
|
||||
"rollbackSafe": true,
|
||||
"minimumUpdaterVersion": "1.0.0",
|
||||
"minimumDeploymentSchemaVersion": 2,
|
||||
"requiredFreeBytes": 8589934592,
|
||||
"components": [
|
||||
{
|
||||
"key": "server-main",
|
||||
"image": "registry.cn-shanghai.aliyuncs.com/comfy-ai/comfy-server",
|
||||
"digest": "sha256:38cbe3fdb151b54dd729071e1368ad0670710a5b0160aa5fdbc486737bf5b2ef",
|
||||
"imageSizeBytes": 2723428239,
|
||||
"buildId": "db43ef28"
|
||||
},
|
||||
{
|
||||
"key": "ws-gateway",
|
||||
"image": "registry.cn-shanghai.aliyuncs.com/easyaigc/wsgateway",
|
||||
"digest": "sha256:661eb2dc5ca6e458e00b8c2e2f068c2a1773694a3017982ecb1aa42de677468e",
|
||||
"imageSizeBytes": 1982899440,
|
||||
"buildId": "db43ef28"
|
||||
},
|
||||
{
|
||||
"key": "web",
|
||||
"image": "registry.cn-shanghai.aliyuncs.com/comfy-ai/one-ai",
|
||||
"digest": "sha256:bc82b10e08886904b2ef4a5c2fe7727b1dac9114c7493b4f2acc0b1a8ef5e29c",
|
||||
"imageSizeBytes": 1038564864,
|
||||
"buildId": "188b0ee9"
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user