Rewrite platform naming around a single descriptor
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:
+43
-48
@@ -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}")
|
||||
|
||||
+4
-4
@@ -9,8 +9,8 @@ Reads from [project.urls] Repository in pyproject.toml.
|
||||
Token: GITEA_TOKEN environment variable
|
||||
|
||||
Steps:
|
||||
1. Find clean-versioned ZIPs in build/ and matching dist/ wheels/sdists
|
||||
2. Abort if any dist files are missing for a found ZIP version
|
||||
1. Find clean-versioned platform artifacts in build/ and matching dist/ wheels/sdists
|
||||
2. Abort if any dist files are missing for a found artifact version
|
||||
3. Create a Gitea release for each version (or reuse the existing one
|
||||
for the tag, skipping already-uploaded assets) and upload all assets
|
||||
4. Remind the user to run: uv publish
|
||||
@@ -76,7 +76,7 @@ _CLEAN_ARTIFACT_RE = re.compile(
|
||||
|
||||
|
||||
def find_releasable_artifacts() -> list[tuple[Path, str, str]]:
|
||||
"""Return (path, version, platform_tag) for clean-versioned ZIPs/DMGs/EXEs in build/."""
|
||||
"""Return (path, version, platform_tag) for clean-versioned artifacts in build/."""
|
||||
build_dir = REPO_ROOT / "build"
|
||||
results = []
|
||||
for p in sorted(build_dir.glob("MediaHive-*")):
|
||||
@@ -246,7 +246,7 @@ def main() -> None:
|
||||
artifacts = find_releasable_artifacts()
|
||||
if not artifacts:
|
||||
print(
|
||||
"No clean-versioned ZIPs/DMGs/EXEs found in build/.\n"
|
||||
"No clean-versioned platform artifacts found in build/.\n"
|
||||
"Run scripts/guibuild.py first.",
|
||||
file=sys.stderr,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user