1
0

Merge branch 'skyline69:main' into main

This commit is contained in:
Kingmaxthe2
2025-04-21 03:35:48 -05:00
committed by GitHub
11 changed files with 304 additions and 92 deletions

5
.github/scripts/requirements.lock vendored Normal file
View File

@@ -0,0 +1,5 @@
certifi==2025.1.31
charset-normalizer==3.4.1
idna==3.10
requests==2.32.3
urllib3==2.4.0

View File

@@ -3,12 +3,14 @@
import json
import os
import re
import requests
import sys
import time
from datetime import datetime
from enum import Enum
from pathlib import Path
import requests
# 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 {}
@@ -24,12 +26,19 @@ def extract_repo_info(repo_url):
return owner, repo
return None, None
def get_version_string(source, owner, repo, start_timestamp, n = 1):
VersionSource = Enum("VersionSource", [
("RELEASE_TAG", "release"),
("HEAD", "commit"),
])
def get_version_string(source: Enum, owner, repo, start_timestamp, n = 1):
"""Get the version string from a given GitHub repo."""
if source == 'release':
if source is VersionSource.RELEASE_TAG:
url = f'https://api.github.com/repos/{owner}/{repo}/releases/latest'
else:
if not source is VersionSource.HEAD:
print(f"UNIMPLEMENTED(VersionSource): `{source}`,\nfalling back to `HEAD`")
source = VersionSource.HEAD
url = f'https://api.github.com/repos/{owner}/{repo}/commits'
try:
@@ -42,20 +51,30 @@ def get_version_string(source, owner, repo, start_timestamp, n = 1):
api_resource = response.headers.get('x-ratelimit-resource')
print(f"GitHub API ({api_resource}) calls: {api_rate_usage}/{api_rate_limit}")
if response.status_code == 200:
if source == 'release':
data = response.json()
# Return name of latest tag
return data.get('tag_name')
else:
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 == 404:
if response.status_code == 404:
# Not found
return None
elif api_rate_remaining == 0 or (response.status_code == 403 and 'rate limit exceeded' in response.text.lower()):
if response.status_code == 200:
data = response.json()
if source is VersionSource.RELEASE_TAG:
# Return name of latest tag
return data.get('tag_name')
if data and len(data) > 0:
# Return shortened commit hash (first 7 characters)
return data[0]['sha'][:7]
print(f"⚠️ Warning: unexpected response format for {source}s:\n{
json.dumps(data, indent=2, ensure_ascii=False)
}")
return
if api_rate_remaining == 0 or (
response.status_code == 403
and "rate limit exceeded" in response.text.lower()
):
print(f"GitHub API access is being rate limited!")
current_timestamp = int(time.time())
@@ -95,86 +114,98 @@ def process_mods(start_timestamp):
"""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()]:
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}")
# If download url links to latest head, use version of latest commit hash
download_url = meta.get('downloadURL')
if "/archive/refs/heads/" in download_url:
print("Download URL links to HEAD, checking latest commit...")
version_source = "commit"
new_version = get_version_string(version_source, owner, repo, start_timestamp)
else:
# Try to get latest release version
print("Checking releases for latest version tag...")
version_source = "release"
new_version = get_version_string(version_source, owner, repo, start_timestamp)
# If no releases, fall back to latest commit
if not new_version:
print("No releases found, checking latest commit...")
version_source = "commit"
new_version = get_version_string(version_source, owner, repo, start_timestamp)
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})")
try:
if mod := process_mod(start_timestamp, mod_dir.name, mod_dir / 'meta.json'):
updated_mods.append(mod)
except Exception as e:
print(f"❌ Error processing {mod_dir.name}: {str(e)}")
return updated_mods
def process_mod(start_timestamp, name, meta_file):
if not meta_file.exists():
return
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'):
return
print(f"Processing {name}...")
repo_url = meta.get('repo')
if not repo_url:
print(f"⚠️ Warning: Mod {name} has automatic-version-check but no repo URL")
return
owner, repo = extract_repo_info(repo_url)
if not owner or not repo:
print(f"⚠️ Warning: Could not extract repo info from {repo_url}")
return
print(f"Checking GitHub repo: `{owner}/{repo}`")
# If download url links to latest head, use version of latest commit hash
download_url = meta.get('downloadURL')
new_version = None
if "/archive/refs/heads/" in download_url:
print("Download URL links to HEAD, checking latest commit...")
source = VersionSource.HEAD
new_version = get_version_string(VersionSource.HEAD, owner, repo, start_timestamp)
else:
print("Checking releases for latest version tag...")
source = VersionSource.RELEASE_TAG
new_version = get_version_string(source, owner, repo, start_timestamp)
if not new_version:
print("No releases found, falling back to latest commit instead...")
source = VersionSource.HEAD
new_version = get_version_string(source, owner, repo, start_timestamp)
if not new_version:
print(f"⚠️ Warning: Could not determine version for {name}")
return
current_version = meta.get('version')
# Update version if it changed
if current_version == new_version:
print(f" No version change for {name} (current: {current_version})")
return
print(
f"✅ Updating {name} from {current_version} to {new_version} ({source})"
)
meta['version'] = new_version
if "/archive/refs/tags/" in download_url:
meta['downloadURL'] = f"{repo_url}/archive/refs/tags/{meta['version']}.zip"
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
return {
'name': meta.get('title', name),
'old_version': current_version,
'new_version': meta['version'],
'source': source
}
def generate_commit_message(updated_mods):
"""Generate a detailed commit message listing all updated mods."""
if not updated_mods:
@@ -191,6 +222,7 @@ def generate_commit_message(updated_mods):
return message
if __name__ == "__main__":
start_timestamp = int(time.time())
start_datetime = datetime.fromtimestamp(start_timestamp).strftime('%H:%M:%S')

View File

@@ -18,13 +18,13 @@ jobs:
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.10'
python-version: '3.12'
cache: 'pip' # This enables pip caching
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r .github/scripts/requirements.txt
pip install -r .github/scripts/requirements.lock
- name: Update mod versions
env:

175
.gitignore vendored
View File

@@ -1 +1,176 @@
.DS_Store
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
.pybuilder/
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# UV
# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
#uv.lock
# poetry
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
#poetry.lock
# pdm
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
#pdm.lock
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
# in version control.
# https://pdm.fming.dev/latest/usage/project/#working-with-version-control
.pdm.toml
.pdm-python
.pdm-build/
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# pytype static type analyzer
.pytype/
# Cython debug symbols
cython_debug/
# PyCharm
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/
# Ruff stuff:
.ruff_cache/
# PyPI configuration file
.pypirc

View File

@@ -11,5 +11,5 @@
"repo": "https://github.com/BakersDozenBagels/BalatroBakery",
"downloadURL": "https://github.com/BakersDozenBagels/BalatroBakery/archive/refs/heads/main.zip",
"automatic-version-check": true,
"version": "c52d911"
"version": "5f89d04"
}

View File

@@ -10,5 +10,5 @@
"repo": "https://github.com/InertSteak/Pokermon",
"downloadURL": "https://github.com/InertSteak/Pokermon/archive/refs/heads/main.zip",
"automatic-version-check": true,
"version": "4595361"
"version": "fa172e8"
}

View File

@@ -9,5 +9,5 @@
"repo": "https://github.com/Steamodded/smods",
"downloadURL": "https://github.com/Steamodded/smods/archive/refs/heads/main.zip",
"automatic-version-check": true,
"version": "5858625"
"version": "8654267"
}

View File

@@ -8,7 +8,7 @@
],
"author": "janw4ld",
"repo": "https://github.com/janw4ld/balatro-typist-mod",
"downloadURL": "https://github.com/janw4ld/balatro-typist-mod/archive/refs/heads/main.zip",
"downloadURL": "https://github.com/janw4ld/balatro-typist-mod/archive/refs/tags/1.6.1.zip",
"automatic-version-check": true,
"version": "bce214b"
"version": "1.6.1"
}

View File

@@ -9,6 +9,6 @@
"repo": "https://github.com/lord-ruby/Entropy",
"downloadURL": "https://github.com/lord-ruby/Entropy/archive/refs/heads/main.zip",
"folderName": "Entropy",
"version": "dfd7e40",
"version": "f18ba8e",
"automatic-version-check": true
}

View File

@@ -10,5 +10,5 @@
"repo": "https://github.com/nh6574/JoyousSpring",
"downloadURL": "https://github.com/nh6574/JoyousSpring/archive/refs/heads/master.zip",
"automatic-version-check": true,
"version": "399d20b"
"version": "705074b"
}

View File

@@ -9,5 +9,5 @@
"repo": "https://github.com/the-Astra/Maximus",
"downloadURL": "https://github.com/the-Astra/Maximus/archive/refs/heads/main.zip",
"automatic-version-check": true,
"version": "4a2da31"
"version": "5d5afa7"
}