Add ability to download specific version of Python from releases

This commit is contained in:
MaksimZhukov 2020-04-24 20:29:24 +03:00
parent 985150d1f6
commit 81b3a118a7
9 changed files with 4063 additions and 3618 deletions

View file

@ -3,6 +3,8 @@ import * as path from 'path';
import * as semver from 'semver';
import * as installer from './install-python';
let cacheDirectory = process.env['RUNNER_TOOLSDIRECTORY'] || '';
if (!cacheDirectory) {
@ -92,29 +94,31 @@ async function useCpythonVersion(
const semanticVersionSpec = pythonVersionToSemantic(desugaredVersionSpec);
core.debug(`Semantic version spec of ${version} is ${semanticVersionSpec}`);
const installDir: string | null = tc.find(
let installDir: string | null = tc.find(
'Python',
semanticVersionSpec,
architecture
);
if (!installDir) {
// Fail and list available versions
const x86Versions = tc
.findAllVersions('Python', 'x86')
.map(s => `${s} (x86)`)
.join(os.EOL);
core.info(`Version ${semanticVersionSpec} is not found in local cache`);
const foundRelease = await installer.findReleaseFromManifest(
semanticVersionSpec,
architecture
);
const x64Versions = tc
.findAllVersions('Python', 'x64')
.map(s => `${s} (x64)`)
.join(os.EOL);
if (foundRelease && foundRelease.files && foundRelease.files.length > 0) {
core.info(`Version ${semanticVersionSpec} is available for downloading`);
await installer.installCpythonFromRelease(foundRelease);
installDir = tc.find('Python', semanticVersionSpec, architecture);
}
}
if (!installDir) {
throw new Error(
[
`Version ${version} with arch ${architecture} not found`,
'Available versions:',
x86Versions,
x64Versions
`The list of all available versions can be found here: ${installer.MANIFEST_URL}`
].join(os.EOL)
);
}

64
src/install-python.ts Normal file
View file

@ -0,0 +1,64 @@
import * as path from 'path';
import * as core from '@actions/core';
import * as tc from '@actions/tool-cache';
import * as exec from '@actions/exec';
import {ExecOptions} from '@actions/exec/lib/interfaces';
const AUTH_TOKEN = core.getInput('token');
const MANIFEST_REPO_OWNER = 'actions';
const MANIFEST_REPO_NAME = 'python-versions';
export const MANIFEST_URL = `https://raw.githubusercontent.com/${MANIFEST_REPO_OWNER}/${MANIFEST_REPO_NAME}/master/versions-manifest.json`;
const IS_WINDOWS = process.platform === 'win32';
const IS_LINUX = process.platform === 'linux';
export async function findReleaseFromManifest(
semanticVersionSpec: string,
architecture: string
): Promise<tc.IToolRelease | undefined> {
const manifest: tc.IToolRelease[] = await tc.getManifestFromRepo(
MANIFEST_REPO_OWNER,
MANIFEST_REPO_NAME,
AUTH_TOKEN
);
return await tc.findFromManifest(
semanticVersionSpec,
true,
manifest,
architecture
);
}
export async function installCpythonFromRelease(release: tc.IToolRelease) {
const downloadUrl = release.files[0].download_url;
core.info(`Download from "${downloadUrl}"`);
const pythonPath = await tc.downloadTool(downloadUrl, undefined, AUTH_TOKEN);
const fileName = path.basename(pythonPath, '.zip');
core.info('Extract downloaded archive');
let pythonExtractedFolder;
if (IS_WINDOWS) {
pythonExtractedFolder = await tc.extractZip(pythonPath, `./${fileName}`);
} else {
pythonExtractedFolder = await tc.extractTar(pythonPath, `./${fileName}`);
}
const options: ExecOptions = {
cwd: pythonExtractedFolder,
silent: true,
listeners: {
stdout: (data: Buffer) => {
core.debug(data.toString().trim());
}
}
};
core.info('Execute installation script');
if (IS_WINDOWS) {
await exec.exec('powershell', ['./setup.ps1'], options);
} else if (IS_LINUX) {
await exec.exec('sudo', ['bash', './setup.sh'], options);
} else {
await exec.exec('bash', ['./setup.sh'], options);
}
}