feat: hot reload for config/templates and GitPython-based hot update with pre-update notification
This commit is contained in:
1 parent
8775c022bd
commit
67776b0092
7 files changed
+164
-5
No files matched your search
+69
@@ -0,0 +1,69 @@
|
||||
"""Git 热更新:定期检查远端新版本,更新前先推送通知,再拉取并重启进程。
|
||||
|
||||
基于 GitPython。
|
||||
"""
|
||||
import asyncio
|
||||
import logging
|
||||
import os
|
||||
import sys
|
||||
|
||||
import git
|
||||
|
||||
log = logging.getLogger("updater")
|
||||
|
||||
|
||||
class Updater:
|
||||
def __init__(self, ob, cfg: dict):
|
||||
self.ob = ob
|
||||
self.interval = cfg.get("interval", 300)
|
||||
self.groups = cfg.get("groups", []) or []
|
||||
self.friends = cfg.get("friends", []) or []
|
||||
self._updating = False
|
||||
try:
|
||||
self.repo = git.Repo(".")
|
||||
except (git.InvalidGitRepositoryError, git.NoSuchPathError):
|
||||
self.repo = None
|
||||
|
||||
def start(self):
|
||||
if self.repo is None:
|
||||
log.info("非 git 仓库,热更新已禁用")
|
||||
return
|
||||
self._task = asyncio.get_running_loop().create_task(self._loop())
|
||||
|
||||
async def stop(self):
|
||||
if hasattr(self, "_task"):
|
||||
self._task.cancel()
|
||||
|
||||
async def _loop(self):
|
||||
log.info("热更新已启动: 每 %ds 检查一次远端", self.interval)
|
||||
while True:
|
||||
try:
|
||||
await asyncio.sleep(self.interval)
|
||||
if self.ob.connected and not self._updating:
|
||||
await self.check_once()
|
||||
except asyncio.CancelledError:
|
||||
break
|
||||
except Exception:
|
||||
log.exception("热更新检查出错")
|
||||
|
||||
async def check_once(self):
|
||||
"""检查远端;有更新则通知、拉取并重启进程。"""
|
||||
self._updating = True
|
||||
try:
|
||||
await asyncio.to_thread(self.repo.remotes.origin.fetch)
|
||||
refs = self.repo.remotes.origin.refs
|
||||
remote = getattr(refs, "HEAD", None) or (refs[0] if refs else None)
|
||||
if remote is None or remote.commit == self.repo.head.commit:
|
||||
return
|
||||
log.info("发现新版本: %s -> %s",
|
||||
self.repo.head.commit.hexsha[:8], remote.commit.hexsha[:8])
|
||||
if self.ob.connected and (self.groups or self.friends):
|
||||
await self.ob.broadcast(
|
||||
"[更新] 检测到新版本,正在更新并重启机器人...",
|
||||
self.groups, self.friends)
|
||||
await asyncio.to_thread(self.repo.remotes.origin.pull, "--ff-only")
|
||||
log.warning("更新完成,重启进程...")
|
||||
await asyncio.sleep(1)
|
||||
os.execv(sys.executable, [sys.executable] + sys.argv)
|
||||
finally:
|
||||
self._updating = False
|
||||
Reference in new issue
Block a user