mirror of
https://github.com/actions/setup-python.git
synced 2026-03-20 08:00:19 +08:00
fix: address review feedback on system Python fallback
- Gate fallback on architecture having no manifest entries, preventing false triggers on supported architectures with missing versions - Skip fallback for free-threaded Python builds - Return early with correct outputs (sys.executable, version, bin dir) instead of relying on toolcache path parsing which breaks with system prefix paths like /usr - Set environment variables (pythonLocation, Python_ROOT_DIR, etc.) correctly for system Python paths Signed-off-by: Bruno Verachten <gounthar@gmail.com>
This commit is contained in:
parent
156786c425
commit
02cd31ab13
2 changed files with 80 additions and 39 deletions
51
dist/setup/index.js
vendored
51
dist/setup/index.js
vendored
|
|
@ -82997,28 +82997,43 @@ async function useCpythonVersion(version, architecture, updateEnvironment, check
|
||||||
installDir = tc.find('Python', semanticVersionSpec, architecture);
|
installDir = tc.find('Python', semanticVersionSpec, architecture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!installDir) {
|
if (!installDir && !freethreaded) {
|
||||||
// Try system Python as fallback (e.g., on architectures without pre-built binaries)
|
// Try system Python as fallback, but only for architectures that have
|
||||||
try {
|
// no pre-built binaries in the manifest at all. This prevents the
|
||||||
const { exitCode, stdout } = await exec.getExecOutput('python3', [
|
// fallback from firing when a specific version is missing on a
|
||||||
'-c',
|
// supported architecture (e.g., requesting Python 3.99 on x86_64).
|
||||||
'import sys; print(sys.prefix)'
|
const baseArchitecture = architecture.replace('-freethreaded', '');
|
||||||
]);
|
if (!manifest) {
|
||||||
if (exitCode === 0) {
|
manifest = await installer.getManifest();
|
||||||
const systemPrefix = stdout.trim();
|
}
|
||||||
const systemVersion = await exec.getExecOutput('python3', [
|
const archHasManifestEntries = manifest?.some(release => release.files?.some((file) => file.arch === baseArchitecture));
|
||||||
|
if (!archHasManifestEntries) {
|
||||||
|
try {
|
||||||
|
const sysInfo = await exec.getExecOutput('python3', [
|
||||||
'-c',
|
'-c',
|
||||||
'import sys; print(f"{sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}")'
|
'import sys, os; print(sys.executable + "\\n" + f"{sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}" + "\\n" + sys.prefix + "\\n" + os.path.dirname(sys.executable))'
|
||||||
]);
|
]);
|
||||||
if (systemVersion.exitCode === 0 &&
|
if (sysInfo.exitCode === 0) {
|
||||||
semver.satisfies(systemVersion.stdout.trim(), semanticVersionSpec)) {
|
const [sysExecutable, sysVersion, sysPrefix, sysBinDir] = sysInfo.stdout.trim().split('\n');
|
||||||
installDir = systemPrefix;
|
if (semver.satisfies(sysVersion, semanticVersionSpec)) {
|
||||||
core.warning(`Pre-built Python not available for architecture '${architecture}'. Using system Python ${systemVersion.stdout.trim()} at ${systemPrefix}.`);
|
core.warning(`Pre-built Python not available for architecture '${baseArchitecture}'. Using system Python ${sysVersion} at ${sysExecutable}.`);
|
||||||
|
if (updateEnvironment) {
|
||||||
|
core.exportVariable('pythonLocation', sysPrefix);
|
||||||
|
core.exportVariable('PKG_CONFIG_PATH', sysPrefix + '/lib/pkgconfig');
|
||||||
|
core.exportVariable('Python_ROOT_DIR', sysPrefix);
|
||||||
|
core.exportVariable('Python2_ROOT_DIR', sysPrefix);
|
||||||
|
core.exportVariable('Python3_ROOT_DIR', sysPrefix);
|
||||||
|
core.addPath(sysBinDir);
|
||||||
|
}
|
||||||
|
core.setOutput('python-version', sysVersion);
|
||||||
|
core.setOutput('python-path', sysExecutable);
|
||||||
|
return { impl: 'CPython', version: sysVersion };
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
catch {
|
||||||
catch {
|
// System Python not available, fall through to error
|
||||||
// System Python not available, fall through to error
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!installDir) {
|
if (!installDir) {
|
||||||
|
|
|
||||||
|
|
@ -122,31 +122,57 @@ export async function useCpythonVersion(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!installDir) {
|
if (!installDir && !freethreaded) {
|
||||||
// Try system Python as fallback (e.g., on architectures without pre-built binaries)
|
// Try system Python as fallback, but only for architectures that have
|
||||||
try {
|
// no pre-built binaries in the manifest at all. This prevents the
|
||||||
const {exitCode, stdout} = await exec.getExecOutput('python3', [
|
// fallback from firing when a specific version is missing on a
|
||||||
'-c',
|
// supported architecture (e.g., requesting Python 3.99 on x86_64).
|
||||||
'import sys; print(sys.prefix)'
|
const baseArchitecture = architecture.replace('-freethreaded', '');
|
||||||
]);
|
if (!manifest) {
|
||||||
if (exitCode === 0) {
|
manifest = await installer.getManifest();
|
||||||
const systemPrefix = stdout.trim();
|
}
|
||||||
const systemVersion = await exec.getExecOutput('python3', [
|
const archHasManifestEntries = manifest?.some(
|
||||||
|
release =>
|
||||||
|
release.files?.some(
|
||||||
|
(file: {arch: string}) => file.arch === baseArchitecture
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!archHasManifestEntries) {
|
||||||
|
try {
|
||||||
|
const sysInfo = await exec.getExecOutput('python3', [
|
||||||
'-c',
|
'-c',
|
||||||
'import sys; print(f"{sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}")'
|
'import sys, os; print(sys.executable + "\\n" + f"{sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}" + "\\n" + sys.prefix + "\\n" + os.path.dirname(sys.executable))'
|
||||||
]);
|
]);
|
||||||
if (
|
if (sysInfo.exitCode === 0) {
|
||||||
systemVersion.exitCode === 0 &&
|
const [sysExecutable, sysVersion, sysPrefix, sysBinDir] =
|
||||||
semver.satisfies(systemVersion.stdout.trim(), semanticVersionSpec)
|
sysInfo.stdout.trim().split('\n');
|
||||||
) {
|
if (semver.satisfies(sysVersion, semanticVersionSpec)) {
|
||||||
installDir = systemPrefix;
|
core.warning(
|
||||||
core.warning(
|
`Pre-built Python not available for architecture '${baseArchitecture}'. Using system Python ${sysVersion} at ${sysExecutable}.`
|
||||||
`Pre-built Python not available for architecture '${architecture}'. Using system Python ${systemVersion.stdout.trim()} at ${systemPrefix}.`
|
);
|
||||||
);
|
|
||||||
|
if (updateEnvironment) {
|
||||||
|
core.exportVariable('pythonLocation', sysPrefix);
|
||||||
|
core.exportVariable(
|
||||||
|
'PKG_CONFIG_PATH',
|
||||||
|
sysPrefix + '/lib/pkgconfig'
|
||||||
|
);
|
||||||
|
core.exportVariable('Python_ROOT_DIR', sysPrefix);
|
||||||
|
core.exportVariable('Python2_ROOT_DIR', sysPrefix);
|
||||||
|
core.exportVariable('Python3_ROOT_DIR', sysPrefix);
|
||||||
|
core.addPath(sysBinDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
core.setOutput('python-version', sysVersion);
|
||||||
|
core.setOutput('python-path', sysExecutable);
|
||||||
|
|
||||||
|
return {impl: 'CPython', version: sysVersion};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
} catch {
|
||||||
|
// System Python not available, fall through to error
|
||||||
}
|
}
|
||||||
} catch {
|
|
||||||
// System Python not available, fall through to error
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue