Compare commits

..

3 Commits

6 changed files with 276 additions and 486 deletions
-45
View File
@@ -1,45 +0,0 @@
name: "Code scanning - action"
on:
push:
schedule:
- cron: '25 3 * * 5'
jobs:
CodeQL-Build:
strategy:
fail-fast: false
# CodeQL runs on ubuntu-latest and windows-latest
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v2
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
# Override language selection by uncommenting this and choosing your languages
# with:
# languages: go, javascript, csharp, python, cpp, java
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v1
# ️ Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language
#- run: |
# make bootstrap
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1
-63
View File
@@ -1,63 +0,0 @@
name: Validate 'setup-python'
on:
push:
branches:
- main
paths-ignore:
- '**.md'
pull_request:
paths-ignore:
- '**.md'
schedule:
- cron: 0 0 * * *
jobs:
default-version:
name: Setup default version
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [macos-latest, windows-latest, ubuntu-16.04, ubuntu-18.04]
steps:
- name: Checkout
uses: actions/checkout@v2
- name: setup default python
uses: ./
- name: Validate version
run: python --version
- name: Run simple python code
run: python -c 'import math; print(math.factorial(5))'
setup-versions-from-manifest:
name: Setup ${{ matrix.python }} ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [macos-latest, windows-latest, ubuntu-16.04, ubuntu-18.04]
python: [3.5.4, 3.6.7, 3.7.5, 3.8.1]
steps:
- name: Checkout
uses: actions/checkout@v2
- name: setup-python ${{ matrix.python }}
uses: ./
with:
python-version: ${{ matrix.python }}
- name: Validate version
run: |
$pythonVersion = (python --version)
if ("Python ${{ matrix.python }}" -ne "$pythonVersion"){
Write-Host "The current version is $pythonVersion; expected version is ${{ matrix.python }}"
exit 1
}
$pythonVersion
shell: pwsh
- name: Run simple code
run: python -c 'import math; print(math.factorial(5))'
-90
View File
@@ -1,90 +0,0 @@
name: Main workflow
on:
push:
branches:
- main
paths-ignore:
- '**.md'
pull_request:
paths-ignore:
- '**.md'
jobs:
run:
name: Run
runs-on: ${{ matrix.operating-system }}
strategy:
matrix:
operating-system: [ubuntu-latest, windows-latest]
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Set Node.js 12.x
uses: actions/setup-node@v1
with:
node-version: 12.x
- name: npm install
run: npm install
- name: Lint
run: npm run format-check
- name: npm test
run: npm test
- name: Run with setup-python 2.7
uses: ./
with:
python-version: 2.7
- name: Verify 2.7
run: python __tests__/verify-python.py 2.7
- name: Run with setup-python 3.5
uses: ./
with:
python-version: 3.5
- name: Verify 3.5
run: python __tests__/verify-python.py 3.5
- name: Run with setup-python 3.6
uses: ./
with:
python-version: 3.6
- name: Verify 3.6
run: python __tests__/verify-python.py 3.6
- name: Run with setup-python 3.7
uses: ./
with:
python-version: 3.7
- name: Verify 3.7
run: python __tests__/verify-python.py 3.7
- name: Run with setup-python 3.8
uses: ./
with:
python-version: 3.8
- name: Verify 3.8
run: python __tests__/verify-python.py 3.8
- name: Run with setup-python 3.7.5
uses: ./
with:
python-version: 3.7.5
- name: Verify 3.7.5
run: python __tests__/verify-python.py 3.7.5
- name: Run with setup-python 3.6.7
uses: ./
with:
python-version: 3.6.7
- name: Verify 3.6.7
run: python __tests__/verify-python.py 3.6.7
- name: Run with setup-python 3.8.1
uses: ./
with:
python-version: 3.8.1
- name: Verify 3.8.1
run: python __tests__/verify-python.py 3.8.1
+2 -4
View File
@@ -106,7 +106,7 @@ Check out our detailed guide on using [Python with GitHub Actions](https://help.
- If `3.8.1` is installed for example, and `3.8.2` is released, expect `3.8.1` to be removed and replaced by `3.8.2` in the tools cache.
- If the exact patch version doesn't matter to you, specifying just the major and minor version will get you the latest preinstalled patch version. In the previous example, the version spec `3.8` will use the `3.8.2` Python version found in the cache.
- Downloadable Python versions from GitHub Releases ([actions/python-versions](https://github.com/actions/python-versions/releases))
- All available versions are listed in the [version-manifest.json](https://github.com/actions/python-versions/blob/main/versions-manifest.json) file.
- All available versions are listed in the [version-manifest.json](https://github.com/actions/python-versions/blob/master/versions-manifest.json) file.
- If there is a specific version of Python that is not available, you can open an issue here
# Hosted Tool Cache
@@ -136,9 +136,7 @@ You should specify only a major and minor version if you are okay with the most
# Using `setup-python` with a self hosted runner
Python distributions are only available for the same [environments](https://github.com/actions/virtual-environments#available-environments) that GitHub Actions hosted environments are available for. If you are using an unsupported version of Ubuntu such as `19.04` or another Linux distribution such as Fedora, `setup-python` will not work. If you have a supported self-hosted runner and you would like to use `setup-python`, there are a few extra things you need to make sure are set up so that new versions of Python can be downloaded and configured on your runner.
If you are experiencing problems while configuring Python on your self-hosted runner, turn on [step debugging](https://github.com/actions/toolkit/blob/main/docs/action-debugging.md#step-debug-logs) to see addition logs.
If you would like to use `setup-python` and a self-hosted runner, there are a few extra things you need to make sure are set up so that new versions of Python can be downloaded and configured on your runner.
### Windows
+271 -275
View File
@@ -2361,46 +2361,46 @@ const Range = __webpack_require__(124)
/***/ (function(__unusedmodule, exports, __webpack_require__) {
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
result["default"] = mod;
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
const core = __importStar(__webpack_require__(470));
const finder = __importStar(__webpack_require__(927));
const path = __importStar(__webpack_require__(622));
const os = __importStar(__webpack_require__(87));
function run() {
return __awaiter(this, void 0, void 0, function* () {
try {
let version = core.getInput('python-version');
if (version) {
const arch = core.getInput('architecture') || os.arch();
const installed = yield finder.findPythonVersion(version, arch);
core.info(`Successfully setup ${installed.impl} (${installed.version})`);
}
const matchersPath = path.join(__dirname, '..', '.github');
core.info(`##[add-matcher]${path.join(matchersPath, 'python.json')}`);
}
catch (err) {
core.setFailed(err.message);
}
});
}
run();
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
result["default"] = mod;
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
const core = __importStar(__webpack_require__(470));
const finder = __importStar(__webpack_require__(927));
const path = __importStar(__webpack_require__(622));
const os = __importStar(__webpack_require__(87));
function run() {
return __awaiter(this, void 0, void 0, function* () {
try {
let version = core.getInput('python-version');
if (version) {
const arch = core.getInput('architecture') || os.arch();
const installed = yield finder.findPythonVersion(version, arch);
core.info(`Successfully setup ${installed.impl} (${installed.version})`);
}
const matchersPath = path.join(__dirname, '..', '.github');
core.info(`##[add-matcher]${path.join(matchersPath, 'python.json')}`);
}
catch (err) {
core.setFailed(err.message);
}
});
}
run();
/***/ }),
@@ -6312,87 +6312,83 @@ module.exports = diff
/***/ (function(__unusedmodule, exports, __webpack_require__) {
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
result["default"] = mod;
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
const path = __importStar(__webpack_require__(622));
const core = __importStar(__webpack_require__(470));
const tc = __importStar(__webpack_require__(533));
const exec = __importStar(__webpack_require__(986));
const TOKEN = core.getInput('token');
const AUTH = !TOKEN || isGhes() ? undefined : `token ${TOKEN}`;
const MANIFEST_REPO_OWNER = 'actions';
const MANIFEST_REPO_NAME = 'python-versions';
const MANIFEST_REPO_BRANCH = 'main';
exports.MANIFEST_URL = `https://raw.githubusercontent.com/${MANIFEST_REPO_OWNER}/${MANIFEST_REPO_NAME}/${MANIFEST_REPO_BRANCH}/versions-manifest.json`;
const IS_WINDOWS = process.platform === 'win32';
function findReleaseFromManifest(semanticVersionSpec, architecture) {
return __awaiter(this, void 0, void 0, function* () {
const manifest = yield tc.getManifestFromRepo(MANIFEST_REPO_OWNER, MANIFEST_REPO_NAME, AUTH, MANIFEST_REPO_BRANCH);
return yield tc.findFromManifest(semanticVersionSpec, true, manifest, architecture);
});
}
exports.findReleaseFromManifest = findReleaseFromManifest;
function installPython(workingDirectory) {
return __awaiter(this, void 0, void 0, function* () {
const options = {
cwd: workingDirectory,
silent: true,
listeners: {
stdout: (data) => {
core.info(data.toString().trim());
},
stderr: (data) => {
core.error(data.toString().trim());
}
}
};
if (IS_WINDOWS) {
yield exec.exec('powershell', ['./setup.ps1'], options);
}
else {
yield exec.exec('bash', ['./setup.sh'], options);
}
});
}
function installCpythonFromRelease(release) {
return __awaiter(this, void 0, void 0, function* () {
const downloadUrl = release.files[0].download_url;
core.info(`Download from "${downloadUrl}"`);
const pythonPath = yield tc.downloadTool(downloadUrl, undefined, AUTH);
const fileName = path.basename(pythonPath, '.zip');
core.info('Extract downloaded archive');
let pythonExtractedFolder;
if (IS_WINDOWS) {
pythonExtractedFolder = yield tc.extractZip(pythonPath, `./${fileName}`);
}
else {
pythonExtractedFolder = yield tc.extractTar(pythonPath, `./${fileName}`);
}
core.info('Execute installation script');
yield installPython(pythonExtractedFolder);
});
}
exports.installCpythonFromRelease = installCpythonFromRelease;
function isGhes() {
const ghUrl = new URL(process.env['GITHUB_SERVER_URL'] || 'https://github.com');
return ghUrl.hostname.toUpperCase() !== 'GITHUB.COM';
}
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
result["default"] = mod;
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
const path = __importStar(__webpack_require__(622));
const core = __importStar(__webpack_require__(470));
const tc = __importStar(__webpack_require__(533));
const exec = __importStar(__webpack_require__(986));
const TOKEN = core.getInput('token');
const AUTH = !TOKEN || isGhes() ? undefined : `token ${TOKEN}`;
const MANIFEST_REPO_OWNER = 'actions';
const MANIFEST_REPO_NAME = 'python-versions';
exports.MANIFEST_URL = `https://raw.githubusercontent.com/${MANIFEST_REPO_OWNER}/${MANIFEST_REPO_NAME}/master/versions-manifest.json`;
const IS_WINDOWS = process.platform === 'win32';
function findReleaseFromManifest(semanticVersionSpec, architecture) {
return __awaiter(this, void 0, void 0, function* () {
const manifest = yield tc.getManifestFromRepo(MANIFEST_REPO_OWNER, MANIFEST_REPO_NAME, AUTH);
return yield tc.findFromManifest(semanticVersionSpec, true, manifest, architecture);
});
}
exports.findReleaseFromManifest = findReleaseFromManifest;
function installPython(workingDirectory) {
return __awaiter(this, void 0, void 0, function* () {
const options = {
cwd: workingDirectory,
silent: true,
listeners: {
stdout: (data) => {
core.debug(data.toString().trim());
}
}
};
if (IS_WINDOWS) {
yield exec.exec('powershell', ['./setup.ps1'], options);
}
else {
yield exec.exec('bash', ['./setup.sh'], options);
}
});
}
function installCpythonFromRelease(release) {
return __awaiter(this, void 0, void 0, function* () {
const downloadUrl = release.files[0].download_url;
core.info(`Download from "${downloadUrl}"`);
const pythonPath = yield tc.downloadTool(downloadUrl, undefined, AUTH);
const fileName = path.basename(pythonPath, '.zip');
core.info('Extract downloaded archive');
let pythonExtractedFolder;
if (IS_WINDOWS) {
pythonExtractedFolder = yield tc.extractZip(pythonPath, `./${fileName}`);
}
else {
pythonExtractedFolder = yield tc.extractTar(pythonPath, `./${fileName}`);
}
core.info('Execute installation script');
yield installPython(pythonExtractedFolder);
});
}
exports.installCpythonFromRelease = installCpythonFromRelease;
function isGhes() {
const ghUrl = new URL(process.env['GITHUB_SERVER_URL'] || 'https://github.com');
return ghUrl.hostname.toUpperCase() !== 'GITHUB.COM';
}
/***/ }),
@@ -6573,160 +6569,160 @@ module.exports = lte
/***/ (function(__unusedmodule, exports, __webpack_require__) {
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
result["default"] = mod;
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
const os = __importStar(__webpack_require__(87));
const path = __importStar(__webpack_require__(622));
const semver = __importStar(__webpack_require__(876));
const installer = __importStar(__webpack_require__(824));
const core = __importStar(__webpack_require__(470));
const tc = __importStar(__webpack_require__(533));
const IS_WINDOWS = process.platform === 'win32';
// Python has "scripts" or "bin" directories where command-line tools that come with packages are installed.
// This is where pip is, along with anything that pip installs.
// There is a seperate directory for `pip install --user`.
//
// For reference, these directories are as follows:
// macOS / Linux:
// <sys.prefix>/bin (by default /usr/local/bin, but not on hosted agents -- see the `else`)
// (--user) ~/.local/bin
// Windows:
// <Python installation dir>\Scripts
// (--user) %APPDATA%\Python\PythonXY\Scripts
// See https://docs.python.org/3/library/sysconfig.html
function binDir(installDir) {
if (IS_WINDOWS) {
return path.join(installDir, 'Scripts');
}
else {
return path.join(installDir, 'bin');
}
}
// Note on the tool cache layout for PyPy:
// PyPy has its own versioning scheme that doesn't follow the Python versioning scheme.
// A particular version of PyPy may contain one or more versions of the Python interpreter.
// For example, PyPy 7.0 contains Python 2.7, 3.5, and 3.6-alpha.
// We only care about the Python version, so we don't use the PyPy version for the tool cache.
function usePyPy(majorVersion, architecture) {
const findPyPy = tc.find.bind(undefined, 'PyPy', majorVersion.toString());
let installDir = findPyPy(architecture);
if (!installDir && IS_WINDOWS) {
// PyPy only precompiles binaries for x86, but the architecture parameter defaults to x64.
// On our Windows virtual environments, we only install an x86 version.
// Fall back to x86.
installDir = findPyPy('x86');
}
if (!installDir) {
// PyPy not installed in $(Agent.ToolsDirectory)
throw new Error(`PyPy ${majorVersion} not found`);
}
// For PyPy, Windows uses 'bin', not 'Scripts'.
const _binDir = path.join(installDir, 'bin');
// On Linux and macOS, the Python interpreter is in 'bin'.
// On Windows, it is in the installation root.
const pythonLocation = IS_WINDOWS ? installDir : _binDir;
core.exportVariable('pythonLocation', pythonLocation);
core.addPath(installDir);
core.addPath(_binDir);
const impl = 'pypy' + majorVersion.toString();
core.setOutput('python-version', impl);
return { impl: impl, version: versionFromPath(installDir) };
}
function useCpythonVersion(version, architecture) {
return __awaiter(this, void 0, void 0, function* () {
const desugaredVersionSpec = desugarDevVersion(version);
const semanticVersionSpec = pythonVersionToSemantic(desugaredVersionSpec);
core.debug(`Semantic version spec of ${version} is ${semanticVersionSpec}`);
let installDir = tc.find('Python', semanticVersionSpec, architecture);
if (!installDir) {
core.info(`Version ${semanticVersionSpec} was not found in the local cache`);
const foundRelease = yield installer.findReleaseFromManifest(semanticVersionSpec, architecture);
if (foundRelease && foundRelease.files && foundRelease.files.length > 0) {
core.info(`Version ${semanticVersionSpec} is available for downloading`);
yield installer.installCpythonFromRelease(foundRelease);
installDir = tc.find('Python', semanticVersionSpec, architecture);
}
}
if (!installDir) {
throw new Error([
`Version ${version} with arch ${architecture} not found`,
`The list of all available versions can be found here: ${installer.MANIFEST_URL}`
].join(os.EOL));
}
core.exportVariable('pythonLocation', installDir);
core.addPath(installDir);
core.addPath(binDir(installDir));
if (IS_WINDOWS) {
// Add --user directory
// `installDir` from tool cache should look like $RUNNER_TOOL_CACHE/Python/<semantic version>/x64/
// So if `findLocalTool` succeeded above, we must have a conformant `installDir`
const version = path.basename(path.dirname(installDir));
const major = semver.major(version);
const minor = semver.minor(version);
const userScriptsDir = path.join(process.env['APPDATA'] || '', 'Python', `Python${major}${minor}`, 'Scripts');
core.addPath(userScriptsDir);
}
// On Linux and macOS, pip will create the --user directory and add it to PATH as needed.
const installed = versionFromPath(installDir);
core.setOutput('python-version', installed);
return { impl: 'CPython', version: installed };
});
}
/** Convert versions like `3.8-dev` to a version like `>= 3.8.0-a0`. */
function desugarDevVersion(versionSpec) {
if (versionSpec.endsWith('-dev')) {
const versionRoot = versionSpec.slice(0, -'-dev'.length);
return `>= ${versionRoot}.0-a0`;
}
else {
return versionSpec;
}
}
/** Extracts python version from install path from hosted tool cache as described in README.md */
function versionFromPath(installDir) {
const parts = installDir.split(path.sep);
const idx = parts.findIndex(part => part === 'PyPy' || part === 'Python');
return parts[idx + 1] || '';
}
/**
* 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.
*/
function pythonVersionToSemantic(versionSpec) {
const prereleaseVersion = /(\d+\.\d+\.\d+)((?:a|b|rc)\d*)/g;
return versionSpec.replace(prereleaseVersion, '$1-$2');
}
exports.pythonVersionToSemantic = pythonVersionToSemantic;
function findPythonVersion(version, architecture) {
return __awaiter(this, void 0, void 0, function* () {
switch (version.toUpperCase()) {
case 'PYPY2':
return usePyPy(2, architecture);
case 'PYPY3':
return usePyPy(3, architecture);
default:
return yield useCpythonVersion(version, architecture);
}
});
}
exports.findPythonVersion = findPythonVersion;
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
result["default"] = mod;
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
const os = __importStar(__webpack_require__(87));
const path = __importStar(__webpack_require__(622));
const semver = __importStar(__webpack_require__(876));
const installer = __importStar(__webpack_require__(824));
const core = __importStar(__webpack_require__(470));
const tc = __importStar(__webpack_require__(533));
const IS_WINDOWS = process.platform === 'win32';
// Python has "scripts" or "bin" directories where command-line tools that come with packages are installed.
// This is where pip is, along with anything that pip installs.
// There is a seperate directory for `pip install --user`.
//
// For reference, these directories are as follows:
// macOS / Linux:
// <sys.prefix>/bin (by default /usr/local/bin, but not on hosted agents -- see the `else`)
// (--user) ~/.local/bin
// Windows:
// <Python installation dir>\Scripts
// (--user) %APPDATA%\Python\PythonXY\Scripts
// See https://docs.python.org/3/library/sysconfig.html
function binDir(installDir) {
if (IS_WINDOWS) {
return path.join(installDir, 'Scripts');
}
else {
return path.join(installDir, 'bin');
}
}
// Note on the tool cache layout for PyPy:
// PyPy has its own versioning scheme that doesn't follow the Python versioning scheme.
// A particular version of PyPy may contain one or more versions of the Python interpreter.
// For example, PyPy 7.0 contains Python 2.7, 3.5, and 3.6-alpha.
// We only care about the Python version, so we don't use the PyPy version for the tool cache.
function usePyPy(majorVersion, architecture) {
const findPyPy = tc.find.bind(undefined, 'PyPy', majorVersion.toString());
let installDir = findPyPy(architecture);
if (!installDir && IS_WINDOWS) {
// PyPy only precompiles binaries for x86, but the architecture parameter defaults to x64.
// On our Windows virtual environments, we only install an x86 version.
// Fall back to x86.
installDir = findPyPy('x86');
}
if (!installDir) {
// PyPy not installed in $(Agent.ToolsDirectory)
throw new Error(`PyPy ${majorVersion} not found`);
}
// For PyPy, Windows uses 'bin', not 'Scripts'.
const _binDir = path.join(installDir, 'bin');
// On Linux and macOS, the Python interpreter is in 'bin'.
// On Windows, it is in the installation root.
const pythonLocation = IS_WINDOWS ? installDir : _binDir;
core.exportVariable('pythonLocation', pythonLocation);
core.addPath(installDir);
core.addPath(_binDir);
const impl = 'pypy' + majorVersion.toString();
core.setOutput('python-version', impl);
return { impl: impl, version: versionFromPath(installDir) };
}
function useCpythonVersion(version, architecture) {
return __awaiter(this, void 0, void 0, function* () {
const desugaredVersionSpec = desugarDevVersion(version);
const semanticVersionSpec = pythonVersionToSemantic(desugaredVersionSpec);
core.debug(`Semantic version spec of ${version} is ${semanticVersionSpec}`);
let installDir = tc.find('Python', semanticVersionSpec, architecture);
if (!installDir) {
core.info(`Version ${semanticVersionSpec} was not found in the local cache`);
const foundRelease = yield installer.findReleaseFromManifest(semanticVersionSpec, architecture);
if (foundRelease && foundRelease.files && foundRelease.files.length > 0) {
core.info(`Version ${semanticVersionSpec} is available for downloading`);
yield installer.installCpythonFromRelease(foundRelease);
installDir = tc.find('Python', semanticVersionSpec, architecture);
}
}
if (!installDir) {
throw new Error([
`Version ${version} with arch ${architecture} not found`,
`The list of all available versions can be found here: ${installer.MANIFEST_URL}`
].join(os.EOL));
}
core.exportVariable('pythonLocation', installDir);
core.addPath(installDir);
core.addPath(binDir(installDir));
if (IS_WINDOWS) {
// Add --user directory
// `installDir` from tool cache should look like $RUNNER_TOOL_CACHE/Python/<semantic version>/x64/
// So if `findLocalTool` succeeded above, we must have a conformant `installDir`
const version = path.basename(path.dirname(installDir));
const major = semver.major(version);
const minor = semver.minor(version);
const userScriptsDir = path.join(process.env['APPDATA'] || '', 'Python', `Python${major}${minor}`, 'Scripts');
core.addPath(userScriptsDir);
}
// On Linux and macOS, pip will create the --user directory and add it to PATH as needed.
const installed = versionFromPath(installDir);
core.setOutput('python-version', installed);
return { impl: 'CPython', version: installed };
});
}
/** Convert versions like `3.8-dev` to a version like `>= 3.8.0-a0`. */
function desugarDevVersion(versionSpec) {
if (versionSpec.endsWith('-dev')) {
const versionRoot = versionSpec.slice(0, -'-dev'.length);
return `>= ${versionRoot}.0-a0`;
}
else {
return versionSpec;
}
}
/** Extracts python version from install path from hosted tool cache as described in README.md */
function versionFromPath(installDir) {
const parts = installDir.split(path.sep);
const idx = parts.findIndex(part => part === 'PyPy' || part === 'Python');
return parts[idx + 1] || '';
}
/**
* 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.
*/
function pythonVersionToSemantic(versionSpec) {
const prereleaseVersion = /(\d+\.\d+\.\d+)((?:a|b|rc)\d*)/g;
return versionSpec.replace(prereleaseVersion, '$1-$2');
}
exports.pythonVersionToSemantic = pythonVersionToSemantic;
function findPythonVersion(version, architecture) {
return __awaiter(this, void 0, void 0, function* () {
switch (version.toUpperCase()) {
case 'PYPY2':
return usePyPy(2, architecture);
case 'PYPY3':
return usePyPy(3, architecture);
default:
return yield useCpythonVersion(version, architecture);
}
});
}
exports.findPythonVersion = findPythonVersion;
/***/ }),
+3 -9
View File
@@ -3,14 +3,12 @@ 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';
import {stderr} from 'process';
const TOKEN = core.getInput('token');
const AUTH = !TOKEN || isGhes() ? undefined : `token ${TOKEN}`;
const MANIFEST_REPO_OWNER = 'actions';
const MANIFEST_REPO_NAME = 'python-versions';
const MANIFEST_REPO_BRANCH = 'main';
export const MANIFEST_URL = `https://raw.githubusercontent.com/${MANIFEST_REPO_OWNER}/${MANIFEST_REPO_NAME}/${MANIFEST_REPO_BRANCH}/versions-manifest.json`;
export const MANIFEST_URL = `https://raw.githubusercontent.com/${MANIFEST_REPO_OWNER}/${MANIFEST_REPO_NAME}/master/versions-manifest.json`;
const IS_WINDOWS = process.platform === 'win32';
@@ -21,8 +19,7 @@ export async function findReleaseFromManifest(
const manifest: tc.IToolRelease[] = await tc.getManifestFromRepo(
MANIFEST_REPO_OWNER,
MANIFEST_REPO_NAME,
AUTH,
MANIFEST_REPO_BRANCH
AUTH
);
return await tc.findFromManifest(
semanticVersionSpec,
@@ -38,10 +35,7 @@ async function installPython(workingDirectory: string) {
silent: true,
listeners: {
stdout: (data: Buffer) => {
core.info(data.toString().trim());
},
stderr: (data: Buffer) => {
core.error(data.toString().trim());
core.debug(data.toString().trim());
}
}
};