diff --git a/scripts/release.py b/scripts/release.py
index 4e730a2..0820bf7 100644
--- a/scripts/release.py
+++ b/scripts/release.py
@@ -1,6 +1,6 @@
"""Create a GitHub release with tagged JSON artifacts.
-Expects `make build` to have already been run. This script only handles
+Expects `just build` to have already been run. This script only handles
the publish side: tagging, pushing, and creating the GitHub release.
Workflow:
@@ -12,8 +12,8 @@ Workflow:
6. Create git tag, push, and create GitHub release
Usage:
- make build # build artifacts first
- make publish # then publish
+ just build # build artifacts first
+ just release # then publish
Requires: gh (GitHub CLI), git, python3
"""
@@ -41,6 +41,8 @@ STANDARD_JSON = REPO_ROOT / "obtainium-emulation-pack-latest.json"
DUAL_SCREEN_JSON = REPO_ROOT / "obtainium-emulation-pack-dual-screen-latest.json"
APPLICATIONS_JSON = REPO_ROOT / "src" / "applications.json"
+RELEASES_URL = "https://github.com/RJNY/Obtainium-Emulation-Pack/releases/tag"
+
SEMVER_PATTERN = re.compile(r"^v?(\d+)\.(\d+)\.(\d+)$")
@@ -204,13 +206,27 @@ def diff_apps(
# Table rendering for release notes
+def _make_ref_key(app: dict[str, Any]) -> str:
+ return get_display_name(app).lower().replace(" ", "-").replace("!", "").replace("(", "").replace(")", "")
+
+
def make_app_table_row(app: dict[str, Any], change: str) -> str:
- display_name = f'{get_display_name(app)}'
- obtainium_link = make_obtainium_link(app)
- badge = f'Add to Obtainium!' if change != "Removed" else "-"
+ name = get_display_name(app)
+ ref_key = _make_ref_key(app)
+ app_link = f"[{name}]({get_application_url(app)})"
+ if change == "Removed":
+ install = "-"
+ else:
+ install = f"[Add to Obtainium!][{ref_key}]"
std = "✅" if should_include_app(app, "standard") else "❌"
ds = "✅" if should_include_app(app, "dual-screen") else "❌"
- return f"| {display_name} | {badge} | {change} | {std} | {ds} |"
+ return f"| {app_link} | {install} | {change} | {std} | {ds} |"
+
+
+def make_app_reference_link(app: dict[str, Any]) -> str:
+ ref_key = _make_ref_key(app)
+ obtainium_link = make_obtainium_link(app)
+ return f"[{ref_key}]: {obtainium_link}"
CHANGES_TABLE_HEADER = (
@@ -223,6 +239,7 @@ def generate_changes_table(
added: list[dict[str, Any]],
changed: list[dict[str, Any]],
removed: list[dict[str, Any]],
+ version: str,
) -> str:
rows: list[tuple[str, dict[str, Any]]] = []
for app in added:
@@ -240,6 +257,15 @@ def generate_changes_table(
lines = [CHANGES_TABLE_HEADER]
for change, app in rows:
lines.append(make_app_table_row(app, change))
+
+ lines.append("")
+ lines.append("Links appear broken? [click here][release]")
+ lines.append("")
+ lines.append(f"[release]: {RELEASES_URL}/{version}")
+ for change, app in rows:
+ if change != "Removed":
+ lines.append(make_app_reference_link(app))
+
return "\n".join(lines)
@@ -303,6 +329,7 @@ def generate_release_notes(
added: list[dict[str, Any]],
changed: list[dict[str, Any]],
removed: list[dict[str, Any]],
+ version: str,
) -> str:
lines: list[str] = []
@@ -327,7 +354,7 @@ def generate_release_notes(
if added or changed or removed:
lines.append("## App Changes\n")
- lines.append(generate_changes_table(added, changed, removed))
+ lines.append(generate_changes_table(added, changed, removed, version))
lines.append("")
return "\n".join(lines)
@@ -436,6 +463,10 @@ def main() -> None:
"--notes-file", "-f",
help="Path to a file containing release notes. Skips generation and editor.",
)
+ parser.add_argument(
+ "--since", "-s",
+ help="Override base tag for diff (e.g. v7.5.0). Defaults to latest tag.",
+ )
parser.add_argument(
"--dry-run", "--dryrun",
action="store_true",
@@ -449,7 +480,7 @@ def main() -> None:
print("Fetching tags from remote...")
run(["git", "fetch", "--tags"])
- latest = get_latest_tag()
+ latest = args.since or get_latest_tag()
# Determine version
if args.version:
@@ -463,10 +494,11 @@ def main() -> None:
version = prompt_version(latest)
# Check if tag already exists
- result = run(["git", "tag", "-l", version], capture=True)
- if version in result.stdout.strip().splitlines():
- print(f"Error: Tag {version} already exists.")
- sys.exit(1)
+ if not args.dry_run:
+ result = run(["git", "tag", "-l", version], capture=True)
+ if version in result.stdout.strip().splitlines():
+ print(f"Error: Tag {version} already exists.")
+ sys.exit(1)
# Detect changed apps
print("\nDetecting app changes...")
@@ -485,7 +517,7 @@ def main() -> None:
notes = args.notes
else:
# Auto-generate and open in editor
- notes = generate_release_notes(latest, added, changed, removed)
+ notes = generate_release_notes(latest, added, changed, removed, version)
if args.dry_run:
tmp_dir = REPO_ROOT / "tmp"
@@ -523,7 +555,7 @@ def main() -> None:
for f in (STANDARD_JSON, DUAL_SCREEN_JSON):
if not f.exists():
print(f"Error: Expected artifact not found: {f}")
- print("Did you run `make build` first?")
+ print("Did you run `just build` first?")
sys.exit(1)
# Show summary before proceeding
@@ -546,7 +578,7 @@ def main() -> None:
print("Aborted.")
sys.exit(0)
- # Commit any uncommitted changes (e.g. from `make build`)
+ # Commit any uncommitted changes (e.g. from `just build`)
if not check_working_tree_clean():
print()
print("Working tree has changes. Committing...")
@@ -563,7 +595,7 @@ def main() -> None:
print()
print(f"Release {version} created successfully!")
- print(f"https://github.com/RJNY/Obtainium-Emulation-Pack/releases/tag/{version}")
+ print(f"{RELEASES_URL}/{version}")
finally:
cleanup(versioned_copies)