From 156786c425f4b4169717def2a3b322fd7e1ab675 Mon Sep 17 00:00:00 2001 From: Bruno Verachten Date: Wed, 18 Mar 2026 15:48:13 +0100 Subject: [PATCH] feat: fall back to system Python when pre-built binaries unavailable When pre-built Python binaries are not available for the current architecture (e.g., riscv64), try using system Python as a fallback instead of failing with an error. This enables setup-python to work on architectures that don't yet have pre-built binaries in actions/python-versions, such as riscv64 self-hosted runners. The fallback only activates when: 1. No cached version is found 2. No manifest entry exists for the architecture 3. System python3 exists and satisfies the requested version spec A warning is emitted so users know the fallback was used. Fixes #1288 Signed-off-by: Bruno Verachten --- dist/setup/index.js | 24 ++++++++++++++++++++++++ src/find-python.ts | 28 ++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/dist/setup/index.js b/dist/setup/index.js index 41363d8b..b53c01a8 100644 --- a/dist/setup/index.js +++ b/dist/setup/index.js @@ -82997,6 +82997,30 @@ async function useCpythonVersion(version, architecture, updateEnvironment, check installDir = tc.find('Python', semanticVersionSpec, architecture); } } + if (!installDir) { + // Try system Python as fallback (e.g., on architectures without pre-built binaries) + try { + const { exitCode, stdout } = await exec.getExecOutput('python3', [ + '-c', + 'import sys; print(sys.prefix)' + ]); + if (exitCode === 0) { + const systemPrefix = stdout.trim(); + const systemVersion = await exec.getExecOutput('python3', [ + '-c', + 'import sys; print(f"{sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}")' + ]); + if (systemVersion.exitCode === 0 && + semver.satisfies(systemVersion.stdout.trim(), semanticVersionSpec)) { + installDir = systemPrefix; + core.warning(`Pre-built Python not available for architecture '${architecture}'. Using system Python ${systemVersion.stdout.trim()} at ${systemPrefix}.`); + } + } + } + catch { + // System Python not available, fall through to error + } + } if (!installDir) { const osInfo = await (0, utils_1.getOSInfo)(); const msg = [ diff --git a/src/find-python.ts b/src/find-python.ts index 99c6a7f2..9e8de0da 100644 --- a/src/find-python.ts +++ b/src/find-python.ts @@ -122,6 +122,34 @@ export async function useCpythonVersion( } } + if (!installDir) { + // Try system Python as fallback (e.g., on architectures without pre-built binaries) + try { + const {exitCode, stdout} = await exec.getExecOutput('python3', [ + '-c', + 'import sys; print(sys.prefix)' + ]); + if (exitCode === 0) { + const systemPrefix = stdout.trim(); + const systemVersion = await exec.getExecOutput('python3', [ + '-c', + 'import sys; print(f"{sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}")' + ]); + if ( + systemVersion.exitCode === 0 && + semver.satisfies(systemVersion.stdout.trim(), semanticVersionSpec) + ) { + installDir = systemPrefix; + core.warning( + `Pre-built Python not available for architecture '${architecture}'. Using system Python ${systemVersion.stdout.trim()} at ${systemPrefix}.` + ); + } + } + } catch { + // System Python not available, fall through to error + } + } + if (!installDir) { const osInfo = await getOSInfo(); const msg = [