1
0
Files
balatro-mod-index/.github/scripts/update_mod_versions.py
2025-03-09 19:36:28 +01:00

182 lines
6.8 KiB
Python
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/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)