171 lines
6.8 KiB
Python
171 lines
6.8 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
generate_version_json.py
|
|
Auto-generates version.json by:
|
|
1. Reading the current version from project.godot
|
|
2. Auto-bumping the PATCH number
|
|
3. Reading player-friendly entries from CHANGELOG_DRAFT.md
|
|
4. Injecting them into version.json with a date stamp
|
|
5. Updating version in export_presets.cfg export paths
|
|
6. Clearing the [NEXT] section in CHANGELOG_DRAFT.md
|
|
|
|
Usage:
|
|
python3 tools/generate_version_json.py # Full release (CI)
|
|
python3 tools/generate_version_json.py --local # Local: update versions but keep changelog
|
|
python3 tools/generate_version_json.py --skip-changelog # Skip changelog update
|
|
"""
|
|
|
|
import json
|
|
import re
|
|
import os
|
|
import sys
|
|
import argparse
|
|
from datetime import date
|
|
|
|
PROJECT_GODOT = "project.godot"
|
|
CHANGELOG_DRAFT = "CHANGELOG_DRAFT.md"
|
|
VERSION_JSON = "assets/data/version.json"
|
|
EXPORT_PRESETS = "export_presets.cfg"
|
|
MANIFEST_URL = "https://raw.githubusercontent.com/adtpdn/tekton-updates/main/latest/patch.pck"
|
|
|
|
# ─── Parse command line arguments ─────────────────────────────────────────────
|
|
parser = argparse.ArgumentParser(description="Generate version.json and update version numbers")
|
|
parser.add_argument("--local", action="store_true", help="Local mode: update version.json and export_presets but don't clear changelog")
|
|
parser.add_argument("--skip-changelog", action="store_true", help="Skip updating CHANGELOG_DRAFT.md")
|
|
args = parser.parse_args()
|
|
|
|
# ─── 1. Read current version from project.godot ──────────────────────────────
|
|
version_str = "2.1.5"
|
|
with open(PROJECT_GODOT, "r") as f:
|
|
for line in f:
|
|
m = re.search(r'config/version="([^"]+)"', line)
|
|
if m:
|
|
version_str = m.group(1)
|
|
break
|
|
|
|
# ─── 2. Auto-bump patch number ───────────────────────────────────────────────
|
|
parts = version_str.split(".")
|
|
parts[-1] = str(int(parts[-1]) + 1)
|
|
new_version = ".".join(parts)
|
|
|
|
print(f"Version: {version_str} -> {new_version}")
|
|
|
|
# ─── 3. Read CHANGELOG_DRAFT.md ──────────────────────────────────────────────
|
|
changelog_lines = []
|
|
in_next = False
|
|
remaining_lines = []
|
|
|
|
with open(CHANGELOG_DRAFT, "r", encoding="utf-8") as f:
|
|
raw = f.readlines()
|
|
|
|
for line in raw:
|
|
if line.strip() == "## [NEXT]":
|
|
in_next = True
|
|
continue
|
|
if in_next:
|
|
# Stop at next ## heading
|
|
if line.startswith("## ") and "[NEXT]" not in line:
|
|
in_next = False
|
|
remaining_lines.append(line)
|
|
elif line.strip():
|
|
# Strip leading "- " and emoji bullet
|
|
clean = line.strip().lstrip("- ").strip()
|
|
changelog_lines.append(clean)
|
|
else:
|
|
remaining_lines.append(line)
|
|
|
|
if not changelog_lines:
|
|
print("[INFO] No [NEXT] entries found in CHANGELOG_DRAFT.md -- skipping version bump and release generation.")
|
|
exit(0)
|
|
|
|
print(f"Changelog entries: {len(changelog_lines)}")
|
|
|
|
# ─── 4. Load existing version.json ───────────────────────────────────────────
|
|
existing = {"releases": []}
|
|
if os.path.exists(VERSION_JSON):
|
|
with open(VERSION_JSON, "r") as f:
|
|
existing = json.load(f)
|
|
|
|
# ─── 5. Prepend new release ───────────────────────────────────────────────────
|
|
today = date.today().isoformat()
|
|
new_release = {
|
|
"version": new_version,
|
|
"date": today,
|
|
"pck_url": MANIFEST_URL,
|
|
"pck_size": 0,
|
|
"changelog": changelog_lines
|
|
}
|
|
|
|
# Remove any existing entry with the same version
|
|
existing["releases"] = [r for r in existing["releases"] if r.get("version") != new_version]
|
|
existing["releases"].insert(0, new_release)
|
|
|
|
manifest = {
|
|
"latest_version": new_version,
|
|
"minimum_app_version": existing.get("minimum_app_version", "2.1.0"),
|
|
"releases": existing["releases"]
|
|
}
|
|
|
|
with open(VERSION_JSON, "w", encoding="utf-8") as f:
|
|
json.dump(manifest, f, indent="\t")
|
|
f.write("\n")
|
|
|
|
print(f"[OK] Written: {VERSION_JSON} (latest={new_version})")
|
|
|
|
# ─── 6. Bump version in project.godot ────────────────────────────────────────
|
|
with open(PROJECT_GODOT, "r") as f:
|
|
godot_content = f.read()
|
|
|
|
godot_content = re.sub(
|
|
r'(config/version=")[^"]+(")',
|
|
rf'\g<1>{new_version}\g<2>',
|
|
godot_content
|
|
)
|
|
|
|
with open(PROJECT_GODOT, "w", encoding="utf-8") as f:
|
|
f.write(godot_content)
|
|
|
|
print(f"[OK] Bumped project.godot -> {new_version}")
|
|
|
|
# ─── 7. Update version in export_presets.cfg ───────────────────────────────────
|
|
if os.path.exists(EXPORT_PRESETS):
|
|
with open(EXPORT_PRESETS, "r", encoding="utf-8") as f:
|
|
presets_content = f.read()
|
|
|
|
# Replace version in desktop export paths (e.g., v2.1.7 -> v2.1.8)
|
|
# Desktop: tekton_armageddon_v2.1.7.exe/zip/x86_64
|
|
# Android: tekton-dash-armageddon-v.2.1.5.apk (different format)
|
|
desktop_pattern = r'tekton_armageddon_v\d+\.\d+\.\d+'
|
|
presets_content = re.sub(desktop_pattern, f'tekton_armageddon_v{new_version}', presets_content)
|
|
|
|
# Also update Android version if needed (different format)
|
|
android_pattern = r'tekton-dash-armageddon-v\.\d+\.\d+\.\d+'
|
|
presets_content = re.sub(android_pattern, f'tekton-dash-armageddon-v.{new_version}', presets_content)
|
|
|
|
with open(EXPORT_PRESETS, "w", encoding="utf-8") as f:
|
|
f.write(presets_content)
|
|
|
|
print(f"[OK] Updated export paths in {EXPORT_PRESETS} -> v{new_version}")
|
|
else:
|
|
print(f"[WARN] {EXPORT_PRESETS} not found, skipping export path update")
|
|
|
|
# ─── 8. Clear [NEXT] in CHANGELOG_DRAFT.md ───────────────────────────────────
|
|
if not args.local and not args.skip_changelog:
|
|
archived_header = f"## [{new_version}] — {today}\n"
|
|
archived_entries = "".join(f"- {line}\n" for line in changelog_lines)
|
|
|
|
new_draft = "## [NEXT]\n\n" + archived_header + archived_entries
|
|
if remaining_lines:
|
|
new_draft += "\n" + "".join(remaining_lines)
|
|
|
|
with open(CHANGELOG_DRAFT, "w", encoding="utf-8") as f:
|
|
f.write(new_draft)
|
|
|
|
print(f"[OK] Cleared [NEXT] in {CHANGELOG_DRAFT}, archived as [{new_version}]")
|
|
else:
|
|
print(f"[INFO] Skipped updating {CHANGELOG_DRAFT} (--local or --skip-changelog mode)")
|
|
|
|
print(f"\nDone! Version bumped to v{new_version}.")
|
|
if args.local:
|
|
print("Local mode: Changelog not cleared. Run without --local to finalize release.")
|