mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-09-08 17:08:35 +08:00
fix(scheduler): gate release update checks
This commit is contained in:
@@ -178,6 +178,7 @@ class SchedulerRuntimeConfig:
|
||||
ai_agent_job_interval: Any
|
||||
usage_statistic_share: bool
|
||||
site_link: str | None
|
||||
auto_update: bool = False
|
||||
|
||||
|
||||
@dataclass(frozen=True, slots=True)
|
||||
|
||||
@@ -916,13 +916,12 @@ class Settings(BaseSettings, ConfigModel, LogConfigModel):
|
||||
if not isinstance(data, dict):
|
||||
return data
|
||||
|
||||
# Release 已迁移到后台状态机,历史 release/true 不能继续启用启动时更新。
|
||||
# 仅 true 表示启用后台 Release 检查,其他模式不注册该定时服务。
|
||||
if "MOVIEPILOT_AUTO_UPDATE" in data:
|
||||
original_update_mode = data["MOVIEPILOT_AUTO_UPDATE"]
|
||||
mode = str(original_update_mode or "").strip().lower()
|
||||
normalized_update_mode = (
|
||||
"dev"
|
||||
if str(original_update_mode or "").strip().lower() == "dev"
|
||||
else "false"
|
||||
mode if mode in {"true", "dev", "false"} else "false"
|
||||
)
|
||||
if normalized_update_mode != str(original_update_mode):
|
||||
cls.update_env_config(
|
||||
|
||||
+16
-11
@@ -203,7 +203,11 @@ class SchedulerCatalogOwner(_SchedulerOwnerBase):
|
||||
JobSpec("full_gc", "主动内存回收", self.full_gc, "runtime"),
|
||||
JobSpec("agent_heartbeat", "智能体定时任务", self.agent_heartbeat, "agent"),
|
||||
JobSpec("usage_report", "安装版本统计上报", MoviePilotServerHelper.report_usage, "server"),
|
||||
JobSpec("system_update_check", "检查系统更新", system_update_manager.check, "system"),
|
||||
*(
|
||||
[JobSpec("system_update_check", "检查系统更新", system_update_manager.check, "system")]
|
||||
if config.auto_update
|
||||
else []
|
||||
),
|
||||
]
|
||||
).runtime_states()
|
||||
for job_id, job in self._jobs.items():
|
||||
@@ -424,16 +428,17 @@ class SchedulerCatalogOwner(_SchedulerOwnerBase):
|
||||
kwargs={"job_id": "plugin_market_refresh"},
|
||||
)
|
||||
|
||||
# 更新检查只缓存 Release 元数据,不会在未授权时下载或重启。
|
||||
self._scheduler.add_job(
|
||||
self.start,
|
||||
"interval",
|
||||
id="system_update_check",
|
||||
name="检查系统更新",
|
||||
hours=6,
|
||||
next_run_time=datetime.now(pytz.timezone(config.timezone)) + timedelta(minutes=1),
|
||||
kwargs={"job_id": "system_update_check"},
|
||||
)
|
||||
if config.auto_update:
|
||||
# 更新检查只缓存 Release 元数据,不会在未授权时下载或重启。
|
||||
self._scheduler.add_job(
|
||||
self.start,
|
||||
"interval",
|
||||
id="system_update_check",
|
||||
name="检查系统更新",
|
||||
hours=6,
|
||||
next_run_time=datetime.now(pytz.timezone(config.timezone)) + timedelta(minutes=1),
|
||||
kwargs={"job_id": "system_update_check"},
|
||||
)
|
||||
|
||||
# 订阅日历缓存
|
||||
self._scheduler.add_job(
|
||||
|
||||
@@ -72,6 +72,7 @@ class Scheduler(
|
||||
"DB_BACKUP_ENABLE",
|
||||
"DB_BACKUP_CRON",
|
||||
"USAGE_STATISTIC_SHARE",
|
||||
"MOVIEPILOT_AUTO_UPDATE",
|
||||
}
|
||||
|
||||
def __init__(self) -> None:
|
||||
|
||||
@@ -189,6 +189,7 @@ def build_scheduler_runtime_config(settings: Settings) -> SchedulerRuntimeConfig
|
||||
ai_agent_job_interval=settings.AI_AGENT_JOB_INTERVAL,
|
||||
usage_statistic_share=settings.USAGE_STATISTIC_SHARE,
|
||||
site_link=settings.MP_DOMAIN("#/site"),
|
||||
auto_update=str(settings.MOVIEPILOT_AUTO_UPDATE).strip().lower() == "true",
|
||||
)
|
||||
|
||||
|
||||
|
||||
+1
-1
@@ -393,7 +393,7 @@ moviepilot version
|
||||
|
||||
- `start` 会先启动后端,再启动前端
|
||||
- `start --safe` 会以安全模式启动后端,本次启动跳过插件、调度器、监控、命令和工作流等后台扩展能力,不修改用户配置
|
||||
- `MOVIEPILOT_AUTO_UPDATE` 默认关闭;仅 `dev` 保留启动前跟踪当前 v3 开发分支的行为,更新失败只告警,不阻断当前启动
|
||||
- `MOVIEPILOT_AUTO_UPDATE` 默认关闭;设置为 `true` 时启用后台 Release 检查,设置为 `dev` 时保留启动前跟踪当前 v3 开发分支的行为,更新失败只告警,不阻断当前启动
|
||||
- Release 更新由后台每 6 小时检查 GitHub Release;管理员确认后先静默下载安装包并显示进度,下载完成后再次确认重启,启动阶段只安装已下载且通过 SHA-256 校验的包
|
||||
- 页面中的“稍后”会在当前浏览器暂停提醒 24 小时,“忽略此版本”只屏蔽当前版本;出现更高版本时会重新提示
|
||||
- 通过系统内置的重启入口触发重启时,本地 CLI 安装模式也会复用同一套前后端进程管理完成重启
|
||||
|
||||
@@ -177,7 +177,7 @@ moviepilot update all --ref latest --frontend-version latest
|
||||
moviepilot update all --skip-resources
|
||||
```
|
||||
|
||||
`MOVIEPILOT_AUTO_UPDATE` defaults to `false`. Setting it to `dev` retains branch-tracking updates during `start/restart`; stable Release updates use the authenticated background check/download/install API flow and do not use this setting.
|
||||
`MOVIEPILOT_AUTO_UPDATE` defaults to `false`. Setting it to `true` enables the background Release check; setting it to `dev` retains branch-tracking updates during `start/restart`. The setting is hot-reloaded by the scheduler.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -57,6 +57,7 @@ def _config(**changes) -> SchedulerRuntimeConfig:
|
||||
ai_agent_job_interval=None,
|
||||
usage_statistic_share=False,
|
||||
site_link=None,
|
||||
auto_update=False,
|
||||
)
|
||||
return replace(config, **changes)
|
||||
|
||||
@@ -72,6 +73,11 @@ def test_database_backup_schedule_only_watches_job_shape() -> None:
|
||||
}) == {"DB_BACKUP_ENABLE", "DB_BACKUP_CRON"}
|
||||
|
||||
|
||||
def test_auto_update_setting_is_hot_reloadable() -> None:
|
||||
"""自动更新开关变更时应触发 Scheduler 重建。"""
|
||||
assert "MOVIEPILOT_AUTO_UPDATE" in Scheduler.CONFIG_WATCH
|
||||
|
||||
|
||||
def test_disabled_database_backup_does_not_register_job() -> None:
|
||||
"""关闭备份时不注册作业。"""
|
||||
scheduler = _scheduler()
|
||||
@@ -102,6 +108,34 @@ def test_enabled_database_backup_registers_single_replaceable_job(monkeypatch) -
|
||||
assert scheduler._scheduler.jobs["database_backup"]["replace_existing"] is True
|
||||
|
||||
|
||||
def test_auto_update_check_is_registered_only_when_enabled(monkeypatch) -> None:
|
||||
"""只有显式开启自动更新时才注册 Release 检查任务。"""
|
||||
scheduler = _scheduler()
|
||||
scheduler._services = Mock()
|
||||
background_scheduler = Mock()
|
||||
monkeypatch.setattr(scheduler_catalog, "BackgroundScheduler", lambda **_kwargs: background_scheduler)
|
||||
monkeypatch.setattr(scheduler_catalog, "get_plugin_manager", lambda: Mock())
|
||||
monkeypatch.setattr(scheduler_catalog, "get_mediaserver_configs", lambda **_kwargs: [])
|
||||
monkeypatch.setattr(scheduler, "init_workflow_jobs", lambda: None)
|
||||
monkeypatch.setattr(scheduler, "init_agent_task_jobs", lambda: None)
|
||||
monkeypatch.setattr(scheduler, "init_plugin_jobs", lambda: None)
|
||||
|
||||
scheduler_catalog.SchedulerCatalogOwner._initialize_catalog(scheduler, _config(auto_update=False))
|
||||
assert not any(
|
||||
call.kwargs.get("id") == "system_update_check"
|
||||
for call in background_scheduler.add_job.call_args_list
|
||||
)
|
||||
assert "system_update_check" not in scheduler._jobs
|
||||
|
||||
background_scheduler.add_job.reset_mock()
|
||||
scheduler_catalog.SchedulerCatalogOwner._initialize_catalog(scheduler, _config(auto_update=True))
|
||||
assert any(
|
||||
call.kwargs.get("id") == "system_update_check"
|
||||
for call in background_scheduler.add_job.call_args_list
|
||||
)
|
||||
assert "system_update_check" in scheduler._jobs
|
||||
|
||||
|
||||
def test_scheduled_backup_uses_registered_database_governance(monkeypatch) -> None:
|
||||
governance = Mock()
|
||||
monkeypatch.setattr(scheduler_maintenance, "get_database_governance", lambda: governance)
|
||||
|
||||
@@ -473,8 +473,8 @@ def test_btrfs_fsid_dedup_setting_is_opt_in():
|
||||
assert ConfigModel(BTRFS_FSID_DEDUP="true").BTRFS_FSID_DEDUP is True
|
||||
|
||||
|
||||
def test_legacy_release_auto_update_mode_is_disabled(monkeypatch):
|
||||
"""历史 Release 启动更新值迁移为关闭,Dev 值继续保留。"""
|
||||
def test_auto_update_mode_is_normalized(monkeypatch):
|
||||
"""自动更新仅保留 true、dev 和 false 三种运行模式。"""
|
||||
updates = []
|
||||
monkeypatch.setattr(
|
||||
Settings,
|
||||
@@ -485,11 +485,10 @@ def test_legacy_release_auto_update_mode_is_disabled(monkeypatch):
|
||||
)
|
||||
|
||||
assert Settings(MOVIEPILOT_AUTO_UPDATE="release").MOVIEPILOT_AUTO_UPDATE == "false"
|
||||
assert Settings(MOVIEPILOT_AUTO_UPDATE="true").MOVIEPILOT_AUTO_UPDATE == "false"
|
||||
assert Settings(MOVIEPILOT_AUTO_UPDATE="true").MOVIEPILOT_AUTO_UPDATE == "true"
|
||||
assert Settings(MOVIEPILOT_AUTO_UPDATE="dev").MOVIEPILOT_AUTO_UPDATE == "dev"
|
||||
assert updates == [
|
||||
("MOVIEPILOT_AUTO_UPDATE", "release", "false"),
|
||||
("MOVIEPILOT_AUTO_UPDATE", "true", "false"),
|
||||
]
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user