1
0

update_manager.py 3.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. import subprocess
  2. import logging
  3. # Configure logging
  4. logger = logging.getLogger(__name__)
  5. def check_git_updates():
  6. """Check for available Git updates."""
  7. try:
  8. logger.debug("Checking for Git updates")
  9. subprocess.run(["git", "fetch", "--tags", "--force"], check=True)
  10. latest_remote_tag = subprocess.check_output(
  11. ["git", "describe", "--tags", "--abbrev=0", "origin/main"]
  12. ).strip().decode()
  13. latest_local_tag = subprocess.check_output(
  14. ["git", "describe", "--tags", "--abbrev=0"]
  15. ).strip().decode()
  16. tag_behind_count = 0
  17. if latest_local_tag != latest_remote_tag:
  18. tags = subprocess.check_output(
  19. ["git", "tag", "--merged", "origin/main"], text=True
  20. ).splitlines()
  21. found_local = False
  22. for tag in tags:
  23. if tag == latest_local_tag:
  24. found_local = True
  25. elif found_local:
  26. tag_behind_count += 1
  27. if tag == latest_remote_tag:
  28. break
  29. updates_available = latest_remote_tag != latest_local_tag
  30. logger.info(f"Updates available: {updates_available}, {tag_behind_count} versions behind")
  31. return {
  32. "updates_available": updates_available,
  33. "tag_behind_count": tag_behind_count,
  34. "latest_remote_tag": latest_remote_tag,
  35. "latest_local_tag": latest_local_tag,
  36. }
  37. except subprocess.CalledProcessError as e:
  38. logger.error(f"Error checking Git updates: {e}")
  39. return {
  40. "updates_available": False,
  41. "tag_behind_count": 0,
  42. "latest_remote_tag": None,
  43. "latest_local_tag": None,
  44. }
  45. def update_software():
  46. """Update the software to the latest version."""
  47. error_log = []
  48. logger.info("Starting software update process")
  49. def run_command(command, error_message):
  50. try:
  51. logger.debug(f"Running command: {' '.join(command)}")
  52. subprocess.run(command, check=True)
  53. except subprocess.CalledProcessError as e:
  54. logger.error(f"{error_message}: {e}")
  55. error_log.append(error_message)
  56. try:
  57. subprocess.run(["git", "fetch", "--tags"], check=True)
  58. latest_remote_tag = subprocess.check_output(
  59. ["git", "describe", "--tags", "--abbrev=0", "origin/main"]
  60. ).strip().decode()
  61. logger.info(f"Latest remote tag: {latest_remote_tag}")
  62. except subprocess.CalledProcessError as e:
  63. error_msg = f"Failed to fetch tags or get latest remote tag: {e}"
  64. logger.error(error_msg)
  65. error_log.append(error_msg)
  66. return False, error_msg, error_log
  67. run_command(["git", "checkout", latest_remote_tag, '--force'], f"Failed to checkout version {latest_remote_tag}")
  68. # Pull new image and restart container using direct docker commands
  69. # Note: docker restart reuses the existing container, so code changes (via volume mount)
  70. # are picked up immediately. For image changes (new dependencies), manual recreation is needed.
  71. run_command(["docker", "pull", "ghcr.io/tuanchris/dune-weaver:main"], "Failed to pull Docker image")
  72. run_command(["docker", "restart", "dune-weaver"], "Failed to restart Docker container")
  73. update_status = check_git_updates()
  74. if (
  75. update_status["updates_available"] is False
  76. and update_status["latest_local_tag"] == update_status["latest_remote_tag"]
  77. ):
  78. logger.info("Software update completed successfully")
  79. return True, None, None
  80. else:
  81. logger.error("Software update incomplete")
  82. return False, "Update incomplete", error_log