1
0

Add automatic version updating feature

This commit is contained in:
Ö. Efe D.
2025-03-09 19:36:28 +01:00
parent a7a4094aaf
commit f532231f52
4 changed files with 238 additions and 1 deletions

181
.github/scripts/update_mod_versions.py vendored Normal file
View File

@@ -0,0 +1,181 @@
#!/usr/bin/env python3
import json
import os
import re
import requests
import sys
import time
from datetime import datetime
from pathlib import Path
# GitHub API rate limits are higher with authentication
GITHUB_TOKEN = os.environ.get('GITHUB_TOKEN')
HEADERS = {'Authorization': f'token {GITHUB_TOKEN}'} if GITHUB_TOKEN else {}
def extract_repo_info(repo_url):
"""Extract owner and repo name from GitHub repo URL."""
match = re.search(r'github\.com/([^/]+)/([^/]+)', repo_url)
if match:
owner = match.group(1)
repo = match.group(2)
# Remove .git suffix if present
repo = repo.rstrip('.git')
return owner, repo
return None, None
def get_latest_release(owner, repo):
"""Get the latest release version from GitHub."""
url = f'https://api.github.com/repos/{owner}/{repo}/releases/latest'
try:
response = requests.get(url, headers=HEADERS)
if response.status_code == 200:
data = response.json()
return data.get('tag_name')
elif response.status_code == 404:
# No releases found
return None
elif response.status_code == 403 and 'rate limit exceeded' in response.text.lower():
print("GitHub API rate limit exceeded. Waiting for 5 minutes...")
time.sleep(300) # Wait for 5 minutes
return get_latest_release(owner, repo) # Retry
else:
print(f"Error fetching releases: HTTP {response.status_code} - {response.text}")
return None
except Exception as e:
print(f"Exception while fetching releases: {str(e)}")
return None
def get_latest_commit(owner, repo):
"""Get the latest commit hash from GitHub."""
url = f'https://api.github.com/repos/{owner}/{repo}/commits'
try:
response = requests.get(url, headers=HEADERS)
if response.status_code == 200:
commits = response.json()
if commits and len(commits) > 0:
# Return shortened commit hash (first 7 characters)
return commits[0]['sha'][:7]
elif response.status_code == 403 and 'rate limit exceeded' in response.text.lower():
print("GitHub API rate limit exceeded. Waiting for 5 minutes...")
time.sleep(300) # Wait for 5 minutes
return get_latest_commit(owner, repo) # Retry
else:
print(f"Error fetching commits: HTTP {response.status_code} - {response.text}")
return None
except Exception as e:
print(f"Exception while fetching commits: {str(e)}")
return None
def process_mods():
"""Process all mods and update versions where needed."""
mods_dir = Path('mods')
updated_mods = []
print(f"Scanning {mods_dir} for mods with automatic version control...")
# Find all mod directories
for mod_dir in [d for d in mods_dir.iterdir() if d.is_dir()]:
meta_file = mod_dir / 'meta.json'
if not meta_file.exists():
continue
try:
with open(meta_file, 'r', encoding='utf-8') as f:
meta = json.load(f)
# Skip mods without automatic version checking enabled
if not meta.get('automatic-version-check', False):
continue
print(f"Processing {mod_dir.name}...")
repo_url = meta.get('repo')
if not repo_url:
print(f"⚠️ Warning: Mod {mod_dir.name} has automatic-version-check but no repo URL")
continue
owner, repo = extract_repo_info(repo_url)
if not owner or not repo:
print(f"⚠️ Warning: Could not extract repo info from {repo_url}")
continue
print(f"Checking GitHub repo: {owner}/{repo}")
# Try to get latest release version first
new_version = get_latest_release(owner, repo)
version_source = "release"
# If no releases, fall back to latest commit
if not new_version:
print("No releases found, checking latest commit...")
new_version = get_latest_commit(owner, repo)
version_source = "commit"
if not new_version:
print(f"⚠️ Warning: Could not determine version for {mod_dir.name}")
continue
current_version = meta.get('version')
# Update version if it changed
if current_version != new_version:
print(f"✅ Updating {mod_dir.name} from {current_version or 'none'} to {new_version} ({version_source})")
meta['version'] = new_version
with open(meta_file, 'w', encoding='utf-8') as f:
# Preserve formatting with indentation
json.dump(meta, f, indent=2, ensure_ascii=False)
f.write("\n") # Add newline at end of file
updated_mods.append({
'name': meta.get('title', mod_dir.name),
'old_version': current_version,
'new_version': new_version,
'source': version_source
})
else:
print(f" No version change for {mod_dir.name} (current: {current_version})")
except Exception as e:
print(f"❌ Error processing {mod_dir.name}: {str(e)}")
return updated_mods
def generate_commit_message(updated_mods):
"""Generate a detailed commit message listing all updated mods."""
if not updated_mods:
return "No mod versions updated"
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
message = f"Auto-update mod versions ({timestamp})\n\n"
message += "Updated mods:\n"
for mod in updated_mods:
old_ver = mod['old_version'] or 'none'
message += f"- {mod['name']}: {old_ver}{mod['new_version']} ({mod['source']})\n"
return message
if __name__ == "__main__":
print(f"🔄 Starting automatic mod version update at {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}...")
updated_mods = process_mods()
if updated_mods:
# Write commit message to a file that the GitHub Action can use
commit_message = generate_commit_message(updated_mods)
with open('commit_message.txt', 'w', encoding='utf-8') as f:
f.write(commit_message)
print(f"✅ Completed. Updated {len(updated_mods)} mod versions.")
else:
print(" Completed. No mod versions needed updating.")
# Exit with status code 0 even if no updates were made
sys.exit(0)