mirror of
https://github.com/LmeSzinc/AzurLaneAutoScript.git
synced 2025-01-08 12:27:33 +08:00
Opt: Show commit info in updater
This commit is contained in:
parent
bff8296af5
commit
c8a95970d5
6
alas.py
6
alas.py
@ -17,7 +17,7 @@ from module.logger import logger
|
||||
|
||||
class AzurLaneAutoScript:
|
||||
|
||||
stop_event: threading.Event
|
||||
stop_event: threading.Event = None
|
||||
|
||||
def __init__(self, config_name='alas'):
|
||||
self.config_name = config_name
|
||||
@ -284,7 +284,7 @@ class AzurLaneAutoScript:
|
||||
if seconds <= 0:
|
||||
logger.warning(f'Wait until {str(future)}, but sleep length < 0, skip waiting')
|
||||
|
||||
if hasattr(self, 'stop_event'):
|
||||
if self.stop_event is not None:
|
||||
self.stop_event.wait(seconds)
|
||||
if self.stop_event.is_set():
|
||||
logger.info("Update event detected")
|
||||
@ -330,7 +330,7 @@ class AzurLaneAutoScript:
|
||||
failure_record = {}
|
||||
|
||||
while 1:
|
||||
if hasattr(self, 'stop_event'):
|
||||
if self.stop_event is not None:
|
||||
if self.stop_event.is_set():
|
||||
logger.info("Update event detected")
|
||||
logger.info(f"Alas [{self.config_name}] exited.")
|
||||
|
@ -62,22 +62,10 @@ Deploy:
|
||||
InstallUiautomator2: true
|
||||
|
||||
Update:
|
||||
# Api Access token
|
||||
# Not necessary, unauthorised users can call Github API 60 times/h, Gitee API has no limitations
|
||||
# **Use same platform as Repository
|
||||
# Github:
|
||||
# https://github.com/settings/tokens/new
|
||||
# Enter your note, choose expiration and click Generate token, copy the token
|
||||
# Token will be like this: ghp_cdvpqb23klCfg9Ah567anou8Bt4imDwxersj0yz1
|
||||
# Gitee:
|
||||
# https://gitee.com/api/v5/swagger#/
|
||||
# Click "申请授权" at the upper right corner, copy value of access_token
|
||||
# Token will be like this: pqrsg189hijcbkn0672def1lm495a3o4
|
||||
ApiToken: null
|
||||
# Check update every X minute
|
||||
# [Disable] -1
|
||||
# [Default] 30
|
||||
CheckUpdateInterval: 30
|
||||
# [Default] 5
|
||||
CheckUpdateInterval: 5
|
||||
# Scheduled restart time
|
||||
# If there are updates, Alas will automatically restart and update at this time every day
|
||||
# and run all alas instances that running before restarted
|
||||
|
@ -30,6 +30,7 @@ Status:
|
||||
Running:
|
||||
Inactive:
|
||||
Warning:
|
||||
Updating:
|
||||
|
||||
MenuAlas:
|
||||
Overview:
|
||||
@ -66,6 +67,11 @@ Update:
|
||||
UpdateFailed:
|
||||
UpdateChecking:
|
||||
UpdateCancel:
|
||||
Local:
|
||||
Upstream:
|
||||
Author:
|
||||
Time:
|
||||
Message:
|
||||
|
||||
Text:
|
||||
InvalidFeedBack:
|
@ -57,7 +57,7 @@ def name_to_function(name):
|
||||
|
||||
|
||||
class AzurLaneConfig(ConfigUpdater, ManualConfig, GeneratedConfig):
|
||||
stop_event: threading.Event
|
||||
stop_event: threading.Event = None
|
||||
bound = {}
|
||||
|
||||
# Class property
|
||||
@ -406,7 +406,7 @@ class AzurLaneConfig(ConfigUpdater, ManualConfig, GeneratedConfig):
|
||||
bool: If task switched
|
||||
"""
|
||||
# Update event
|
||||
if hasattr(self, 'stop_event'):
|
||||
if self.stop_event is not None:
|
||||
if self.stop_event.is_set():
|
||||
return True
|
||||
prev = self.task
|
||||
|
@ -1782,7 +1782,8 @@
|
||||
"Status": {
|
||||
"Running": "Running",
|
||||
"Inactive": "Inactive",
|
||||
"Warning": "Warning"
|
||||
"Warning": "Warning",
|
||||
"Updating": "Waiting Update"
|
||||
},
|
||||
"MenuAlas": {
|
||||
"Overview": "Overview",
|
||||
@ -1817,7 +1818,12 @@
|
||||
"UpdateRun": "Updating",
|
||||
"UpdateSuccess": "Update succeeded, restarting",
|
||||
"UpdateChecking": "Checking for updates",
|
||||
"UpdateCancel": "Update canceled, restarting Alas"
|
||||
"UpdateCancel": "Update canceled, restarting Alas",
|
||||
"Local": "Local",
|
||||
"Upstream": "Upstream",
|
||||
"Author": "Author",
|
||||
"Time": "Commit time",
|
||||
"Message": "Commit message"
|
||||
},
|
||||
"Text": {
|
||||
"InvalidFeedBack": "Invalid format. Example: {0}"
|
||||
|
@ -1782,7 +1782,8 @@
|
||||
"Status": {
|
||||
"Running": "Gui.Status.Running",
|
||||
"Inactive": "Gui.Status.Inactive",
|
||||
"Warning": "Gui.Status.Warning"
|
||||
"Warning": "Gui.Status.Warning",
|
||||
"Updating": "Gui.Status.Updating"
|
||||
},
|
||||
"MenuAlas": {
|
||||
"Overview": "Gui.MenuAlas.Overview",
|
||||
@ -1817,7 +1818,12 @@
|
||||
"UpdateRun": "Gui.Update.UpdateRun",
|
||||
"UpdateSuccess": "Gui.Update.UpdateSuccess",
|
||||
"UpdateChecking": "Gui.Update.UpdateChecking",
|
||||
"UpdateCancel": "Gui.Update.UpdateCancel"
|
||||
"UpdateCancel": "Gui.Update.UpdateCancel",
|
||||
"Local": "Gui.Update.Local",
|
||||
"Upstream": "Gui.Update.Upstream",
|
||||
"Author": "Gui.Update.Author",
|
||||
"Time": "Gui.Update.Time",
|
||||
"Message": "Gui.Update.Message"
|
||||
},
|
||||
"Text": {
|
||||
"InvalidFeedBack": "Gui.Text.InvalidFeedBack"
|
||||
|
@ -1782,7 +1782,8 @@
|
||||
"Status": {
|
||||
"Running": "运行中",
|
||||
"Inactive": "闲置",
|
||||
"Warning": "发生错误"
|
||||
"Warning": "发生错误",
|
||||
"Updating": "等待更新"
|
||||
},
|
||||
"MenuAlas": {
|
||||
"Overview": "总览",
|
||||
@ -1817,7 +1818,12 @@
|
||||
"UpdateRun": "更新中",
|
||||
"UpdateSuccess": "更新成功,正在重启",
|
||||
"UpdateChecking": "检查更新中",
|
||||
"UpdateCancel": "取消更新,重启 Alas 中"
|
||||
"UpdateCancel": "取消更新,重启 Alas 中",
|
||||
"Local": "本地",
|
||||
"Upstream": "上游仓库",
|
||||
"Author": "作者",
|
||||
"Time": "提交时间",
|
||||
"Message": "提交信息"
|
||||
},
|
||||
"Text": {
|
||||
"InvalidFeedBack": "格式错误。 示例:{0}"
|
||||
|
@ -1782,7 +1782,8 @@
|
||||
"Status": {
|
||||
"Running": "執行中",
|
||||
"Inactive": "閒置",
|
||||
"Warning": "發生錯誤"
|
||||
"Warning": "發生錯誤",
|
||||
"Updating": "等待更新"
|
||||
},
|
||||
"MenuAlas": {
|
||||
"Overview": "總覽",
|
||||
@ -1817,7 +1818,12 @@
|
||||
"UpdateRun": "更新中",
|
||||
"UpdateSuccess": "更新成功,正在重啓",
|
||||
"UpdateChecking": "檢查更新中",
|
||||
"UpdateCancel": "取消更新,重啓 Alas 中"
|
||||
"UpdateCancel": "取消更新,重啓 Alas 中",
|
||||
"Local": "本地",
|
||||
"Upstream": "上游倉庫",
|
||||
"Author": "作者",
|
||||
"Time": "提交時間",
|
||||
"Message": "提交資訊"
|
||||
},
|
||||
"Text": {
|
||||
"InvalidFeedBack": "格式錯誤。 示例:{0}"
|
||||
|
@ -33,7 +33,7 @@ from pywebio.exceptions import SessionClosedException, SessionNotFoundException
|
||||
from pywebio.output import (clear, close_popup, popup, put_button, put_buttons,
|
||||
put_collapse, put_column, put_error, put_html,
|
||||
put_loading, put_markdown, put_row, put_scope,
|
||||
put_text, toast, use_scope)
|
||||
put_table, put_text, toast, use_scope)
|
||||
from pywebio.pin import pin, pin_wait_change
|
||||
from pywebio.session import go_app, info, register_thread, run_js, set_env
|
||||
|
||||
@ -97,6 +97,7 @@ class AlasGUI(Frame):
|
||||
1 (running)
|
||||
2 (not running)
|
||||
3 (warning, stop unexpectedly)
|
||||
4 (stop for update)
|
||||
0 (hide)
|
||||
-1 (*state not changed)
|
||||
"""
|
||||
@ -124,6 +125,13 @@ class AlasGUI(Frame):
|
||||
None,
|
||||
put_text(t("Gui.Status.Warning"))
|
||||
], size='auto 2px 1fr')
|
||||
elif state == 4:
|
||||
put_row([
|
||||
put_loading(shape='grow', color='success').style(
|
||||
"--loading-grow--"),
|
||||
None,
|
||||
put_text(t("Gui.Status.Updating"))
|
||||
], size='auto 2px 1fr')
|
||||
|
||||
@classmethod
|
||||
def set_theme(cls, theme='default') -> None:
|
||||
@ -570,6 +578,18 @@ class AlasGUI(Frame):
|
||||
], size='auto .25rem 1fr')
|
||||
|
||||
put_scope('updater_btn')
|
||||
put_scope('updater_info')
|
||||
|
||||
def update_table():
|
||||
with use_scope('updater_info', clear=True):
|
||||
local_commit = updater.get_commit(short_sha1=True)
|
||||
upstream_commit = updater.get_commit(
|
||||
f'origin/{updater.branch}', short_sha1=True)
|
||||
put_table([
|
||||
[t('Gui.Update.Local'), *local_commit],
|
||||
[t('Gui.Update.Upstream'), *upstream_commit]
|
||||
], header=['', 'SHA1', t('Gui.Update.Author'),
|
||||
t('Gui.Update.Time'), t('Gui.Update.Message')])
|
||||
|
||||
def u(state):
|
||||
if state == -1:
|
||||
@ -586,6 +606,7 @@ class AlasGUI(Frame):
|
||||
color='info',
|
||||
scope='updater_btn'
|
||||
)
|
||||
update_table()
|
||||
elif state == 1:
|
||||
put_loading('grow', 'success', 'updater_loading').style(
|
||||
"--loading-grow--")
|
||||
@ -595,6 +616,7 @@ class AlasGUI(Frame):
|
||||
color='success',
|
||||
scope='updater_btn'
|
||||
)
|
||||
update_table()
|
||||
elif state == 'checking':
|
||||
put_loading('border', 'primary', 'updater_loading').style(
|
||||
"--loading-border--")
|
||||
@ -640,6 +662,7 @@ class AlasGUI(Frame):
|
||||
put_loading('grow', 'success', 'updater_loading').style(
|
||||
"--loading-grow--")
|
||||
put_text(t('Gui.Update.UpdateSuccess'), scope='updater_state')
|
||||
update_table()
|
||||
elif state == 'cancel':
|
||||
put_loading('border', 'danger', 'updater_loading').style(
|
||||
"--loading-border--")
|
||||
@ -661,6 +684,7 @@ class AlasGUI(Frame):
|
||||
name='updater'
|
||||
)
|
||||
|
||||
update_table()
|
||||
self.task_handler.add(updater_switch.g(),
|
||||
delay=0.5, pending_delete=True)
|
||||
|
||||
@ -952,7 +976,7 @@ def app():
|
||||
debug=True,
|
||||
on_startup=[
|
||||
startup,
|
||||
lambda: AlasManager.start_alas(ev = updater.event)
|
||||
lambda: AlasManager.start_alas(ev=updater.event)
|
||||
],
|
||||
on_shutdown=[clearup]
|
||||
)
|
||||
|
@ -1,4 +1,4 @@
|
||||
from module.webui.utils import Icon, TaskHandler, set_localstorage
|
||||
from module.webui.utils import Icon, WebIOTaskHandler, set_localstorage
|
||||
from pywebio.output import clear, put_html, put_scope, put_text, use_scope
|
||||
from pywebio.session import defer_call, info, run_js
|
||||
|
||||
@ -11,7 +11,7 @@ class Base:
|
||||
# Device type
|
||||
self.is_mobile = info.user_agent.is_mobile
|
||||
# Task handler
|
||||
self.task_handler = TaskHandler(use_pywebio=True)
|
||||
self.task_handler = WebIOTaskHandler()
|
||||
defer_call(self.stop)
|
||||
|
||||
def stop(self) -> None:
|
||||
|
@ -62,6 +62,8 @@ class AlasManager:
|
||||
return 1
|
||||
elif len(self.log) == 0 or self.log[-1] == "Scheduler stopped.\n":
|
||||
return 2
|
||||
elif self.log[-2].endswith('Update event detected'):
|
||||
return 4
|
||||
else:
|
||||
return 3
|
||||
|
||||
|
@ -3,7 +3,7 @@ import datetime
|
||||
import subprocess
|
||||
import threading
|
||||
import time
|
||||
from typing import Generator
|
||||
from typing import Generator, Tuple
|
||||
|
||||
import requests
|
||||
from deploy.installer import DeployConfig, ExecutionError, Installer
|
||||
@ -26,11 +26,18 @@ class Updater(Config, Installer):
|
||||
def __init__(self, file=DEPLOY_CONFIG):
|
||||
super().__init__(file=file)
|
||||
self.state = 0
|
||||
self.delay = int(self.config['CheckUpdateInterval'])*60
|
||||
self.schedule_time = datetime.time.fromisoformat(
|
||||
self.config['AutoRestartTime'])
|
||||
self.event: threading.Event = None
|
||||
|
||||
@property
|
||||
def delay(self):
|
||||
self.read()
|
||||
return int(self.config['CheckUpdateInterval'])*60
|
||||
|
||||
@property
|
||||
def schedule_time(self):
|
||||
self.read()
|
||||
return datetime.time.fromisoformat(self.config['AutoRestartTime'])
|
||||
|
||||
@cached_property
|
||||
def repo(self):
|
||||
return self.config['Repository']
|
||||
@ -39,7 +46,65 @@ class Updater(Config, Installer):
|
||||
def branch(self):
|
||||
return self.config['Branch']
|
||||
|
||||
def execute_output(self, command) -> str:
|
||||
command = command.replace(
|
||||
r'\\', '/').replace('\\', '/').replace('\"', '"')
|
||||
log = subprocess.run(command, capture_output=True,
|
||||
text=True, encoding='utf8').stdout
|
||||
return log
|
||||
|
||||
def get_commit(self, revision='', n=1, short_sha1=False) -> Tuple:
|
||||
"""
|
||||
Return:
|
||||
(sha1, author, isotime, message,)
|
||||
"""
|
||||
ph = 'h' if short_sha1 else 'H'
|
||||
|
||||
log = self.execute_output(
|
||||
f'{self.git} log {revision} --pretty=format:"%{ph}---%an---%ad---%s" --date=iso -{n}')
|
||||
|
||||
if not log:
|
||||
return None, None, None, None
|
||||
|
||||
logs = log.split('\n')
|
||||
logs = list(map(lambda log: tuple(log.split('---')), logs))
|
||||
|
||||
if n == 1:
|
||||
return logs[0]
|
||||
else:
|
||||
return logs
|
||||
|
||||
def _check_update(self) -> bool:
|
||||
self.state = 'checking'
|
||||
source = 'origin'
|
||||
for _ in range(3):
|
||||
if self.execute(f'"{self.git}" fetch {source} {self.branch}', allow_failure=True):
|
||||
break
|
||||
else:
|
||||
logger.warning("Git fetch failed")
|
||||
return False
|
||||
|
||||
log = self.execute_output(
|
||||
f'{self.git} log --not --remotes={source}/* -1 --oneline')
|
||||
if log:
|
||||
logger.info(
|
||||
f"Cannot find local commit {log.split()[0]} in upstream, skip update")
|
||||
return False
|
||||
|
||||
sha1, _, _, message = self.get_commit(f'..{source}/{self.branch}')
|
||||
|
||||
if sha1:
|
||||
logger.info(f"New update avaliable")
|
||||
logger.info(f"{sha1[:8]} - {message}")
|
||||
return True
|
||||
else:
|
||||
logger.info(f"No update")
|
||||
return False
|
||||
|
||||
def _check_update_(self) -> bool:
|
||||
"""
|
||||
Deprecated
|
||||
"""
|
||||
self.state = 'checking'
|
||||
r = self.repo.split('/')
|
||||
owner = r[3]
|
||||
@ -60,20 +125,6 @@ class Updater(Config, Installer):
|
||||
if token:
|
||||
headers['Authorization'] = 'token ' + token
|
||||
|
||||
p = subprocess.run(f"{self.git} rev-parse HEAD",
|
||||
capture_output=True, text=True)
|
||||
if p.stdout is None:
|
||||
logger.warning("Cannot get local commit sha1")
|
||||
return 0
|
||||
|
||||
local_sha = p.stdout
|
||||
|
||||
if len(local_sha) != 41:
|
||||
logger.warning("Cannot get local commit sha1")
|
||||
return 0
|
||||
|
||||
local_sha = local_sha.strip()
|
||||
|
||||
try:
|
||||
list_commit = requests.get(
|
||||
base + f"{owner}/{repo}/branches/{self.branch}", headers=headers, params=para)
|
||||
@ -93,6 +144,8 @@ class Updater(Config, Installer):
|
||||
logger.warning("Check update failed when parsing return json")
|
||||
return 0
|
||||
|
||||
local_sha, _, _, _ = self._get_local_commit()
|
||||
|
||||
if sha == local_sha:
|
||||
logger.info("No update")
|
||||
return 0
|
||||
@ -192,7 +245,7 @@ class Updater(Config, Installer):
|
||||
self.event.clear()
|
||||
AlasManager.start_alas(instances, self.event)
|
||||
return False
|
||||
|
||||
|
||||
@staticmethod
|
||||
def _trigger_reload(delay=2):
|
||||
def trigger():
|
||||
|
@ -52,14 +52,15 @@ class Thread(threading.Thread):
|
||||
|
||||
|
||||
class Task:
|
||||
def __init__(self, g: Generator, delay: float, next_run: float = None) -> None:
|
||||
def __init__(self, g: Generator, delay: float, next_run: float = None, name: str = None) -> None:
|
||||
self.g = g
|
||||
g.send(None)
|
||||
self.delay = delay
|
||||
self.next_run = next_run if next_run else time.time()
|
||||
self.name = name if name is not None else self.g.__name__
|
||||
|
||||
def __str__(self) -> str:
|
||||
return f'<{self.g.__name__} (delay={self.delay})>'
|
||||
return f'<{self.name} (delay={self.delay})>'
|
||||
|
||||
def __next__(self) -> None:
|
||||
return next(self.g)
|
||||
@ -71,7 +72,7 @@ class Task:
|
||||
|
||||
|
||||
class TaskHandler:
|
||||
def __init__(self, use_pywebio=False) -> None:
|
||||
def __init__(self) -> None:
|
||||
# List of background running task
|
||||
self.tasks: List[Task] = []
|
||||
# List of task name to be removed
|
||||
@ -81,8 +82,6 @@ class TaskHandler:
|
||||
# Task running thread
|
||||
self._thread: Thread = None
|
||||
self._lock = threading.Lock()
|
||||
# register pywebio thread
|
||||
self.use_pywebio = use_pywebio
|
||||
|
||||
def add(self, func, delay: float, pending_delete: bool = False) -> None:
|
||||
"""
|
||||
@ -143,6 +142,13 @@ class TaskHandler:
|
||||
def remove_current_task(self) -> None:
|
||||
self.remove_task(self._task, nowait=True)
|
||||
|
||||
def get_task(self, name) -> Task:
|
||||
with self._lock:
|
||||
for task in self.tasks:
|
||||
if task.name == name:
|
||||
return task
|
||||
return None
|
||||
|
||||
def loop(self) -> None:
|
||||
"""
|
||||
Start task loop.
|
||||
@ -175,6 +181,11 @@ class TaskHandler:
|
||||
else:
|
||||
time.sleep(0.5)
|
||||
|
||||
def _get_thread(self) -> threading.Thread:
|
||||
thread = Thread(target=self.loop)
|
||||
thread.daemon = True
|
||||
return thread
|
||||
|
||||
def start(self) -> None:
|
||||
"""
|
||||
Start task handler.
|
||||
@ -183,9 +194,7 @@ class TaskHandler:
|
||||
if self._thread is not None and self._thread.is_alive():
|
||||
logger.warning("Task handler already running!")
|
||||
return
|
||||
self._thread = Thread(target=self.loop)
|
||||
if self.use_pywebio:
|
||||
register_thread(self._thread)
|
||||
self._thread = self._get_thread()
|
||||
self._thread.start()
|
||||
|
||||
def stop(self) -> None:
|
||||
@ -195,6 +204,13 @@ class TaskHandler:
|
||||
logger.info("Finish task handler")
|
||||
|
||||
|
||||
class WebIOTaskHandler(TaskHandler):
|
||||
def _get_thread(self) -> threading.Thread:
|
||||
thread = super()._get_thread()
|
||||
register_thread(thread)
|
||||
return thread
|
||||
|
||||
|
||||
class Switch:
|
||||
def __init__(self, status, get_state, name=None):
|
||||
"""
|
||||
|
Loading…
Reference in New Issue
Block a user