Add check for available software updates (#118)

* Add feature to check github repo for available updates

* Add Check for Updates to Help menu
This commit is contained in:
2024-08-24 12:12:30 -05:00
committed by GitHub
parent 98ab837057
commit 2548280dcc
4 changed files with 85 additions and 5 deletions

View File

@@ -13,9 +13,10 @@ from src.distributed_job_manager import DistributedJobManager
from src.engines.engine_manager import EngineManager from src.engines.engine_manager import EngineManager
from src.render_queue import RenderQueue from src.render_queue import RenderQueue
from src.utilities.config import Config from src.utilities.config import Config
from src.utilities.misc_helper import system_safe_path, current_system_cpu, current_system_os, current_system_os_version from src.utilities.misc_helper import (system_safe_path, current_system_cpu, current_system_os,
current_system_os_version, check_for_updates)
from src.utilities.zeroconf_server import ZeroconfServer from src.utilities.zeroconf_server import ZeroconfServer
from version import APP_NAME from version import APP_NAME, APP_VERSION, APP_REPO_NAME, APP_REPO_OWNER
logger = logging.getLogger() logger = logging.getLogger()
@@ -60,6 +61,12 @@ def run(server_only=False) -> int:
# Setup logging for console ui # Setup logging for console ui
buffer_handler = __setup_buffer_handler() if not server_only else None buffer_handler = __setup_buffer_handler() if not server_only else None
# check for updates
update_thread = threading.Thread(target=check_for_updates, args=(APP_REPO_NAME, APP_REPO_OWNER, APP_NAME,
APP_VERSION))
update_thread.start()
# main start
logger.info(f"Starting {APP_NAME} Render Server") logger.info(f"Starting {APP_NAME} Render Server")
return_code = 0 return_code = 0
try: try:

View File

@@ -1,8 +1,6 @@
''' app/ui/widgets/menubar.py ''' ''' app/ui/widgets/menubar.py '''
import sys
from PyQt6.QtGui import QAction from PyQt6.QtGui import QAction
from PyQt6.QtWidgets import QMenuBar, QApplication from PyQt6.QtWidgets import QMenuBar, QApplication, QMessageBox, QDialog, QVBoxLayout, QLabel, QPushButton
class MenuBar(QMenuBar): class MenuBar(QMenuBar):
@@ -43,6 +41,9 @@ class MenuBar(QMenuBar):
about_action = QAction("About", self) about_action = QAction("About", self)
about_action.triggered.connect(self.show_about) about_action.triggered.connect(self.show_about)
help_menu.addAction(about_action) help_menu.addAction(about_action)
update_action = QAction("Check for Updates...", self)
update_action.triggered.connect(self.check_for_updates)
help_menu.addAction(update_action)
def new_job(self): def new_job(self):
self.parent().new_job() self.parent().new_job()
@@ -55,3 +56,46 @@ class MenuBar(QMenuBar):
from src.ui.about_window import AboutDialog from src.ui.about_window import AboutDialog
dialog = AboutDialog() dialog = AboutDialog()
dialog.exec() dialog.exec()
@staticmethod
def check_for_updates():
from src.utilities.misc_helper import check_for_updates
from version import APP_NAME, APP_VERSION, APP_REPO_NAME, APP_REPO_OWNER
found_update = check_for_updates(APP_REPO_NAME, APP_REPO_OWNER, APP_NAME, APP_VERSION)
if found_update:
dialog = UpdateDialog(found_update, APP_VERSION)
dialog.exec()
else:
QMessageBox.information(None, "No Update", "No updates available.")
class UpdateDialog(QDialog):
def __init__(self, release_info, current_version, parent=None):
super().__init__(parent)
self.setWindowTitle(f"Update Available ({current_version} -> {release_info['tag_name']})")
layout = QVBoxLayout()
label = QLabel(f"A new version ({release_info['tag_name']}) is available! Current version: {current_version}")
layout.addWidget(label)
# Label to show the release notes
description = QLabel(release_info["body"])
layout.addWidget(description)
# Button to download the latest version
download_button = QPushButton(f"Download Latest Version ({release_info['tag_name']})")
download_button.clicked.connect(lambda: self.open_url(release_info["html_url"]))
layout.addWidget(download_button)
# OK button to dismiss the dialog
ok_button = QPushButton("Dismiss")
ok_button.clicked.connect(self.accept) # Close the dialog when clicked
layout.addWidget(ok_button)
self.setLayout(layout)
def open_url(self, url):
from PyQt6.QtCore import QUrl
from PyQt6.QtGui import QDesktopServices
QDesktopServices.openUrl(QUrl(url))
self.accept()

View File

@@ -159,6 +159,33 @@ def copy_directory_contents(src_dir, dst_dir):
shutil.copy2(src_path, dst_path) shutil.copy2(src_path, dst_path)
def check_for_updates(repo_name, repo_owner, app_name, current_version):
def get_github_releases(owner, repo):
import requests
url = f"https://api.github.com/repos/{owner}/{repo}/releases"
try:
response = requests.get(url, timeout=3)
response.raise_for_status()
releases = response.json()
return releases
except Exception as e:
logger.error(f"Error checking for updates: {e}")
return []
releases = get_github_releases(repo_owner, repo_name)
if not releases:
return
latest_version = releases[0]
latest_version_tag = latest_version['tag_name']
from packaging import version
if version.parse(latest_version_tag) > version.parse(current_version):
logger.info(f"Newer version of {app_name} available. "
f"Latest: {latest_version_tag}, Current: {current_version}")
return latest_version
def is_localhost(comparison_hostname): def is_localhost(comparison_hostname):
# this is necessary because socket.gethostname() does not always include '.local' - This is a sanitized comparison # this is necessary because socket.gethostname() does not always include '.local' - This is a sanitized comparison
try: try:

View File

@@ -4,3 +4,5 @@ APP_AUTHOR = "Brett Williams"
APP_DESCRIPTION = "Distributed Render Farm Tools" APP_DESCRIPTION = "Distributed Render Farm Tools"
APP_COPYRIGHT_YEAR = "2024" APP_COPYRIGHT_YEAR = "2024"
APP_LICENSE = "MIT License" APP_LICENSE = "MIT License"
APP_REPO_NAME = APP_NAME
APP_REPO_OWNER = "blw1138"