Skip to content

Commit 847742a

Browse files
committed
add update for docker
1 parent 5cc9aa9 commit 847742a

13 files changed

Lines changed: 969 additions & 4 deletions

File tree

.github/workflows/build.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,10 @@ jobs:
295295
echo ${{ needs.version-info.outputs.version }}
296296
echo "VERSION='${{ needs.version-info.outputs.version }}'" >> module/__version__.py
297297
298+
- name: Copy uv files
299+
run: |
300+
cp backend/uv.lock backend/src/
301+
cp backend/pyproject.toml backend/src/
298302
299303
- name: Zip app
300304
run: |

backend/src/module/api/program.py

Lines changed: 129 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import asyncio
12
import logging
23
from contextlib import asynccontextmanager
34

@@ -8,7 +9,8 @@
89
from module.core import Program
910
from module.models import APIResponse
1011
from module.models.response import ResponseModel
11-
from module.security.api import UNAUTHORIZED, get_current_user
12+
from module.security.api import get_current_user
13+
from module.update import ReleaseChecker
1214

1315
from .response import u_response
1416

@@ -128,4 +130,129 @@ async def shutdown_program():
128130
dependencies=[Depends(get_current_user)],
129131
)
130132
async def check_downloader_status():
131-
return await program.program_status.check_downloader()
133+
return program.program_status.check_downloader()
134+
135+
136+
# Check for updates
137+
@router.get(
138+
"/check/update",
139+
tags=["update"],
140+
response_model=dict,
141+
dependencies=[Depends(get_current_user)],
142+
)
143+
async def check_for_update(include_prerelease: bool = False):
144+
"""检查是否有可用的版本更新
145+
146+
Args:
147+
include_prerelease: 是否包含预发布版本
148+
149+
Returns:
150+
dict: 包含版本检查结果的字典
151+
"""
152+
try:
153+
checker = ReleaseChecker("shinonomeow", "Auto_Bangumi")
154+
result = await checker.check_for_update(include_prerelease=True)
155+
return result
156+
except Exception as e:
157+
logger.error(f"Failed to check for updates: {e}")
158+
raise HTTPException(
159+
status_code=500,
160+
detail={"msg_en": "Failed to check for updates.", "msg_zh": "检查更新失败。", "error": str(e)},
161+
)
162+
163+
164+
@router.post("/update", response_model=APIResponse, dependencies=[Depends(get_current_user)])
165+
async def update_program(download_url: str):
166+
"""Docker 环境更新接口
167+
168+
Args:
169+
download_url: 更新包下载 URL(必须是 GitHub releases)
170+
171+
Returns:
172+
APIResponse: 更新结果
173+
"""
174+
try:
175+
# 检测是否在 Docker 环境
176+
from module.utils.environment import is_docker_environment
177+
178+
if not is_docker_environment():
179+
raise HTTPException(
180+
status_code=400,
181+
detail={
182+
"msg_en": "Update only supported in Docker environment.",
183+
"msg_zh": "更新功能仅支持 Docker 环境。",
184+
},
185+
)
186+
187+
# 导入更新器
188+
from module.update import docker_updater
189+
190+
# 创建异步任务执行更新
191+
async def perform_update():
192+
try:
193+
# 等待一小段时间让 API 响应返回
194+
await asyncio.sleep(1)
195+
196+
logger.info(f"[Program] Starting update from URL: {download_url}")
197+
198+
# 停止应用核心
199+
await program.stop()
200+
201+
# 执行更新
202+
await docker_updater.update(download_url)
203+
204+
# 强制重启容器
205+
docker_updater.force_restart()
206+
207+
except Exception as e:
208+
logger.error(f"[Program] Update failed: {e}")
209+
# 尝试重启应用核心
210+
try:
211+
await program.start()
212+
except Exception as restart_error:
213+
logger.error(f"[Program] Failed to restart after update failure: {restart_error}")
214+
215+
# 启动异步更新任务
216+
asyncio.create_task(perform_update())
217+
218+
# 立即返回响应
219+
return u_response(
220+
ResponseModel(
221+
status=True,
222+
status_code=200,
223+
msg_en="Update started successfully. Container will restart shortly.",
224+
msg_zh="更新已开始。容器将很快重启。",
225+
data={"download_url": download_url},
226+
)
227+
)
228+
229+
except HTTPException:
230+
raise
231+
except Exception as e:
232+
logger.error(f"[Program] Update initiation failed: {e}")
233+
raise HTTPException(
234+
status_code=500,
235+
detail={"msg_en": "Failed to start update process.", "msg_zh": "启动更新进程失败。", "error": str(e)},
236+
)
237+
238+
239+
# Update status check
240+
@router.get("/update/status", response_model=dict, dependencies=[Depends(get_current_user)])
241+
async def get_update_status():
242+
"""获取更新状态
243+
244+
Returns:
245+
dict: 更新状态信息
246+
"""
247+
import os
248+
249+
from module.utils.environment import get_environment_info, is_docker_environment
250+
251+
# 检查是否有更新锁文件
252+
update_lock_exists = os.path.exists("/tmp/auto_bangumi_update.lock")
253+
254+
return {
255+
"update_in_progress": update_lock_exists,
256+
"environment": get_environment_info(),
257+
"update_supported": is_docker_environment(),
258+
}

backend/src/module/database/bangumi.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,9 @@ def add(self, data: Bangumi):
5353
return True
5454

5555
def update(self, data: Bangumi) -> bool:
56-
self.session.merge(data)
56+
merge_data = self.session.merge(data)
5757
self.session.commit()
58-
self.session.refresh(data)
58+
self.session.refresh(merge_data)
5959
# logger.debug(f"[Database] Update {data.official_title}")
6060
return True
6161

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,14 @@
1+
from .docker_updater import docker_updater, DockerUpdater
2+
from .release_checker import ReleaseChecker, ReleaseInfo
13
from .startup import first_run, start_up
24
from .version_check import version_check
35

46
__all__ = [
57
"first_run",
68
"start_up",
79
"version_check",
10+
"ReleaseChecker",
11+
"ReleaseInfo",
12+
"docker_updater",
13+
"DockerUpdater",
814
]

0 commit comments

Comments
 (0)