Add support to .tool-version file format

Create a function to parse tool-version (asdf-vm) format, add the
associated tests, and updated the documentation

Ticket-ID: #571
This commit is contained in:
Pablo Ifrán 2023-01-17 18:33:06 -03:00
parent bd6b4b6205
commit 892baae68b
4 changed files with 47 additions and 6 deletions

View File

@ -1,6 +1,7 @@
import * as cache from '@actions/cache'; import * as cache from '@actions/cache';
import * as core from '@actions/core'; import * as core from '@actions/core';
import { import {
parsePythonVersionFile,
validateVersion, validateVersion,
validatePythonVersionFormatForPyPy, validatePythonVersionFormatForPyPy,
isCacheFeatureAvailable isCacheFeatureAvailable
@ -9,6 +10,20 @@ import {
jest.mock('@actions/cache'); jest.mock('@actions/cache');
jest.mock('@actions/core'); jest.mock('@actions/core');
describe('parsePythonVersionFile', () => {
it('handle the content of a .python-version file', () => {
expect(parsePythonVersionFile('3.6')).toEqual('3.6')
});
it('trims extra spaces at the end of the content', () => {
expect(parsePythonVersionFile('3.7 ')).toEqual('3.7')
});
it('parses correctly the content of .tool-version files', () => {
expect(parsePythonVersionFile('python 3.7')).toEqual('3.7')
});
});
describe('validatePythonVersionFormatForPyPy', () => { describe('validatePythonVersionFormatForPyPy', () => {
it.each([ it.each([
['3.6', true], ['3.6', true],

View File

@ -239,9 +239,10 @@ jobs:
## Using the `python-version-file` input ## Using the `python-version-file` input
`setup-python` action can read Python or PyPy version from a version file. `python-version-file` input is used for specifying the path to the version file. If the file that was supplied to `python-version-file` input doesn't exist, the action will fail with error. The python-version-file input accepts a path to a file containing the version of Python to be used by a project, for example .python-version, or .tool-versions.
If both the python-version and the python-version-file inputs are provided then the python-version input is used.
>In case both `python-version` and `python-version-file` inputs are supplied, the `python-version-file` input will be ignored due to its lower priority. > The action will search for the python version file relative to the repository root.
```yaml ```yaml
steps: steps:

View File

@ -5,7 +5,7 @@ import * as path from 'path';
import * as os from 'os'; import * as os from 'os';
import fs from 'fs'; import fs from 'fs';
import {getCacheDistributor} from './cache-distributions/cache-factory'; import {getCacheDistributor} from './cache-distributions/cache-factory';
import {isCacheFeatureAvailable, logWarning, IS_MAC} from './utils'; import {parsePythonVersionFile, isCacheFeatureAvailable, logWarning, IS_MAC} from './utils';
function isPyPyVersion(versionSpec: string) { function isPyPyVersion(versionSpec: string) {
return versionSpec.startsWith('pypy'); return versionSpec.startsWith('pypy');
@ -37,20 +37,29 @@ function resolveVersionInput() {
} }
if (versionFile) { if (versionFile) {
if (!fs.existsSync(versionFile)) { const versionFilePath = path.join(
process.env.GITHUB_WORKSPACE!,
versionFile
);
if (!fs.existsSync(versionFilePath)) {
throw new Error( throw new Error(
`The specified python version file at: ${versionFile} doesn't exist.` `The specified python version file at: ${versionFilePath} doesn't exist.`
); );
} }
const version = fs.readFileSync(versionFile, 'utf8');
const version = parsePythonVersionFile(fs.readFileSync(versionFilePath, 'utf8'));
core.info(`Resolved ${versionFile} as ${version}`); core.info(`Resolved ${versionFile} as ${version}`);
return [version]; return [version];
} }
logWarning( logWarning(
"Neither 'python-version' nor 'python-version-file' inputs were supplied. Attempting to find '.python-version' file." "Neither 'python-version' nor 'python-version-file' inputs were supplied. Attempting to find '.python-version' file."
); );
versionFile = '.python-version'; versionFile = '.python-version';
if (fs.existsSync(versionFile)) { if (fs.existsSync(versionFile)) {
const version = fs.readFileSync(versionFile, 'utf8'); const version = fs.readFileSync(versionFile, 'utf8');
core.info(`Resolved ${versionFile} as ${version}`); core.info(`Resolved ${versionFile} as ${version}`);

View File

@ -28,6 +28,22 @@ export interface IPyPyManifestRelease {
files: IPyPyManifestAsset[]; files: IPyPyManifestAsset[];
} }
export function parsePythonVersionFile(contents: string): string {
let pythonVersion: string | undefined;
// Try to find the version in tool-version file
const found = contents.match(/^(?:python\s+)?v?(?<version>[^\s]+)$/m);
pythonVersion = found?.groups?.version;
// In the case of an unknown format,
// return as is and evaluate the version separately.
if (!pythonVersion) {
pythonVersion = contents.trim();
}
return pythonVersion as string;
}
/** create Symlinks for downloaded PyPy /** create Symlinks for downloaded PyPy
* It should be executed only for downloaded versions in runtime, because * It should be executed only for downloaded versions in runtime, because
* toolcache versions have this setup. * toolcache versions have this setup.