mirror of
https://code.forgejo.org/actions/setup-python
synced 2025-06-10 13:22:20 +02:00
feature: fallback to pre-release when no stable version is found (#414)
This allows to specify version like `3.11` or `pypy3.10` in workflows before those versions are released. This lessen the burden for users of `setup-python` by not having to modify their workflow twice: once when a pre-release is available (e.g. `3.11-dev`) and once when the first stable release is published (e.g. `3.11`)
This commit is contained in:
parent
a6eba85bba
commit
2652534ead
14 changed files with 524 additions and 61 deletions
|
@ -23,7 +23,8 @@ export async function findPyPyVersion(
|
|||
versionSpec: string,
|
||||
architecture: string,
|
||||
updateEnvironment: boolean,
|
||||
checkLatest: boolean
|
||||
checkLatest: boolean,
|
||||
allowPreReleases: boolean
|
||||
): Promise<{resolvedPyPyVersion: string; resolvedPythonVersion: string}> {
|
||||
let resolvedPyPyVersion = '';
|
||||
let resolvedPythonVersion = '';
|
||||
|
@ -39,7 +40,8 @@ export async function findPyPyVersion(
|
|||
releases,
|
||||
pypyVersionSpec.pythonVersion,
|
||||
pypyVersionSpec.pypyVersion,
|
||||
architecture
|
||||
architecture,
|
||||
false
|
||||
);
|
||||
|
||||
if (releaseData) {
|
||||
|
@ -71,6 +73,7 @@ export async function findPyPyVersion(
|
|||
pypyVersionSpec.pypyVersion,
|
||||
pypyVersionSpec.pythonVersion,
|
||||
architecture,
|
||||
allowPreReleases,
|
||||
releases
|
||||
));
|
||||
}
|
||||
|
|
|
@ -34,11 +34,15 @@ export async function useCpythonVersion(
|
|||
version: string,
|
||||
architecture: string,
|
||||
updateEnvironment: boolean,
|
||||
checkLatest: boolean
|
||||
checkLatest: boolean,
|
||||
allowPreReleases: boolean
|
||||
): Promise<InstalledVersion> {
|
||||
let manifest: tc.IToolRelease[] | null = null;
|
||||
const desugaredVersionSpec = desugarDevVersion(version);
|
||||
let semanticVersionSpec = pythonVersionToSemantic(desugaredVersionSpec);
|
||||
let semanticVersionSpec = pythonVersionToSemantic(
|
||||
desugaredVersionSpec,
|
||||
allowPreReleases
|
||||
);
|
||||
core.debug(`Semantic version spec of ${version} is ${semanticVersionSpec}`);
|
||||
|
||||
if (checkLatest) {
|
||||
|
@ -178,8 +182,18 @@ interface InstalledVersion {
|
|||
* Python's prelease versions look like `3.7.0b2`.
|
||||
* This is the one part of Python versioning that does not look like semantic versioning, which specifies `3.7.0-b2`.
|
||||
* If the version spec contains prerelease versions, we need to convert them to the semantic version equivalent.
|
||||
*
|
||||
* For easier use of the action, we also map 'x.y' to allow pre-release before 'x.y.0' release if allowPreReleases is true
|
||||
*/
|
||||
export function pythonVersionToSemantic(versionSpec: string) {
|
||||
export function pythonVersionToSemantic(
|
||||
versionSpec: string,
|
||||
allowPreReleases: boolean
|
||||
) {
|
||||
const prereleaseVersion = /(\d+\.\d+\.\d+)((?:a|b|rc)\d*)/g;
|
||||
return versionSpec.replace(prereleaseVersion, '$1-$2');
|
||||
const majorMinor = /^(\d+)\.(\d+)$/;
|
||||
let result = versionSpec.replace(prereleaseVersion, '$1-$2');
|
||||
if (allowPreReleases) {
|
||||
result = result.replace(majorMinor, '~$1.$2.0-0');
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import * as os from 'os';
|
||||
import * as path from 'path';
|
||||
import * as core from '@actions/core';
|
||||
import * as tc from '@actions/tool-cache';
|
||||
|
@ -19,6 +20,7 @@ export async function installPyPy(
|
|||
pypyVersion: string,
|
||||
pythonVersion: string,
|
||||
architecture: string,
|
||||
allowPreReleases: boolean,
|
||||
releases: IPyPyManifestRelease[] | undefined
|
||||
) {
|
||||
let downloadDir;
|
||||
|
@ -29,13 +31,31 @@ export async function installPyPy(
|
|||
throw new Error('No release was found in PyPy version.json');
|
||||
}
|
||||
|
||||
const releaseData = findRelease(
|
||||
let releaseData = findRelease(
|
||||
releases,
|
||||
pythonVersion,
|
||||
pypyVersion,
|
||||
architecture
|
||||
architecture,
|
||||
false
|
||||
);
|
||||
|
||||
if (allowPreReleases && (!releaseData || !releaseData.foundAsset)) {
|
||||
// check for pre-release
|
||||
core.info(
|
||||
[
|
||||
`Stable PyPy version ${pythonVersion} (${pypyVersion}) with arch ${architecture} not found`,
|
||||
`Trying pre-release versions`
|
||||
].join(os.EOL)
|
||||
);
|
||||
releaseData = findRelease(
|
||||
releases,
|
||||
pythonVersion,
|
||||
pypyVersion,
|
||||
architecture,
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
if (!releaseData || !releaseData.foundAsset) {
|
||||
throw new Error(
|
||||
`PyPy version ${pythonVersion} (${pypyVersion}) with arch ${architecture} not found`
|
||||
|
@ -162,8 +182,10 @@ export function findRelease(
|
|||
releases: IPyPyManifestRelease[],
|
||||
pythonVersion: string,
|
||||
pypyVersion: string,
|
||||
architecture: string
|
||||
architecture: string,
|
||||
includePrerelease: boolean
|
||||
) {
|
||||
const options = {includePrerelease: includePrerelease};
|
||||
const filterReleases = releases.filter(item => {
|
||||
const isPythonVersionSatisfied = semver.satisfies(
|
||||
semver.coerce(item.python_version)!,
|
||||
|
@ -173,7 +195,11 @@ export function findRelease(
|
|||
isNightlyKeyword(pypyVersion) && isNightlyKeyword(item.pypy_version);
|
||||
const isPyPyVersionSatisfied =
|
||||
isPyPyNightly ||
|
||||
semver.satisfies(pypyVersionToSemantic(item.pypy_version), pypyVersion);
|
||||
semver.satisfies(
|
||||
pypyVersionToSemantic(item.pypy_version),
|
||||
pypyVersion,
|
||||
options
|
||||
);
|
||||
const isArchPresent =
|
||||
item.files &&
|
||||
(IS_WINDOWS
|
||||
|
|
|
@ -77,6 +77,7 @@ async function run() {
|
|||
try {
|
||||
const versions = resolveVersionInput();
|
||||
const checkLatest = core.getBooleanInput('check-latest');
|
||||
const allowPreReleases = core.getBooleanInput('allow-prereleases');
|
||||
|
||||
if (versions.length) {
|
||||
let pythonVersion = '';
|
||||
|
@ -89,7 +90,8 @@ async function run() {
|
|||
version,
|
||||
arch,
|
||||
updateEnvironment,
|
||||
checkLatest
|
||||
checkLatest,
|
||||
allowPreReleases
|
||||
);
|
||||
pythonVersion = `${installed.resolvedPyPyVersion}-${installed.resolvedPythonVersion}`;
|
||||
core.info(
|
||||
|
@ -100,7 +102,8 @@ async function run() {
|
|||
version,
|
||||
arch,
|
||||
updateEnvironment,
|
||||
checkLatest
|
||||
checkLatest,
|
||||
allowPreReleases
|
||||
);
|
||||
pythonVersion = installed.version;
|
||||
core.info(`Successfully set up ${installed.impl} (${pythonVersion})`);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue