forked from actions/setup-python
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsetup-python.ts
More file actions
178 lines (165 loc) · 5.83 KB
/
setup-python.ts
File metadata and controls
178 lines (165 loc) · 5.83 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
import * as core from '@actions/core';
import * as finder from './find-python';
import * as finderPyPy from './find-pypy';
import * as finderGraalPy from './find-graalpy';
import * as path from 'path';
import * as os from 'os';
import fs from 'fs';
import {getCacheDistributor} from './cache-distributions/cache-factory';
import {
isCacheFeatureAvailable,
logWarning,
IS_MAC,
getVersionInputFromFile,
getVersionsInputFromPlainFile
} from './utils';
import {exec} from '@actions/exec';
function isPyPyVersion(versionSpec: string) {
return versionSpec.startsWith('pypy');
}
function isGraalPyVersion(versionSpec: string) {
return versionSpec.startsWith('graalpy');
}
async function installPipPackages(pipInstall: string) {
core.info(`Installing pip packages: ${pipInstall}`);
try {
const installArgs = pipInstall.trim().split(/\s+/);
await exec('python', ['-m', 'pip', 'install', ...installArgs]);
core.info('Successfully installed pip packages');
} catch (error) {
core.setFailed(
`Failed to install pip packages from "${pipInstall}". Please verify that the package names, versions, or requirements files provided are correct and installable, that the specified packages and versions can be resolved from PyPI or the configured package index, and that your network connection is stable and allows access to the package index.`
);
}
}
async function cacheDependencies(cache: string, pythonVersion: string) {
const cacheDependencyPath =
core.getInput('cache-dependency-path') || undefined;
const cacheDistributor = getCacheDistributor(
cache,
pythonVersion,
cacheDependencyPath
);
await cacheDistributor.restoreCache();
}
function resolveVersionInputFromDefaultFile(): string[] {
const couples: [string, (versionFile: string) => string[]][] = [
['.python-version', getVersionsInputFromPlainFile]
];
for (const [versionFile, _fn] of couples) {
logWarning(
`Neither 'python-version' nor 'python-version-file' inputs were supplied. Attempting to find '${versionFile}' file.`
);
if (fs.existsSync(versionFile)) {
return _fn(versionFile);
} else {
logWarning(`${versionFile} doesn't exist.`);
}
}
return [];
}
function resolveVersionInput() {
let versions = core.getMultilineInput('python-version');
const versionFile = core.getInput('python-version-file');
if (versions.length) {
if (versionFile) {
core.warning(
'Both python-version and python-version-file inputs are specified, only python-version will be used.'
);
}
} else {
if (versionFile) {
if (!fs.existsSync(versionFile)) {
throw new Error(
`The specified python version file at: ${versionFile} doesn't exist.`
);
}
versions = getVersionInputFromFile(versionFile);
} else {
versions = resolveVersionInputFromDefaultFile();
}
}
return versions;
}
async function run() {
if (IS_MAC) {
process.env['AGENT_TOOLSDIRECTORY'] = '/Users/runner/hostedtoolcache';
}
if (process.env.AGENT_TOOLSDIRECTORY?.trim()) {
process.env['RUNNER_TOOL_CACHE'] = process.env['AGENT_TOOLSDIRECTORY'];
}
core.debug(
`Python is expected to be installed into ${process.env['RUNNER_TOOL_CACHE']}`
);
try {
const versions = resolveVersionInput();
const checkLatest = core.getBooleanInput('check-latest');
const allowPreReleases = core.getBooleanInput('allow-prereleases');
const freethreaded = core.getBooleanInput('freethreaded');
if (versions.length) {
let pythonVersion = '';
const arch: string = core.getInput('architecture') || os.arch();
const updateEnvironment = core.getBooleanInput('update-environment');
core.startGroup('Installed versions');
for (const version of versions) {
if (isPyPyVersion(version)) {
const installed = await finderPyPy.findPyPyVersion(
version,
arch,
updateEnvironment,
checkLatest,
allowPreReleases
);
pythonVersion = `${installed.resolvedPyPyVersion}-${installed.resolvedPythonVersion}`;
core.info(
`Successfully set up PyPy ${installed.resolvedPyPyVersion} with Python (${installed.resolvedPythonVersion})`
);
} else if (isGraalPyVersion(version)) {
const installed = await finderGraalPy.findGraalPyVersion(
version,
arch,
updateEnvironment,
checkLatest,
allowPreReleases
);
pythonVersion = `${installed}`;
core.info(`Successfully set up GraalPy ${installed}`);
} else {
if (version.startsWith('2')) {
core.warning(
'The support for python 2.7 was removed on June 19, 2023. Related issue: https://github.com/actions/setup-python/issues/672'
);
}
const installed = await finder.useCpythonVersion(
version,
arch,
updateEnvironment,
checkLatest,
allowPreReleases,
freethreaded
);
pythonVersion = installed.version;
core.info(`Successfully set up ${installed.impl} (${pythonVersion})`);
}
}
core.endGroup();
const cache = core.getInput('cache');
if (cache && isCacheFeatureAvailable()) {
await cacheDependencies(cache, pythonVersion);
}
const pipInstall = core.getInput('pip-install');
if (pipInstall) {
await installPipPackages(pipInstall);
}
} else {
core.warning(
'The `python-version` input is not set. The version of Python currently in `PATH` will be used.'
);
}
const matchersPath = path.join(__dirname, '../..', '.github');
core.info(`##[add-matcher]${path.join(matchersPath, 'python.json')}`);
} catch (err) {
core.setFailed((err as Error).message);
}
}
run();