ci: provision Python via nuget (idempotent, no registry side effects)
The per-user MSI installer is stateful across runs on a persistent VM: once a version is registered, a later /quiet install no-ops and never lands at the new TargetDir, so python.exe went missing. Switch to a standalone CPython from nuget cached under LOCALAPPDATA — no registry/PATH changes, idempotent, reused across runs. A pre-existing Python 3.11 on PATH is still honoured. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -45,16 +45,17 @@ jobs:
|
||||
run: |
|
||||
$ErrorActionPreference = 'Stop'
|
||||
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
|
||||
$python = $null
|
||||
|
||||
# 1) Existing "py -3.11" launcher
|
||||
try {
|
||||
$exe = & py -3.11 -c "import sys; print(sys.executable)" 2>$null
|
||||
if ($LASTEXITCODE -eq 0 -and $exe) { $python = $exe.Trim() }
|
||||
} catch {}
|
||||
# Persistent, side-effect-free Python for this builder. We use a
|
||||
# standalone CPython from nuget (no registry/PATH changes, idempotent)
|
||||
# cached under LOCALAPPDATA so subsequent runs reuse it. A pre-existing
|
||||
# Python 3.11 on PATH is honoured if present.
|
||||
$pyVersion = "3.11.9"
|
||||
$root = Join-Path $env:LOCALAPPDATA "MacroPadBuild"
|
||||
$python = Join-Path $root "python.$pyVersion\tools\python.exe"
|
||||
|
||||
# 2) A python on PATH that is 3.11.x
|
||||
if (-not $python) {
|
||||
if (-not (Test-Path $python)) {
|
||||
# Honour an existing 3.11 on PATH (e.g. if the VM is pre-provisioned).
|
||||
try {
|
||||
$v = & python --version 2>&1
|
||||
if ($LASTEXITCODE -eq 0 -and "$v" -match '3\.11') {
|
||||
@@ -63,21 +64,20 @@ jobs:
|
||||
} catch {}
|
||||
}
|
||||
|
||||
# 3) Install per-user, silent (no elevation, cannot prompt)
|
||||
if (-not $python) {
|
||||
Write-Host "Python 3.11 not found - installing per-user..."
|
||||
$tmp = if ($env:RUNNER_TEMP) { $env:RUNNER_TEMP } else { $env:TEMP }
|
||||
$installer = Join-Path $tmp "python-3.11.9-amd64.exe"
|
||||
Invoke-WebRequest -UseBasicParsing -Uri "https://www.python.org/ftp/python/3.11.9/python-3.11.9-amd64.exe" -OutFile $installer
|
||||
$dir = Join-Path $tmp "Python311"
|
||||
$proc = Start-Process -FilePath $installer -Wait -PassThru -NoNewWindow -ArgumentList @(
|
||||
"/quiet","InstallAllUsers=0","PrependPath=0","Include_launcher=0","Include_test=0","TargetDir=$dir"
|
||||
)
|
||||
if ($proc.ExitCode -ne 0) { throw "Python installer exited with $($proc.ExitCode)" }
|
||||
$python = Join-Path $dir "python.exe"
|
||||
if (-not (Test-Path $python)) {
|
||||
Write-Host "Provisioning standalone Python $pyVersion via nuget..."
|
||||
New-Item -ItemType Directory -Force -Path $root | Out-Null
|
||||
$nuget = Join-Path $root "nuget.exe"
|
||||
if (-not (Test-Path $nuget)) {
|
||||
Invoke-WebRequest -UseBasicParsing -Uri "https://dist.nuget.org/win-x86-commandline/latest/nuget.exe" -OutFile $nuget
|
||||
}
|
||||
& $nuget install python -Version $pyVersion -OutputDirectory $root -Source "https://api.nuget.org/v3/index.json" -NonInteractive
|
||||
if ($LASTEXITCODE -ne 0) { throw "nuget install python exited with $LASTEXITCODE" }
|
||||
$python = Join-Path $root "python.$pyVersion\tools\python.exe"
|
||||
}
|
||||
|
||||
if (-not (Test-Path $python)) { throw "Python not found at '$python'" }
|
||||
& $python -m ensurepip --upgrade 2>$null | Out-Null
|
||||
& $python --version
|
||||
# Write to GITHUB_ENV without a BOM (ascii) so the value parses cleanly.
|
||||
Add-Content -Path $env:GITHUB_ENV -Value "PYTHON=$python" -Encoding ascii
|
||||
|
||||
Reference in New Issue
Block a user