Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
289ce65431 | ||
|
|
704ce3bef2 | ||
|
|
00f3b76d2a | ||
|
|
efbbfa13ee |
88
build.py
88
build.py
@@ -182,8 +182,9 @@ def build():
|
||||
# Auto-deploy: sync shared files so Claude Code always has the latest
|
||||
deploy_shared_files()
|
||||
|
||||
# Publish release to Gitea
|
||||
# Publish release to Gitea + cleanup old remote releases
|
||||
publish_gitea_release(dst)
|
||||
cleanup_gitea_releases()
|
||||
|
||||
|
||||
def _get_gitea_auth() -> dict:
|
||||
@@ -311,6 +312,78 @@ def _version_key(path: str):
|
||||
return (0, 0, 0)
|
||||
|
||||
|
||||
def _tag_version_key(tag_name: str):
|
||||
"""Extract (major, minor, patch) from tag like 'v1.9.5'."""
|
||||
m = re.match(r'v(\d+)\.(\d+)\.(\d+)', tag_name)
|
||||
if m:
|
||||
return (int(m.group(1)), int(m.group(2)), int(m.group(3)))
|
||||
return (0, 0, 0)
|
||||
|
||||
|
||||
def cleanup_gitea_releases():
|
||||
"""Keep the first release (v1.0.0) and the last 5 on Gitea, delete the rest + orphan tags."""
|
||||
auth = _get_gitea_auth()
|
||||
if not auth:
|
||||
return
|
||||
|
||||
# --- Clean releases ---
|
||||
try:
|
||||
req = urllib.request.Request(f"{_GITEA_API}/releases?limit=50", headers=auth)
|
||||
resp = urllib.request.urlopen(req, timeout=30)
|
||||
releases = json.loads(resp.read())
|
||||
except Exception as e:
|
||||
print(f"Gitea release list failed: {e}")
|
||||
return
|
||||
|
||||
keep_tags = set()
|
||||
if len(releases) > 6:
|
||||
releases.sort(key=lambda r: _tag_version_key(r.get("tag_name", "")))
|
||||
first = releases[0]
|
||||
last_5 = releases[-5:]
|
||||
keep_ids = {first["id"]} | {r["id"] for r in last_5}
|
||||
keep_tags = {first.get("tag_name")} | {r.get("tag_name") for r in last_5}
|
||||
|
||||
removed = []
|
||||
for r in releases:
|
||||
if r["id"] in keep_ids:
|
||||
continue
|
||||
try:
|
||||
req = urllib.request.Request(
|
||||
f"{_GITEA_API}/releases/{r['id']}", headers=auth, method="DELETE")
|
||||
urllib.request.urlopen(req, timeout=15)
|
||||
removed.append(r.get("tag_name", "?"))
|
||||
except Exception as e:
|
||||
print(f"Failed to delete Gitea release {r.get('tag_name')}: {e}")
|
||||
if removed:
|
||||
print(f"Cleaned {len(removed)} old Gitea releases: {', '.join(removed)}")
|
||||
else:
|
||||
keep_tags = {r.get("tag_name") for r in releases}
|
||||
|
||||
# --- Clean orphan tags (tags without releases) ---
|
||||
try:
|
||||
req = urllib.request.Request(f"{_GITEA_API}/tags?limit=50", headers=auth)
|
||||
resp = urllib.request.urlopen(req, timeout=30)
|
||||
tags = json.loads(resp.read())
|
||||
except Exception:
|
||||
return
|
||||
|
||||
removed_tags = []
|
||||
for tag in tags:
|
||||
name = tag.get("name", "")
|
||||
if name in keep_tags:
|
||||
continue
|
||||
try:
|
||||
req = urllib.request.Request(
|
||||
f"{_GITEA_API}/tags/{name}", headers=auth, method="DELETE")
|
||||
urllib.request.urlopen(req, timeout=10)
|
||||
removed_tags.append(name)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
if removed_tags:
|
||||
print(f"Cleaned {len(removed_tags)} orphan Gitea tags: {', '.join(removed_tags)}")
|
||||
|
||||
|
||||
def cleanup_old_releases():
|
||||
"""Keep the first release (v1.0.0) and the last 5 releases, delete the rest."""
|
||||
import glob
|
||||
@@ -327,9 +400,20 @@ def cleanup_old_releases():
|
||||
keep = set([first] + last_5)
|
||||
|
||||
removed = []
|
||||
_flags = subprocess.CREATE_NO_WINDOW if sys.platform == "win32" else 0
|
||||
for f in all_exes:
|
||||
if f not in keep:
|
||||
os.remove(f)
|
||||
# Use git rm so deletion is staged for commit
|
||||
try:
|
||||
subprocess.run(
|
||||
["git", "rm", "-f", "--quiet", f],
|
||||
cwd=PROJECT_DIR, creationflags=_flags,
|
||||
capture_output=True,
|
||||
)
|
||||
except Exception:
|
||||
# Fallback: just delete the file
|
||||
if os.path.exists(f):
|
||||
os.remove(f)
|
||||
removed.append(os.path.basename(f))
|
||||
|
||||
if removed:
|
||||
|
||||
@@ -401,12 +401,15 @@ del /f /q "%~f0" >nul 2>&1
|
||||
return
|
||||
time.sleep(0.1)
|
||||
|
||||
first_run = True
|
||||
while self._running:
|
||||
# Check if enough time passed since last check
|
||||
# On first run after startup, always check regardless of interval
|
||||
last_check = self.store.get_last_update_check()
|
||||
now = time.time()
|
||||
|
||||
if not last_check or (now - last_check) >= _CHECK_INTERVAL:
|
||||
if first_run or not last_check or (now - last_check) >= _CHECK_INTERVAL:
|
||||
first_run = False
|
||||
info = self.check_now()
|
||||
if info and self._gui_callback:
|
||||
mode = self.store.get_update_mode()
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,6 +1,6 @@
|
||||
"""Version info for ServerManager."""
|
||||
|
||||
__version__ = "1.9.9"
|
||||
__version__ = "1.9.12"
|
||||
__app_name__ = "ServerManager"
|
||||
__author__ = "aibot777"
|
||||
__description__ = "Desktop GUI for managing remote servers"
|
||||
|
||||
Reference in New Issue
Block a user