Rewrite platform naming around a single descriptor
release / gui-build (linux, bash) (push) Successful in 56s
release / gui-build (windows, cmd) (push) Successful in 1m19s
release / gui-build (macos, bash) (push) Successful in 2m57s

Replace _platform_zip_suffix() and its overrides with a _Platform
NamedTuple (tag/rid/dist_dir/icon/main_exe/setup_ext) plus
setup_artifact_name(). create_zip() is Windows-only in practice, so it
is now create_portable_zip() with a fixed -win64-portable.zip name
instead of a generic name patched by string replace.
This commit is contained in:
2026-09-23 02:22:18 +00:00
parent 5f3ba47098
commit ff493506ba
2 changed files with 47 additions and 52 deletions
+43 -48
View File
@@ -29,6 +29,7 @@ import sys
import urllib.request
import zipfile
from pathlib import Path
from typing import NamedTuple
import setuptools_scm
from platformdirs import user_cache_path
@@ -63,14 +64,32 @@ _VPK_URL = (
_VPK_STAGING = _build_cache_dir() / f"vpk-{_VPK_VERSION}"
def _platform_zip_suffix() -> str:
# Only Windows keeps an arch marker (win64); macOS is arm64-only and we
# build just one Linux flavor, so -macos / -linux suffice.
class _Platform(NamedTuple):
"""Per-platform naming/packaging constants.
tag is the release artifact suffix. Only Windows keeps an arch marker
(win64); macOS builds are arm64-only and we ship one Linux flavor.
"""
tag: str # win64 / macos / linux
rid: str # Velopack runtime id
dist_dir: str # PyInstaller output dir under build/
icon: str # file in mediahive/assets
main_exe: str
setup_ext: str
def _platform() -> _Platform:
if sys.platform == "win32":
return "win64"
return _Platform("win64", "win-x64", "MediaHive", "mediahive.ico", "MediaHive.exe", ".exe")
if sys.platform == "darwin":
return "macos"
return "linux"
return _Platform("macos", "osx-arm64", "MediaHive.app", "mediahive.icns", "MediaHive", ".pkg")
return _Platform("linux", "linux-x64", "MediaHive", "mediahive.png", "MediaHive", ".AppImage")
def setup_artifact_name(version: str) -> str:
p = _platform()
return f"MediaHive-{version}-{p.tag}-setup{p.setup_ext}"
def fetch_ffmpeg() -> Path:
@@ -310,24 +329,8 @@ def build_velopack(version: str) -> Path:
the .NET CLR loads pythonnet/pywebview assemblies that it refuses from
a downloaded ZIP.
"""
if sys.platform == "darwin":
dist_folder = _REPO_ROOT / "build" / "MediaHive.app"
icon = _ASSETS_DIR / "mediahive.icns"
rid = "osx-arm64"
main_exe = "MediaHive"
artifact_ext = ".pkg"
elif sys.platform == "win32":
dist_folder = _REPO_ROOT / "build" / "MediaHive"
icon = _ASSETS_DIR / "mediahive.ico"
rid = "win-x64"
main_exe = "MediaHive.exe"
artifact_ext = ".exe"
else:
dist_folder = _REPO_ROOT / "build" / "MediaHive"
icon = _ASSETS_DIR / "mediahive.png"
rid = "linux-x64"
main_exe = "MediaHive"
artifact_ext = ".AppImage"
plat = _platform()
dist_folder = _REPO_ROOT / "build" / plat.dist_dir
if not dist_folder.exists():
raise FileNotFoundError(f"Distribution folder not found: {dist_folder}")
@@ -345,15 +348,15 @@ def build_velopack(version: str) -> Path:
"--packDir",
str(dist_folder),
"--mainExe",
main_exe,
plat.main_exe,
"--packAuthors",
"MediaHive",
"--packTitle",
"MediaHive",
"--icon",
str(icon),
str(_ASSETS_DIR / plat.icon),
"--runtime",
rid,
plat.rid,
"--outputDir",
str(releases_dir),
]
@@ -370,18 +373,14 @@ def build_velopack(version: str) -> Path:
f"stdout:\n{result.stdout}\nstderr:\n{result.stderr}"
)
setup = next(iter(sorted(releases_dir.glob(f"*Setup*{artifact_ext}"))), None)
setup = next(iter(sorted(releases_dir.glob(f"*Setup*{plat.setup_ext}"))), None)
if setup is None:
setup = next(iter(sorted(releases_dir.glob(f"*{artifact_ext}"))), None)
setup = next(iter(sorted(releases_dir.glob(f"*{plat.setup_ext}"))), None)
if setup is None:
raise RuntimeError(f"vpk produced no *{artifact_ext} in {releases_dir}")
raise RuntimeError(f"vpk produced no *{plat.setup_ext} in {releases_dir}")
if sys.platform == "darwin":
force_macos_user_install(setup)
artifact = (
_REPO_ROOT
/ "build"
/ f"MediaHive-{version}-{_platform_zip_suffix()}-setup{artifact_ext}"
)
artifact = _REPO_ROOT / "build" / setup_artifact_name(version)
artifact.unlink(missing_ok=True)
setup.rename(artifact)
rename_feed_packages(releases_dir)
@@ -487,21 +486,18 @@ def build_executable() -> None:
raise RuntimeError(f"PyInstaller failed with exit code {result.returncode}")
def create_zip(version: str) -> Path:
"""Create a version-numbered ZIP file of the build/MediaHive folder."""
repo_root = _REPO_ROOT
dist_folder = repo_root / "build" / "MediaHive"
def create_portable_zip(version: str) -> Path:
"""Create the Windows portable ZIP of the build/MediaHive folder.
Velopack-less plain-folder distribution for users who cannot or do not
want to run Setup.exe. No auto-updates; the app strips Mark-of-the-Web
from bundled DLLs at first run instead.
"""
dist_folder = _REPO_ROOT / "build" / "MediaHive"
if not dist_folder.exists():
raise FileNotFoundError(f"Distribution folder not found: {dist_folder}")
zip_name = f"MediaHive-{version}-{_platform_zip_suffix()}.zip"
if sys.platform == "win32":
# Distinguish from the Velopack installer (MediaHive-*-win64-setup.exe)
zip_name = zip_name.replace("-win64.zip", "-win64-portable.zip")
zip_path = repo_root / "build" / zip_name
zip_path.parent.mkdir(parents=True, exist_ok=True)
zip_path = _REPO_ROOT / "build" / f"MediaHive-{version}-win64-portable.zip"
print(f"Creating {zip_path}...")
shutil.make_archive(
str(zip_path.with_suffix("")), # removes .zip so make_archive can add it
@@ -534,8 +530,7 @@ def main() -> None:
artifacts = [build_velopack(version)]
if sys.platform == "win32":
# Velopack-less plain-folder distribution (with MOTW strip)
artifacts.append(create_zip(version))
artifacts.append(create_portable_zip(version))
for artifact_path in artifacts:
print(f"✓ Built successfully: {artifact_path}")