Fix doubled platformdirs paths; pick newest dotnet runtime
appauthor=False/opinion=False avoids mediahive\mediahive\Cache style paths on Windows. fetch_dotnet now probes all known dotnet locations and selects the highest Microsoft.NETCore.App major, requiring the version vpk's TFM targets (10) — PATH on the Windows CI runner resolves to a runtime-only .NET 8 while scoop holds the SDK 10.
This commit is contained in:
+31
-19
@@ -47,7 +47,7 @@ _ASSETS_DIR = _REPO_ROOT / "mediahive" / "assets"
|
||||
|
||||
def _build_cache_dir() -> Path:
|
||||
"""Return the persistent cross-build cache dir for downloaded tools (CI wipes build/)."""
|
||||
return user_cache_path("mediahive-build")
|
||||
return user_cache_path("mediahive-build", appauthor=False, opinion=False)
|
||||
|
||||
|
||||
_FFMPEG_STAGING = _build_cache_dir() / "ffmpeg"
|
||||
@@ -202,12 +202,16 @@ def ensure_macos_icon() -> Path:
|
||||
return icon_icns
|
||||
|
||||
|
||||
_VPK_TFM = "net10.0"
|
||||
_VPK_REQUIRED_DOTNET_MAJOR = int(re.fullmatch(r"net(\d+)\.0", _VPK_TFM).group(1))
|
||||
|
||||
|
||||
def fetch_vpk() -> Path:
|
||||
"""Download the Velopack CLI package into the persistent build cache.
|
||||
|
||||
Returns the path to vpk.dll, runnable with `dotnet vpk.dll ...`.
|
||||
"""
|
||||
vpk_dll = _VPK_STAGING / "tools" / "net10.0" / "any" / "vpk.dll"
|
||||
vpk_dll = _VPK_STAGING / "tools" / _VPK_TFM / "any" / "vpk.dll"
|
||||
if vpk_dll.exists():
|
||||
print(f"vpk already staged at {_VPK_STAGING}, skipping download.")
|
||||
return vpk_dll
|
||||
@@ -226,35 +230,35 @@ def fetch_vpk() -> Path:
|
||||
return vpk_dll
|
||||
|
||||
|
||||
def _dotnet_has_runtime(exe: Path) -> bool:
|
||||
"""Check that `exe` runs and has Microsoft.NETCore.App >= 8."""
|
||||
def _dotnet_runtime_major(exe: Path) -> int | None:
|
||||
"""Return the highest installed Microsoft.NETCore.App major version, or None."""
|
||||
try:
|
||||
result = subprocess.run(
|
||||
[str(exe), "--list-runtimes"], capture_output=True, text=True, timeout=30
|
||||
)
|
||||
except (OSError, subprocess.TimeoutExpired):
|
||||
return False
|
||||
return None
|
||||
if result.returncode != 0:
|
||||
return False
|
||||
return None
|
||||
majors = []
|
||||
for line in result.stdout.splitlines():
|
||||
parts = line.split()
|
||||
if len(parts) >= 2 and parts[0] == "Microsoft.NETCore.App":
|
||||
try:
|
||||
if int(parts[1].split(".")[0]) >= 8:
|
||||
return True
|
||||
majors.append(int(parts[1].split(".")[0]))
|
||||
except ValueError:
|
||||
continue
|
||||
return False
|
||||
return max(majors, default=None)
|
||||
|
||||
|
||||
def fetch_dotnet() -> str:
|
||||
"""Resolve a dotnet host with a modern (>= 8) runtime from the system.
|
||||
"""Resolve a system dotnet host able to run vpk (needs .NET >= 10).
|
||||
|
||||
The .NET SDK is a build prerequisite installed on the build machine —
|
||||
downloading a runtime per build is slow and flaky. A plain `dotnet` may
|
||||
resolve to a runtime-only installation, and long-running services (CI
|
||||
runners) may carry a stale environment without DOTNET_ROOT or scoop
|
||||
paths — so probe known locations explicitly.
|
||||
downloading a runtime per build is slow and flaky. Several dotnet
|
||||
installations may coexist (PATH may resolve to a runtime-only .NET 8
|
||||
while scoop holds the SDK 10), so probe known locations and pick the
|
||||
newest runtime rather than the first that runs.
|
||||
"""
|
||||
exe_name = "dotnet.exe" if sys.platform == "win32" else "dotnet"
|
||||
candidates: list[Path] = []
|
||||
@@ -281,14 +285,22 @@ def fetch_dotnet() -> str:
|
||||
Path.home() / ".dotnet" / exe_name,
|
||||
]
|
||||
|
||||
best: tuple[int, Path] | None = None
|
||||
for exe in candidates:
|
||||
if exe.exists() and _dotnet_has_runtime(exe):
|
||||
print(f"Using dotnet at {exe}")
|
||||
return str(exe)
|
||||
if not exe.exists():
|
||||
continue
|
||||
major = _dotnet_runtime_major(exe)
|
||||
if major is not None and (best is None or major > best[0]):
|
||||
best = (major, exe)
|
||||
|
||||
if best is not None and best[0] >= _VPK_REQUIRED_DOTNET_MAJOR:
|
||||
print(f"Using dotnet at {best[1]} (.NET {best[0]})")
|
||||
return str(best[1])
|
||||
|
||||
found = f"newest found is .NET {best[0]} at {best[1]}" if best else "none found"
|
||||
raise RuntimeError(
|
||||
"No dotnet with Microsoft.NETCore.App >= 8 found. "
|
||||
"Install the .NET SDK on this build machine "
|
||||
f"vpk requires Microsoft.NETCore.App >= {_VPK_REQUIRED_DOTNET_MAJOR} ({found}). "
|
||||
"Install the current .NET SDK on this build machine "
|
||||
"(Windows: `scoop install dotnet-sdk`; macOS: `brew install dotnet-sdk`; "
|
||||
"Linux: distro `dotnet-sdk` package or the dotnet-install script)."
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user