mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-09-05 23:47:41 +08:00
fix(cli): align frontend download with version.py
Use FRONTEND_VERSION from version.py as the default frontend release target so local setup and auto-update install the matching frontend bundle. Closes #5693
This commit is contained in:
+4
-14
@@ -31,7 +31,6 @@ HEALTH_PATH = "/api/v1/system/global"
|
|||||||
HEALTH_TOKEN = "moviepilot"
|
HEALTH_TOKEN = "moviepilot"
|
||||||
FRONTEND_HEALTH_PATH = "/version.txt"
|
FRONTEND_HEALTH_PATH = "/version.txt"
|
||||||
BACKEND_RELEASES_API = "https://api.github.com/repos/jxxghp/MoviePilot/releases"
|
BACKEND_RELEASES_API = "https://api.github.com/repos/jxxghp/MoviePilot/releases"
|
||||||
FRONTEND_RELEASES_API = "https://api.github.com/repos/jxxghp/MoviePilot-Frontend/releases"
|
|
||||||
LOCAL_HOSTS = {"0.0.0.0", "::", "::1", "", "localhost"}
|
LOCAL_HOSTS = {"0.0.0.0", "::", "::1", "", "localhost"}
|
||||||
MANAGED_ACTIVE_STATES = {"running", "starting"}
|
MANAGED_ACTIVE_STATES = {"running", "starting"}
|
||||||
AUTO_UPDATE_ENABLED_VALUES = {"true", "release", "dev"}
|
AUTO_UPDATE_ENABLED_VALUES = {"true", "release", "dev"}
|
||||||
@@ -279,9 +278,8 @@ def _auto_update_mode() -> str:
|
|||||||
return SystemHelper.get_auto_update_mode()
|
return SystemHelper.get_auto_update_mode()
|
||||||
|
|
||||||
|
|
||||||
def _resolve_auto_update_targets(mode: str) -> tuple[Optional[str], Optional[str]]:
|
def _resolve_auto_update_targets(mode: str) -> Optional[str]:
|
||||||
backend_prefix = _release_prefix(APP_VERSION)
|
backend_prefix = _release_prefix(APP_VERSION)
|
||||||
frontend_prefix = _release_prefix(_installed_frontend_version() or APP_VERSION)
|
|
||||||
|
|
||||||
if mode == "dev":
|
if mode == "dev":
|
||||||
current_branch = _git_current_branch()
|
current_branch = _git_current_branch()
|
||||||
@@ -295,13 +293,7 @@ def _resolve_auto_update_targets(mode: str) -> tuple[Optional[str], Optional[str
|
|||||||
repo="jxxghp/MoviePilot",
|
repo="jxxghp/MoviePilot",
|
||||||
prefix=backend_prefix,
|
prefix=backend_prefix,
|
||||||
)
|
)
|
||||||
|
return backend_ref
|
||||||
frontend_version = _latest_release_tag(
|
|
||||||
FRONTEND_RELEASES_API,
|
|
||||||
repo="jxxghp/MoviePilot-Frontend",
|
|
||||||
prefix=frontend_prefix,
|
|
||||||
)
|
|
||||||
return backend_ref, frontend_version
|
|
||||||
|
|
||||||
|
|
||||||
def _best_effort_auto_update() -> None:
|
def _best_effort_auto_update() -> None:
|
||||||
@@ -310,12 +302,12 @@ def _best_effort_auto_update() -> None:
|
|||||||
return
|
return
|
||||||
|
|
||||||
try:
|
try:
|
||||||
backend_ref, frontend_version = _resolve_auto_update_targets(mode)
|
backend_ref = _resolve_auto_update_targets(mode)
|
||||||
except RuntimeError as exc:
|
except RuntimeError as exc:
|
||||||
_warn(f"自动更新准备失败,继续使用当前版本启动:{exc}")
|
_warn(f"自动更新准备失败,继续使用当前版本启动:{exc}")
|
||||||
return
|
return
|
||||||
|
|
||||||
if not backend_ref or not frontend_version:
|
if not backend_ref:
|
||||||
_warn("自动更新准备失败,未能解析当前主版本对应的远端版本,继续使用当前版本启动")
|
_warn("自动更新准备失败,未能解析当前主版本对应的远端版本,继续使用当前版本启动")
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -326,8 +318,6 @@ def _best_effort_auto_update() -> None:
|
|||||||
"all",
|
"all",
|
||||||
"--ref",
|
"--ref",
|
||||||
backend_ref,
|
backend_ref,
|
||||||
"--frontend-version",
|
|
||||||
frontend_version,
|
|
||||||
"--venv",
|
"--venv",
|
||||||
str(_repo_root() / "venv"),
|
str(_repo_root() / "venv"),
|
||||||
"--config-dir",
|
"--config-dir",
|
||||||
|
|||||||
+5
-4
@@ -14,7 +14,7 @@ curl -fsSL https://raw.githubusercontent.com/jxxghp/MoviePilot/v2/scripts/bootst
|
|||||||
- 自动检查并尽量安装 `git`、`curl`、`Python 3.11+`
|
- 自动检查并尽量安装 `git`、`curl`、`Python 3.11+`
|
||||||
- 克隆 `MoviePilot`
|
- 克隆 `MoviePilot`
|
||||||
- 安装后端依赖
|
- 安装后端依赖
|
||||||
- 下载 `MoviePilot-Frontend` 最新 release 的 `dist.zip`
|
- 按当前仓库 `version.py` 中的 `FRONTEND_VERSION` 下载对应前端 release 的 `dist.zip`
|
||||||
- 下载 `MoviePilot-Resources` 主分支资源
|
- 下载 `MoviePilot-Resources` 主分支资源
|
||||||
- 将 `resources.v2/*` 同步到后端 [app/helper](/Users/jxxghp/PycharmProjects/MoviePilot/app/helper)
|
- 将 `resources.v2/*` 同步到后端 [app/helper](/Users/jxxghp/PycharmProjects/MoviePilot/app/helper)
|
||||||
- 下载本地 Node 运行时并安装前端运行依赖
|
- 下载本地 Node 运行时并安装前端运行依赖
|
||||||
@@ -172,7 +172,8 @@ moviepilot install frontend --config-dir /path/to/moviepilot-config
|
|||||||
|
|
||||||
说明:
|
说明:
|
||||||
|
|
||||||
- 默认下载 `MoviePilot-Frontend` 最新 release 的 `dist.zip`
|
- 默认按当前仓库 `version.py` 中的 `FRONTEND_VERSION` 下载对应前端 release 的 `dist.zip`
|
||||||
|
- 如需覆盖默认行为,仍可显式传入 `--version latest` 或指定具体 tag
|
||||||
- 会自动安装本地 Node 运行时
|
- 会自动安装本地 Node 运行时
|
||||||
- 会自动安装 `service.js` 所需的运行依赖
|
- 会自动安装 `service.js` 所需的运行依赖
|
||||||
|
|
||||||
@@ -323,8 +324,8 @@ moviepilot update all --skip-resources
|
|||||||
说明:
|
说明:
|
||||||
|
|
||||||
- `update backend` 会更新 Git 仓库并重新安装后端依赖
|
- `update backend` 会更新 Git 仓库并重新安装后端依赖
|
||||||
- `update frontend` 会下载并替换前端 release
|
- `update frontend` 会按当前仓库 `version.py` 中的 `FRONTEND_VERSION` 下载并替换前端 release
|
||||||
- `update all` 会同时更新后端、前端,默认也会同步资源文件
|
- `update all` 会先更新后端,再按更新后代码中的 `FRONTEND_VERSION` 更新前端,默认也会同步资源文件
|
||||||
- 更新前请先执行 `moviepilot stop`
|
- 更新前请先执行 `moviepilot stop`
|
||||||
|
|
||||||
## Agent 命令
|
## Agent 命令
|
||||||
|
|||||||
+5
-5
@@ -10,10 +10,10 @@ Usage: moviepilot [BOOTSTRAP COMMAND] | [RUNTIME COMMAND]
|
|||||||
|
|
||||||
Bootstrap Commands:
|
Bootstrap Commands:
|
||||||
moviepilot install deps [--python PYTHON] [--venv PATH] [--recreate] [--config-dir PATH]
|
moviepilot install deps [--python PYTHON] [--venv PATH] [--recreate] [--config-dir PATH]
|
||||||
moviepilot install frontend [--version latest] [--node-version 20.12.1] [--config-dir PATH]
|
moviepilot install frontend [--version TAG] [--node-version 20.12.1] [--config-dir PATH]
|
||||||
moviepilot install resources [--resources-repo PATH] [--resource-dir PATH] [--config-dir PATH]
|
moviepilot install resources [--resources-repo PATH] [--resource-dir PATH] [--config-dir PATH]
|
||||||
moviepilot init [--skip-resources] [--force-token] [--wizard] [--superuser NAME] [--superuser-password PASSWORD] [--config-dir PATH]
|
moviepilot init [--skip-resources] [--force-token] [--wizard] [--superuser NAME] [--superuser-password PASSWORD] [--config-dir PATH]
|
||||||
moviepilot setup [--python PYTHON] [--venv PATH] [--recreate] [--frontend-version latest] [--node-version 20.12.1] [--wizard] [--superuser NAME] [--superuser-password PASSWORD] [--config-dir PATH]
|
moviepilot setup [--python PYTHON] [--venv PATH] [--recreate] [--frontend-version TAG] [--node-version 20.12.1] [--wizard] [--superuser NAME] [--superuser-password PASSWORD] [--config-dir PATH]
|
||||||
moviepilot uninstall [--venv PATH] [--config-dir PATH]
|
moviepilot uninstall [--venv PATH] [--config-dir PATH]
|
||||||
moviepilot update {backend|frontend|all} [OPTIONS]
|
moviepilot update {backend|frontend|all} [OPTIONS]
|
||||||
moviepilot startup {enable|disable|status} [--venv PATH] [--config-dir PATH]
|
moviepilot startup {enable|disable|status} [--venv PATH] [--config-dir PATH]
|
||||||
@@ -107,7 +107,7 @@ Options:
|
|||||||
--config-dir PATH 指定配置目录
|
--config-dir PATH 指定配置目录
|
||||||
|
|
||||||
frontend:
|
frontend:
|
||||||
--version TAG 前端版本,默认 latest
|
--version TAG 前端版本,默认使用 version.py 中的 FRONTEND_VERSION
|
||||||
--node-version VER 本地 Node 运行时版本,默认 20.12.1
|
--node-version VER 本地 Node 运行时版本,默认 20.12.1
|
||||||
--config-dir PATH 指定配置目录
|
--config-dir PATH 指定配置目录
|
||||||
|
|
||||||
@@ -143,7 +143,7 @@ Options:
|
|||||||
--python PYTHON 用于创建虚拟环境的 Python 解释器,默认自动选择本地 3.11+ 版本
|
--python PYTHON 用于创建虚拟环境的 Python 解释器,默认自动选择本地 3.11+ 版本
|
||||||
--venv PATH 虚拟环境目录,默认 ./venv
|
--venv PATH 虚拟环境目录,默认 ./venv
|
||||||
--recreate 删除并重建虚拟环境
|
--recreate 删除并重建虚拟环境
|
||||||
--frontend-version TAG 前端版本,默认 latest
|
--frontend-version TAG 前端版本,默认使用 version.py 中的 FRONTEND_VERSION
|
||||||
--node-version VER 本地 Node 运行时版本,默认 20.12.1
|
--node-version VER 本地 Node 运行时版本,默认 20.12.1
|
||||||
--skip-resources 跳过资源同步
|
--skip-resources 跳过资源同步
|
||||||
--force-token 强制重置 API_TOKEN
|
--force-token 强制重置 API_TOKEN
|
||||||
@@ -180,7 +180,7 @@ Usage:
|
|||||||
|
|
||||||
Options:
|
Options:
|
||||||
--ref REF 后端 Git 版本,默认 latest
|
--ref REF 后端 Git 版本,默认 latest
|
||||||
--frontend-version TAG 前端版本,默认 latest
|
--frontend-version TAG 前端版本,默认使用 version.py 中的 FRONTEND_VERSION
|
||||||
--node-version VER 本地 Node 运行时版本,默认 20.12.1
|
--node-version VER 本地 Node 运行时版本,默认 20.12.1
|
||||||
--python PYTHON 用于安装后端依赖的 Python 解释器,默认自动选择本地 3.11+ 版本
|
--python PYTHON 用于安装后端依赖的 Python 解释器,默认自动选择本地 3.11+ 版本
|
||||||
--venv PATH 虚拟环境目录,默认 ./venv
|
--venv PATH 虚拟环境目录,默认 ./venv
|
||||||
|
|||||||
+19
-3
@@ -113,6 +113,21 @@ RUNTIME_PACKAGE = {
|
|||||||
"express-http-proxy": "^2.0.0",
|
"express-http-proxy": "^2.0.0",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def _repo_frontend_version() -> str:
|
||||||
|
version_file = ROOT / "version.py"
|
||||||
|
module_name = f"moviepilot_version_{uuid.uuid4().hex}"
|
||||||
|
spec = importlib.util.spec_from_file_location(module_name, version_file)
|
||||||
|
if spec is None or spec.loader is None:
|
||||||
|
raise RuntimeError(f"无法加载版本文件:{version_file}")
|
||||||
|
|
||||||
|
module = importlib.util.module_from_spec(spec)
|
||||||
|
spec.loader.exec_module(module)
|
||||||
|
frontend_version = str(getattr(module, "FRONTEND_VERSION", "") or "").strip()
|
||||||
|
if not frontend_version:
|
||||||
|
raise RuntimeError(f"版本文件未定义有效的 FRONTEND_VERSION:{version_file}")
|
||||||
|
return frontend_version
|
||||||
LOCAL_FRONTEND_SERVICE_SCRIPT = textwrap.dedent(
|
LOCAL_FRONTEND_SERVICE_SCRIPT = textwrap.dedent(
|
||||||
"""
|
"""
|
||||||
const http = require('node:http')
|
const http = require('node:http')
|
||||||
@@ -687,6 +702,7 @@ def _remove_path(path: Path) -> None:
|
|||||||
|
|
||||||
|
|
||||||
def _resolve_frontend_release(frontend_version: str) -> tuple[str, str]:
|
def _resolve_frontend_release(frontend_version: str) -> tuple[str, str]:
|
||||||
|
frontend_version = (frontend_version or "").strip() or _repo_frontend_version()
|
||||||
if frontend_version == "latest":
|
if frontend_version == "latest":
|
||||||
release = fetch_json(FRONTEND_LATEST_API)
|
release = fetch_json(FRONTEND_LATEST_API)
|
||||||
else:
|
else:
|
||||||
@@ -3482,7 +3498,7 @@ def build_parser() -> argparse.ArgumentParser:
|
|||||||
"install-frontend", help="下载前端 release 并安装本地运行时"
|
"install-frontend", help="下载前端 release 并安装本地运行时"
|
||||||
)
|
)
|
||||||
frontend_parser.add_argument(
|
frontend_parser.add_argument(
|
||||||
"--version", default="latest", help="前端版本,默认 latest"
|
"--version", help="前端版本,默认使用 version.py 中的 FRONTEND_VERSION"
|
||||||
)
|
)
|
||||||
frontend_parser.add_argument(
|
frontend_parser.add_argument(
|
||||||
"--node-version", default=DEFAULT_NODE_VERSION, help="本地 Node 运行时版本"
|
"--node-version", default=DEFAULT_NODE_VERSION, help="本地 Node 运行时版本"
|
||||||
@@ -3535,7 +3551,7 @@ def build_parser() -> argparse.ArgumentParser:
|
|||||||
"--recreate", action="store_true", help="删除并重建虚拟环境"
|
"--recreate", action="store_true", help="删除并重建虚拟环境"
|
||||||
)
|
)
|
||||||
setup_parser.add_argument(
|
setup_parser.add_argument(
|
||||||
"--frontend-version", default="latest", help="前端版本,默认 latest"
|
"--frontend-version", help="前端版本,默认使用 version.py 中的 FRONTEND_VERSION"
|
||||||
)
|
)
|
||||||
setup_parser.add_argument(
|
setup_parser.add_argument(
|
||||||
"--node-version", default=DEFAULT_NODE_VERSION, help="本地 Node 运行时版本"
|
"--node-version", default=DEFAULT_NODE_VERSION, help="本地 Node 运行时版本"
|
||||||
@@ -3592,7 +3608,7 @@ def build_parser() -> argparse.ArgumentParser:
|
|||||||
"--ref", default="latest", help="后端 Git 版本,默认 latest"
|
"--ref", default="latest", help="后端 Git 版本,默认 latest"
|
||||||
)
|
)
|
||||||
update_parser.add_argument(
|
update_parser.add_argument(
|
||||||
"--frontend-version", default="latest", help="前端版本,默认 latest"
|
"--frontend-version", help="前端版本,默认使用 version.py 中的 FRONTEND_VERSION"
|
||||||
)
|
)
|
||||||
update_parser.add_argument(
|
update_parser.add_argument(
|
||||||
"--node-version", default=DEFAULT_NODE_VERSION, help="本地 Node 运行时版本"
|
"--node-version", default=DEFAULT_NODE_VERSION, help="本地 Node 运行时版本"
|
||||||
|
|||||||
@@ -0,0 +1,116 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import importlib.util
|
||||||
|
import sys
|
||||||
|
import tempfile
|
||||||
|
import unittest
|
||||||
|
import uuid
|
||||||
|
from pathlib import Path
|
||||||
|
from types import ModuleType, SimpleNamespace
|
||||||
|
from unittest.mock import patch
|
||||||
|
|
||||||
|
|
||||||
|
MODULE_PATH = Path(__file__).resolve().parents[1] / "app" / "cli.py"
|
||||||
|
|
||||||
|
|
||||||
|
class _DummySystemHelper:
|
||||||
|
@staticmethod
|
||||||
|
def consume_one_shot_update_mode():
|
||||||
|
return None
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_auto_update_mode():
|
||||||
|
return "false"
|
||||||
|
|
||||||
|
|
||||||
|
def load_cli_module():
|
||||||
|
with tempfile.TemporaryDirectory() as temp_dir:
|
||||||
|
root = Path(temp_dir)
|
||||||
|
settings = SimpleNamespace(
|
||||||
|
TEMP_PATH=root / "temp",
|
||||||
|
LOG_PATH=root / "logs",
|
||||||
|
ROOT_PATH=root,
|
||||||
|
FRONTEND_PATH=str(root / "public"),
|
||||||
|
CONFIG_PATH=root / "config",
|
||||||
|
HOST="127.0.0.1",
|
||||||
|
PORT=3001,
|
||||||
|
NGINX_PORT=3000,
|
||||||
|
PROXY_HOST="",
|
||||||
|
GITHUB_TOKEN="",
|
||||||
|
PROXY={},
|
||||||
|
REPO_GITHUB_HEADERS=lambda _repo: {},
|
||||||
|
)
|
||||||
|
|
||||||
|
app_module = ModuleType("app")
|
||||||
|
core_module = ModuleType("app.core")
|
||||||
|
helper_module = ModuleType("app.helper")
|
||||||
|
config_module = ModuleType("app.core.config")
|
||||||
|
system_module = ModuleType("app.helper.system")
|
||||||
|
version_module = ModuleType("version")
|
||||||
|
psutil_module = ModuleType("psutil")
|
||||||
|
|
||||||
|
app_module.__path__ = []
|
||||||
|
core_module.__path__ = []
|
||||||
|
helper_module.__path__ = []
|
||||||
|
config_module.Settings = type("Settings", (), {})
|
||||||
|
config_module.settings = settings
|
||||||
|
system_module.SystemHelper = _DummySystemHelper
|
||||||
|
version_module.APP_VERSION = "v2.10.11"
|
||||||
|
psutil_module.STATUS_ZOMBIE = "zombie"
|
||||||
|
psutil_module.NoSuchProcess = RuntimeError
|
||||||
|
psutil_module.AccessDenied = RuntimeError
|
||||||
|
psutil_module.ZombieProcess = RuntimeError
|
||||||
|
psutil_module.Process = object
|
||||||
|
|
||||||
|
stub_modules = {
|
||||||
|
"app": app_module,
|
||||||
|
"app.core": core_module,
|
||||||
|
"app.helper": helper_module,
|
||||||
|
"app.core.config": config_module,
|
||||||
|
"app.helper.system": system_module,
|
||||||
|
"version": version_module,
|
||||||
|
"psutil": psutil_module,
|
||||||
|
}
|
||||||
|
|
||||||
|
module_name = f"moviepilot_app_cli_{uuid.uuid4().hex}"
|
||||||
|
spec = importlib.util.spec_from_file_location(module_name, MODULE_PATH)
|
||||||
|
module = importlib.util.module_from_spec(spec)
|
||||||
|
assert spec and spec.loader
|
||||||
|
|
||||||
|
with patch.dict(sys.modules, stub_modules):
|
||||||
|
spec.loader.exec_module(module)
|
||||||
|
return module
|
||||||
|
|
||||||
|
|
||||||
|
class CliAutoUpdateTests(unittest.TestCase):
|
||||||
|
def test_resolve_auto_update_targets_only_queries_backend_release(self):
|
||||||
|
module = load_cli_module()
|
||||||
|
|
||||||
|
with patch.object(module, "_latest_release_tag", return_value="v2.10.12") as latest_mock:
|
||||||
|
backend_ref = module._resolve_auto_update_targets("release")
|
||||||
|
|
||||||
|
latest_mock.assert_called_once_with(
|
||||||
|
module.BACKEND_RELEASES_API,
|
||||||
|
repo="jxxghp/MoviePilot",
|
||||||
|
prefix="v2",
|
||||||
|
)
|
||||||
|
self.assertEqual(backend_ref, "v2.10.12")
|
||||||
|
|
||||||
|
def test_best_effort_auto_update_does_not_pass_frontend_version_override(self):
|
||||||
|
module = load_cli_module()
|
||||||
|
run_result = SimpleNamespace(returncode=0, stdout="ok")
|
||||||
|
|
||||||
|
with patch.object(module, "_auto_update_mode", return_value="release"), patch.object(
|
||||||
|
module, "_resolve_auto_update_targets", return_value="v2.10.12"
|
||||||
|
), patch.object(module.subprocess, "run", return_value=run_result) as run_mock, patch.object(
|
||||||
|
module.click, "echo"
|
||||||
|
):
|
||||||
|
module._best_effort_auto_update()
|
||||||
|
|
||||||
|
command = run_mock.call_args.args[0]
|
||||||
|
self.assertEqual(command[1:5], [str(module._repo_root() / "scripts" / "local_setup.py"), "update", "all", "--ref"])
|
||||||
|
self.assertNotIn("--frontend-version", command)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
unittest.main()
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import importlib.util
|
||||||
|
import tempfile
|
||||||
|
import unittest
|
||||||
|
import uuid
|
||||||
|
from pathlib import Path
|
||||||
|
from unittest.mock import patch
|
||||||
|
|
||||||
|
|
||||||
|
MODULE_PATH = Path(__file__).resolve().parents[1] / "scripts" / "local_setup.py"
|
||||||
|
|
||||||
|
|
||||||
|
def load_local_setup_module():
|
||||||
|
module_name = f"moviepilot_local_setup_frontend_{uuid.uuid4().hex}"
|
||||||
|
spec = importlib.util.spec_from_file_location(module_name, MODULE_PATH)
|
||||||
|
module = importlib.util.module_from_spec(spec)
|
||||||
|
assert spec and spec.loader
|
||||||
|
spec.loader.exec_module(module)
|
||||||
|
return module
|
||||||
|
|
||||||
|
|
||||||
|
class LocalSetupFrontendVersionTests(unittest.TestCase):
|
||||||
|
def test_repo_frontend_version_reads_version_file(self):
|
||||||
|
module = load_local_setup_module()
|
||||||
|
|
||||||
|
with tempfile.TemporaryDirectory() as temp_dir:
|
||||||
|
root = Path(temp_dir)
|
||||||
|
(root / "version.py").write_text(
|
||||||
|
"APP_VERSION = 'v0.0.1'\nFRONTEND_VERSION = 'v9.9.9'\n",
|
||||||
|
encoding="utf-8",
|
||||||
|
)
|
||||||
|
|
||||||
|
with patch.object(module, "ROOT", root):
|
||||||
|
self.assertEqual(module._repo_frontend_version(), "v9.9.9")
|
||||||
|
|
||||||
|
def test_resolve_frontend_release_uses_repo_frontend_version_by_default(self):
|
||||||
|
module = load_local_setup_module()
|
||||||
|
release = {
|
||||||
|
"tag_name": "v9.9.9",
|
||||||
|
"assets": [
|
||||||
|
{
|
||||||
|
"name": "dist.zip",
|
||||||
|
"browser_download_url": "https://example.com/dist.zip",
|
||||||
|
}
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
with patch.object(module, "_repo_frontend_version", return_value="v9.9.9"), patch.object(
|
||||||
|
module, "fetch_json", return_value=release
|
||||||
|
) as fetch_mock:
|
||||||
|
tag_name, download_url = module._resolve_frontend_release(None)
|
||||||
|
|
||||||
|
fetch_mock.assert_called_once_with(
|
||||||
|
module.FRONTEND_TAG_API.format(tag="v9.9.9")
|
||||||
|
)
|
||||||
|
self.assertEqual(tag_name, "v9.9.9")
|
||||||
|
self.assertEqual(download_url, "https://example.com/dist.zip")
|
||||||
|
|
||||||
|
def test_parser_leaves_frontend_version_empty_until_runtime_resolution(self):
|
||||||
|
module = load_local_setup_module()
|
||||||
|
parser = module.build_parser()
|
||||||
|
|
||||||
|
install_args = parser.parse_args(["install-frontend"])
|
||||||
|
setup_args = parser.parse_args(["setup"])
|
||||||
|
update_args = parser.parse_args(["update", "frontend"])
|
||||||
|
|
||||||
|
self.assertIsNone(install_args.version)
|
||||||
|
self.assertIsNone(setup_args.frontend_version)
|
||||||
|
self.assertIsNone(update_args.frontend_version)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
unittest.main()
|
||||||
Reference in New Issue
Block a user