feat: implement dashboard download caching and fallback mechanism

- Add local file caching for dashboard downloads with version validation
- Implement fallback to 'latest' version if specific version download fails
- Add robust error handling in CLI check_dashboard to prevent crashes
- Remove dashboard caching from smoke tests (backend-only mode)
This commit is contained in:
LIghtJUNction
2026-03-15 19:14:13 +08:00
parent c18165909e
commit 04aee2890a
3 changed files with 113 additions and 36 deletions
+3 -1
View File
@@ -39,7 +39,9 @@ jobs:
- name: Run smoke tests
run: |
uv run main.py &
# uv run main.py &
uv tool install -e . --force
astrbot run --backend-only
APP_PID=$!
echo "Waiting for application to start..."
+10 -7
View File
@@ -45,13 +45,16 @@ async def check_dashboard(astrbot_root: Path) -> None:
abort=True,
):
click.echo("Installing dashboard...")
await download_dashboard(
path="data/dashboard.zip",
extract_path=str(astrbot_root / "data"),
version=f"v{VERSION}",
latest=False,
)
click.echo("Dashboard installed successfully")
try:
await download_dashboard(
path="data/dashboard.zip",
extract_path=str(astrbot_root / "data"),
version=f"v{VERSION}",
latest=False,
)
click.echo("Dashboard installed successfully")
except Exception as e:
click.echo(f"Failed to install dashboard: {e}")
case str():
if VersionComparator.compare_version(VERSION, dashboard_version) <= 0:
+100 -28
View File
@@ -285,35 +285,107 @@ async def download_dashboard(
else:
zip_path = Path(path).absolute()
if latest or len(str(version)) != 40:
ver_name = "latest" if latest else version
dashboard_release_url = f"https://astrbot-registry.soulter.top/download/astrbot-dashboard/{ver_name}/dist.zip"
logger.info(
f"准备下载指定发行版本的 AstrBot WebUI 文件: {dashboard_release_url}",
)
try:
await download_file(
dashboard_release_url,
str(zip_path),
show_progress=True,
# 缓存机制
cache_dir = Path(get_astrbot_data_path()).absolute() / "cache"
if not cache_dir.exists():
cache_dir.mkdir(parents=True, exist_ok=True)
use_cache = False
# Only use cache if not requesting "latest" (we don't know the version yet)
if not latest and version:
cache_name = f"dashboard_{version}.zip"
cache_path = cache_dir / cache_name
if cache_path.exists():
logger.info(f"发现本地缓存的管理面板文件: {cache_path}")
try:
with zipfile.ZipFile(cache_path, "r") as z:
if z.testzip() is None:
logger.info("缓存文件校验通过,将直接使用缓存。")
if str(cache_path) != str(zip_path):
shutil.copy(cache_path, zip_path)
use_cache = True
else:
logger.warning("缓存文件损坏,将重新下载。")
os.remove(cache_path)
except zipfile.BadZipFile:
logger.warning("缓存文件损坏 (BadZipFile),将重新下载。")
os.remove(cache_path)
if not use_cache:
if latest or len(str(version)) != 40:
ver_name = "latest" if latest else version
dashboard_release_url = f"https://astrbot-registry.soulter.top/download/astrbot-dashboard/{ver_name}/dist.zip"
logger.info(
f"准备下载指定发行版本的 AstrBot WebUI 文件: {dashboard_release_url}",
)
except BaseException as _:
if latest:
dashboard_release_url = "https://github.com/AstrBotDevs/AstrBot/releases/latest/download/dist.zip"
else:
dashboard_release_url = f"https://github.com/AstrBotDevs/AstrBot/releases/download/{version}/dist.zip"
try:
await download_file(
dashboard_release_url,
str(zip_path),
show_progress=True,
)
except BaseException as _:
try:
if latest:
dashboard_release_url = "https://github.com/AstrBotDevs/AstrBot/releases/latest/download/dist.zip"
else:
dashboard_release_url = f"https://github.com/AstrBotDevs/AstrBot/releases/download/{version}/dist.zip"
if proxy:
dashboard_release_url = f"{proxy}/{dashboard_release_url}"
await download_file(
dashboard_release_url,
str(zip_path),
show_progress=True,
)
except Exception as e:
if not latest:
logger.warning(
f"下载指定版本({version})失败: {e},尝试下载最新版本。"
)
await download_dashboard(
path=path,
extract_path=extract_path,
latest=True,
proxy=proxy,
)
return
raise e
else:
url = f"https://github.com/AstrBotDevs/astrbot-release-harbour/releases/download/release-{version}/dist.zip"
logger.info(f"准备下载指定版本的 AstrBot WebUI: {url}")
if proxy:
dashboard_release_url = f"{proxy}/{dashboard_release_url}"
await download_file(
dashboard_release_url,
str(zip_path),
show_progress=True,
)
else:
url = f"https://github.com/AstrBotDevs/astrbot-release-harbour/releases/download/release-{version}/dist.zip"
logger.info(f"准备下载指定版本的 AstrBot WebUI: {url}")
if proxy:
url = f"{proxy}/{url}"
await download_file(url, str(zip_path), show_progress=True)
url = f"{proxy}/{url}"
await download_file(url, str(zip_path), show_progress=True)
# 下载完成后存入缓存
try:
save_cache_name = None
if not latest and version:
save_cache_name = f"dashboard_{version}.zip"
else:
# 尝试从下载的文件中读取版本号
try:
with zipfile.ZipFile(zip_path, "r") as z:
for v_path in ["dist/assets/version", "assets/version"]:
try:
with z.open(v_path) as f:
v = f.read().decode("utf-8").strip()
save_cache_name = f"dashboard_{v}.zip"
break
except KeyError:
continue
except Exception:
pass
if save_cache_name:
cache_save_path = cache_dir / save_cache_name
if str(zip_path) != str(cache_save_path):
shutil.copy(zip_path, cache_save_path)
logger.info(f"已缓存管理面板文件至: {cache_save_path}")
except Exception as e:
logger.warning(f"缓存管理面板文件失败: {e}")
with zipfile.ZipFile(zip_path, "r") as z:
z.extractall(extract_path)