From 25dfb8432412ef4e29bce02b6641b2993cf9873e Mon Sep 17 00:00:00 2001 From: sagitchu Date: Thu, 7 May 2026 19:51:18 +0800 Subject: [PATCH] fix: panel self-upgrade helper not recreating containers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add --force-recreate --remove-orphans to docker compose up so helper actually replaces running containers with newly pulled images - Add upgrade.log file for post-mortem debugging when helper fails - Add pre-flight validation for docker-compose.yml and .env - Fix "立即升级" button permanently disabled by relaxing the disabled condition so auto-check on click can fire --- .../internal/http/handler/system_upgrade.go | 42 ++++++++++++++--- vite-frontend/src/api/types.ts | 3 +- vite-frontend/src/pages/config.tsx | 46 ++++++++++++------- vite-frontend/src/pages/tunnel.tsx | 11 ++++- .../src/shadcn-bridge/heroui/select.tsx | 2 +- 5 files changed, 76 insertions(+), 28 deletions(-) diff --git a/go-backend/internal/http/handler/system_upgrade.go b/go-backend/internal/http/handler/system_upgrade.go index f085b5d..04c53de 100644 --- a/go-backend/internal/http/handler/system_upgrade.go +++ b/go-backend/internal/http/handler/system_upgrade.go @@ -180,13 +180,41 @@ func (e *systemUpgradeExecutor) selectComposeAsset(current []byte) string { } func (e *systemUpgradeExecutor) helperScript() string { - return strings.Join([]string{ - "set -eu", - `cd "$PANEL_DEPLOY_DIR"`, - "docker compose pull backend frontend", - "sleep 5", - "docker compose up -d backend frontend", - }, "\n") + return `set -eu +LOGFILE="$PANEL_DEPLOY_DIR/upgrade.log" +log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" | tee -a "$LOGFILE"; } + +cd "$PANEL_DEPLOY_DIR" +echo "" > "$LOGFILE" +log "开始面板升级" +log "工作目录: $(pwd)" + +if [ ! -f docker-compose.yml ]; then + log "错误: docker-compose.yml 不存在" + exit 1 +fi +if [ ! -f .env ]; then + log "错误: .env 不存在" + exit 1 +fi + +log "拉取新镜像..." +if ! docker compose pull backend frontend 2>&1 | tee -a "$LOGFILE"; then + log "错误: 拉取镜像失败" + exit 1 +fi + +log "等待旧容器释放资源..." +sleep 3 + +log "重启服务(force-recreate)..." +if ! docker compose up -d --force-recreate --remove-orphans backend frontend 2>&1 | tee -a "$LOGFILE"; then + log "错误: 重启服务失败" + exit 1 +fi + +log "升级完成" +` } func (e *systemUpgradeExecutor) buildHelperRunArgs(imageID, helperName string) ([]string, error) { diff --git a/vite-frontend/src/api/types.ts b/vite-frontend/src/api/types.ts index 7ded022..c97e9fd 100644 --- a/vite-frontend/src/api/types.ts +++ b/vite-frontend/src/api/types.ts @@ -508,8 +508,7 @@ export interface SystemUpgradeVersionApiData { capability: SystemUpgradeCapabilityApiData; } -export interface SystemUpgradeCheckApiData - extends SystemUpgradeVersionApiData { +export interface SystemUpgradeCheckApiData extends SystemUpgradeVersionApiData { releases: SystemUpgradeReleaseApiItem[]; } diff --git a/vite-frontend/src/pages/config.tsx b/vite-frontend/src/pages/config.tsx index 454835d..9c36276 100644 --- a/vite-frontend/src/pages/config.tsx +++ b/vite-frontend/src/pages/config.tsx @@ -1,3 +1,10 @@ +import type { + SystemUpgradeCheckApiData, + SystemUpgradeRunApiData, + SystemUpgradeReleaseApiItem, + SystemUpgradeVersionApiData, +} from "@/api/types"; + import { useState, useEffect, useRef } from "react"; import { useNavigate } from "react-router-dom"; import { AnimatePresence, motion } from "framer-motion"; @@ -32,12 +39,6 @@ import { runSystemUpgrade, type AnnouncementData, } from "@/api"; -import type { - SystemUpgradeCheckApiData, - SystemUpgradeRunApiData, - SystemUpgradeReleaseApiItem, - SystemUpgradeVersionApiData, -} from "@/api/types"; import { BackIcon, SettingsIcon } from "@/components/icons"; import { ThemeSettings } from "@/components/theme-settings"; import { isAdmin } from "@/utils/auth"; @@ -328,6 +329,12 @@ export default function ConfigPage() { systemUpgradeReleasesMatchChannel && systemUpgradeReleases.length > 0, ); + const canTriggerSystemUpgrade = Boolean( + !systemUpgradeLoading && + !systemUpgradeChecking && + !systemUpgradeExecuting && + systemUpgradeInfo?.capability.capable !== false, + ); const canOpenSystemUpgradeModal = Boolean( systemUpgradeInfo?.capability.capable && systemUpgradeHasConfirmedUpdate && @@ -421,7 +428,9 @@ export default function ConfigPage() { hasUpdate: response.data.channel === channel ? response.data.hasUpdate : false, latestVersion: - response.data.channel === channel ? response.data.latestVersion : "", + response.data.channel === channel + ? response.data.latestVersion + : "", }); } else { setSystemUpgradeInfo(null); @@ -512,7 +521,9 @@ export default function ConfigPage() { : "未获取到可用版本", ); - return Boolean(data.capability.capable && data.hasUpdate && data.releases?.length); + return Boolean( + data.capability.capable && data.hasUpdate && data.releases?.length, + ); } else { setSystemUpgradeReleases([]); setSystemUpgradeCheckedChannel(null); @@ -1568,7 +1579,8 @@ export default function ConfigPage() {

部署目录

- {systemUpgradeInfo?.capability.deployDir || "未获取到部署目录"} + {systemUpgradeInfo?.capability.deployDir || + "未获取到部署目录"}

@@ -1625,7 +1637,9 @@ export default function ConfigPage() { size="md" variant="bordered" onSelectionChange={(keys) => { - const selected = Array.from(keys)[0] as string | undefined; + const selected = Array.from(keys)[0] as + | string + | undefined; setSystemUpgradeSelectedVersion(selected || ""); }} @@ -1648,17 +1662,15 @@ export default function ConfigPage() {