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 urllib.request
|
||||||
import zipfile
|
import zipfile
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
from typing import NamedTuple
|
||||||
|
|
||||||
import setuptools_scm
|
import setuptools_scm
|
||||||
from platformdirs import user_cache_path
|
from platformdirs import user_cache_path
|
||||||
@@ -63,14 +64,32 @@ _VPK_URL = (
|
|||||||
_VPK_STAGING = _build_cache_dir() / f"vpk-{_VPK_VERSION}"
|
_VPK_STAGING = _build_cache_dir() / f"vpk-{_VPK_VERSION}"
|
||||||
|
|
||||||
|
|
||||||
def _platform_zip_suffix() -> str:
|
class _Platform(NamedTuple):
|
||||||
# Only Windows keeps an arch marker (win64); macOS is arm64-only and we
|
"""Per-platform naming/packaging constants.
|
||||||
# build just one Linux flavor, so -macos / -linux suffice.
|
|
||||||
|
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":
|
if sys.platform == "win32":
|
||||||
return "win64"
|
return _Platform("win64", "win-x64", "MediaHive", "mediahive.ico", "MediaHive.exe", ".exe")
|
||||||
if sys.platform == "darwin":
|
if sys.platform == "darwin":
|
||||||
return "macos"
|
return _Platform("macos", "osx-arm64", "MediaHive.app", "mediahive.icns", "MediaHive", ".pkg")
|
||||||
return "linux"
|
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:
|
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
|
the .NET CLR loads pythonnet/pywebview assemblies that it refuses from
|
||||||
a downloaded ZIP.
|
a downloaded ZIP.
|
||||||
"""
|
"""
|
||||||
if sys.platform == "darwin":
|
plat = _platform()
|
||||||
dist_folder = _REPO_ROOT / "build" / "MediaHive.app"
|
dist_folder = _REPO_ROOT / "build" / plat.dist_dir
|
||||||
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"
|
|
||||||
if not dist_folder.exists():
|
if not dist_folder.exists():
|
||||||
raise FileNotFoundError(f"Distribution folder not found: {dist_folder}")
|
raise FileNotFoundError(f"Distribution folder not found: {dist_folder}")
|
||||||
|
|
||||||
@@ -345,15 +348,15 @@ def build_velopack(version: str) -> Path:
|
|||||||
"--packDir",
|
"--packDir",
|
||||||
str(dist_folder),
|
str(dist_folder),
|
||||||
"--mainExe",
|
"--mainExe",
|
||||||
main_exe,
|
plat.main_exe,
|
||||||
"--packAuthors",
|
"--packAuthors",
|
||||||
"MediaHive",
|
"MediaHive",
|
||||||
"--packTitle",
|
"--packTitle",
|
||||||
"MediaHive",
|
"MediaHive",
|
||||||
"--icon",
|
"--icon",
|
||||||
str(icon),
|
str(_ASSETS_DIR / plat.icon),
|
||||||
"--runtime",
|
"--runtime",
|
||||||
rid,
|
plat.rid,
|
||||||
"--outputDir",
|
"--outputDir",
|
||||||
str(releases_dir),
|
str(releases_dir),
|
||||||
]
|
]
|
||||||
@@ -370,18 +373,14 @@ def build_velopack(version: str) -> Path:
|
|||||||
f"stdout:\n{result.stdout}\nstderr:\n{result.stderr}"
|
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:
|
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:
|
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":
|
if sys.platform == "darwin":
|
||||||
force_macos_user_install(setup)
|
force_macos_user_install(setup)
|
||||||
artifact = (
|
artifact = _REPO_ROOT / "build" / setup_artifact_name(version)
|
||||||
_REPO_ROOT
|
|
||||||
/ "build"
|
|
||||||
/ f"MediaHive-{version}-{_platform_zip_suffix()}-setup{artifact_ext}"
|
|
||||||
)
|
|
||||||
artifact.unlink(missing_ok=True)
|
artifact.unlink(missing_ok=True)
|
||||||
setup.rename(artifact)
|
setup.rename(artifact)
|
||||||
rename_feed_packages(releases_dir)
|
rename_feed_packages(releases_dir)
|
||||||
@@ -487,21 +486,18 @@ def build_executable() -> None:
|
|||||||
raise RuntimeError(f"PyInstaller failed with exit code {result.returncode}")
|
raise RuntimeError(f"PyInstaller failed with exit code {result.returncode}")
|
||||||
|
|
||||||
|
|
||||||
def create_zip(version: str) -> Path:
|
def create_portable_zip(version: str) -> Path:
|
||||||
"""Create a version-numbered ZIP file of the build/MediaHive folder."""
|
"""Create the Windows portable ZIP of the build/MediaHive folder.
|
||||||
repo_root = _REPO_ROOT
|
|
||||||
dist_folder = repo_root / "build" / "MediaHive"
|
|
||||||
|
|
||||||
|
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():
|
if not dist_folder.exists():
|
||||||
raise FileNotFoundError(f"Distribution folder not found: {dist_folder}")
|
raise FileNotFoundError(f"Distribution folder not found: {dist_folder}")
|
||||||
|
|
||||||
zip_name = f"MediaHive-{version}-{_platform_zip_suffix()}.zip"
|
zip_path = _REPO_ROOT / "build" / f"MediaHive-{version}-win64-portable.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)
|
|
||||||
|
|
||||||
print(f"Creating {zip_path}...")
|
print(f"Creating {zip_path}...")
|
||||||
shutil.make_archive(
|
shutil.make_archive(
|
||||||
str(zip_path.with_suffix("")), # removes .zip so make_archive can add it
|
str(zip_path.with_suffix("")), # removes .zip so make_archive can add it
|
||||||
@@ -534,8 +530,7 @@ def main() -> None:
|
|||||||
|
|
||||||
artifacts = [build_velopack(version)]
|
artifacts = [build_velopack(version)]
|
||||||
if sys.platform == "win32":
|
if sys.platform == "win32":
|
||||||
# Velopack-less plain-folder distribution (with MOTW strip)
|
artifacts.append(create_portable_zip(version))
|
||||||
artifacts.append(create_zip(version))
|
|
||||||
|
|
||||||
for artifact_path in artifacts:
|
for artifact_path in artifacts:
|
||||||
print(f"✓ Built successfully: {artifact_path}")
|
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
|
Token: GITEA_TOKEN environment variable
|
||||||
|
|
||||||
Steps:
|
Steps:
|
||||||
1. Find clean-versioned ZIPs in build/ and matching dist/ wheels/sdists
|
1. Find clean-versioned platform artifacts in build/ and matching dist/ wheels/sdists
|
||||||
2. Abort if any dist files are missing for a found ZIP version
|
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
|
3. Create a Gitea release for each version (or reuse the existing one
|
||||||
for the tag, skipping already-uploaded assets) and upload all assets
|
for the tag, skipping already-uploaded assets) and upload all assets
|
||||||
4. Remind the user to run: uv publish
|
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]]:
|
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"
|
build_dir = REPO_ROOT / "build"
|
||||||
results = []
|
results = []
|
||||||
for p in sorted(build_dir.glob("MediaHive-*")):
|
for p in sorted(build_dir.glob("MediaHive-*")):
|
||||||
@@ -246,7 +246,7 @@ def main() -> None:
|
|||||||
artifacts = find_releasable_artifacts()
|
artifacts = find_releasable_artifacts()
|
||||||
if not artifacts:
|
if not artifacts:
|
||||||
print(
|
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.",
|
"Run scripts/guibuild.py first.",
|
||||||
file=sys.stderr,
|
file=sys.stderr,
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user