Compare commits

..

3 Commits

Author SHA1 Message Date
e9c40fbc2b Add support for pip-version (#1129)
* Add pip-version input

* Update workflow files

* Add documentation

* Update workflow files
2025-06-19 22:09:35 -05:00
5fa0ee6f38 Bump @actions/tool-cache from 2.0.1 to 2.0.2 (#1095)
* Bump @actions/tool-cache from 2.0.1 to 2.0.2

Bumps [@actions/tool-cache](https://github.com/actions/toolkit/tree/HEAD/packages/tool-cache) from 2.0.1 to 2.0.2.
- [Changelog](https://github.com/actions/toolkit/blob/main/packages/tool-cache/RELEASES.md)
- [Commits](https://github.com/actions/toolkit/commits/HEAD/packages/tool-cache)

---
updated-dependencies:
- dependency-name: "@actions/tool-cache"
  dependency-version: 2.0.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

* Fix failures

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: HarithaVattikuti <73516759+HarithaVattikuti@users.noreply.github.com>
2025-06-18 17:01:16 -05:00
5db1cf9a59 Enhance reading from .python-version (#787)
* Enhance reading from .python-version

* Fix typos

* Fix lint

* Add built files

* Don't use EOL versions in `utils.test.ts`

* Fix Prettier

* Don't use unreleased versions in `utils.test.ts`

* Update versions in `utils.test.ts` again
2025-05-21 16:19:28 -05:00
15 changed files with 329 additions and 218 deletions

View File

@ -162,3 +162,60 @@ jobs:
run: curl https://raw.githubusercontent.com/pypa/pipenv/master/get-pipenv.py | python run: curl https://raw.githubusercontent.com/pypa/pipenv/master/get-pipenv.py | python
- name: Install dependencies - name: Install dependencies
run: pipenv install requests run: pipenv install requests
python-pip-dependencies-caching-with-pip-version:
name: Test pip (Python ${{ matrix.python-version}}, ${{ matrix.os }})
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os:
[
ubuntu-latest,
ubuntu-22.04,
ubuntu-24.04-arm,
ubuntu-22.04-arm,
windows-latest,
macos-latest,
macos-13
]
python-version: [3.13.0t, 3.13.1t, 3.13.2t]
steps:
- uses: actions/checkout@v4
- name: Setup Python
uses: ./
with:
python-version: ${{ matrix.python-version }}
cache: 'pip'
pip-version: '25.0.1'
- name: Install dependencies
run: pip install numpy pandas requests
python-pip-dependencies-caching-path-with-pip-version:
name: Test pip (Python ${{ matrix.python-version}}, ${{ matrix.os }}, caching path)
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os:
[
ubuntu-latest,
ubuntu-22.04,
ubuntu-24.04-arm,
ubuntu-22.04-arm,
windows-latest,
macos-latest,
macos-13
]
python-version: [3.13.0t, 3.13.1t, 3.13.2t]
steps:
- uses: actions/checkout@v4
- name: Setup Python
uses: ./
with:
python-version: ${{ matrix.python-version }}
cache: 'pip'
cache-dependency-path: __tests__/data/requirements.txt
pip-version: '25.0.1'
- name: Install dependencies
run: pip install numpy pandas requests

View File

@ -249,3 +249,60 @@ jobs:
} }
- name: Run Python Script - name: Run Python Script
run: pipenv run python test-pipenv.py run: pipenv run python test-pipenv.py
python-pip-dependencies-caching-with-pip-version:
name: Test pip (Python ${{ matrix.python-version}}, ${{ matrix.os }})
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os:
[
ubuntu-latest,
ubuntu-24.04-arm,
ubuntu-22.04,
ubuntu-22.04-arm,
windows-latest,
macos-latest,
macos-13
]
python-version: ['3.9', '3.10', '3.11', '3.12', '3.13']
steps:
- uses: actions/checkout@v4
- name: Setup Python
uses: ./
with:
python-version: ${{ matrix.python-version }}
cache: 'pip'
pip-version: '25.0.1'
- name: Install dependencies
run: pip install numpy pandas requests
python-pip-dependencies-caching-path-with-pip-version:
name: Test pip (Python ${{ matrix.python-version}}, ${{ matrix.os }}, caching path)
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os:
[
ubuntu-latest,
ubuntu-24.04-arm,
ubuntu-22.04,
ubuntu-22.04-arm,
windows-latest,
macos-latest,
macos-13
]
python-version: ['3.9', '3.10', '3.11', '3.12', '3.13']
steps:
- uses: actions/checkout@v4
- name: Setup Python
uses: ./
with:
python-version: ${{ matrix.python-version }}
cache: 'pip'
cache-dependency-path: __tests__/data/requirements.txt
pip-version: '25.0.1'
- name: Install dependencies
run: pip install numpy pandas requests

View File

@ -1,6 +1,6 @@
--- ---
name: "@actions/tool-cache" name: "@actions/tool-cache"
version: 2.0.1 version: 2.0.2
type: npm type: npm
summary: Actions tool-cache lib summary: Actions tool-cache lib
homepage: https://github.com/actions/toolkit/tree/main/packages/tool-cache homepage: https://github.com/actions/toolkit/tree/main/packages/tool-cache

View File

@ -1,39 +0,0 @@
---
name: uuid
version: 3.4.0
type: npm
summary: RFC4122 (v1, v4, and v5) UUIDs
homepage: https://github.com/uuidjs/uuid#readme
license: mit
licenses:
- sources: LICENSE.md
text: |
The MIT License (MIT)
Copyright (c) 2010-2016 Robert Kieffer and other contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
notices:
- sources: AUTHORS
text: |-
Robert Kieffer <robert@broofa.com>
Christoph Tavan <dev@tavan.de>
AJ ONeal <coolaj86@gmail.com>
Vincent Voyer <vincent@zeroload.net>
Roman Shtylman <shtylman@gmail.com>

View File

@ -3,7 +3,7 @@ name: uuid
version: 8.3.2 version: 8.3.2
type: npm type: npm
summary: RFC4122 (v1, v4, and v5) UUIDs summary: RFC4122 (v1, v4, and v5) UUIDs
homepage: https://github.com/uuidjs/uuid#readme homepage:
license: mit license: mit
licenses: licenses:
- sources: LICENSE.md - sources: LICENSE.md

View File

@ -108,6 +108,7 @@ See examples of using `cache` and `cache-dependency-path` for `pipenv` and `poet
- [Using `setup-python` with a self-hosted runner](docs/advanced-usage.md#using-setup-python-with-a-self-hosted-runner) - [Using `setup-python` with a self-hosted runner](docs/advanced-usage.md#using-setup-python-with-a-self-hosted-runner)
- [Using `setup-python` on GHES](docs/advanced-usage.md#using-setup-python-on-ghes) - [Using `setup-python` on GHES](docs/advanced-usage.md#using-setup-python-on-ghes)
- [Allow pre-releases](docs/advanced-usage.md#allow-pre-releases) - [Allow pre-releases](docs/advanced-usage.md#allow-pre-releases)
- [Using the pip-version input](docs/advanced-usage.md#using-the-pip-version-input)
## Recommended permissions ## Recommended permissions

View File

@ -10,7 +10,7 @@ import {
validatePythonVersionFormatForPyPy, validatePythonVersionFormatForPyPy,
isCacheFeatureAvailable, isCacheFeatureAvailable,
getVersionInputFromFile, getVersionInputFromFile,
getVersionInputFromPlainFile, getVersionsInputFromPlainFile,
getVersionInputFromTomlFile, getVersionInputFromTomlFile,
getNextPageUrl, getNextPageUrl,
isGhes, isGhes,
@ -24,10 +24,10 @@ jest.mock('@actions/core');
describe('validatePythonVersionFormatForPyPy', () => { describe('validatePythonVersionFormatForPyPy', () => {
it.each([ it.each([
['3.6', true], ['3.12', true],
['3.7', true], ['3.13', true],
['3.6.x', false], ['3.12.x', false],
['3.7.x', false], ['3.13.x', false],
['3.x', false], ['3.x', false],
['3', false] ['3', false]
])('%s -> %s', (input, expected) => { ])('%s -> %s', (input, expected) => {
@ -95,24 +95,52 @@ const tempDir = path.join(
); );
describe('Version from file test', () => { describe('Version from file test', () => {
it.each([getVersionInputFromPlainFile, getVersionInputFromFile])( it.each([getVersionsInputFromPlainFile, getVersionInputFromFile])(
'Version from plain file test', 'Version from plain file test',
async _fn => { async _fn => {
await io.mkdirP(tempDir); await io.mkdirP(tempDir);
const pythonVersionFileName = 'python-version.file'; const pythonVersionFileName = 'python-version.file';
const pythonVersionFilePath = path.join(tempDir, pythonVersionFileName); const pythonVersionFilePath = path.join(tempDir, pythonVersionFileName);
const pythonVersionFileContent = '3.7'; const pythonVersionFileContent = '3.13';
fs.writeFileSync(pythonVersionFilePath, pythonVersionFileContent); fs.writeFileSync(pythonVersionFilePath, pythonVersionFileContent);
expect(_fn(pythonVersionFilePath)).toEqual([pythonVersionFileContent]); expect(_fn(pythonVersionFilePath)).toEqual([pythonVersionFileContent]);
} }
); );
it.each([getVersionsInputFromPlainFile, getVersionInputFromFile])(
'Versions from multiline plain file test',
async _fn => {
await io.mkdirP(tempDir);
const pythonVersionFileName = 'python-version.file';
const pythonVersionFilePath = path.join(tempDir, pythonVersionFileName);
const pythonVersionFileContent = '3.13\r\n3.12';
fs.writeFileSync(pythonVersionFilePath, pythonVersionFileContent);
expect(_fn(pythonVersionFilePath)).toEqual(['3.13', '3.12']);
}
);
it.each([getVersionsInputFromPlainFile, getVersionInputFromFile])(
'Version from complex plain file test',
async _fn => {
await io.mkdirP(tempDir);
const pythonVersionFileName = 'python-version.file';
const pythonVersionFilePath = path.join(tempDir, pythonVersionFileName);
const pythonVersionFileContent =
'3.13/envs/virtualenv\r# 3.12\n3.11\r\n3.10\r\n 3.9 \r\n';
fs.writeFileSync(pythonVersionFilePath, pythonVersionFileContent);
expect(_fn(pythonVersionFilePath)).toEqual([
'3.13',
'3.11',
'3.10',
'3.9'
]);
}
);
it.each([getVersionInputFromTomlFile, getVersionInputFromFile])( it.each([getVersionInputFromTomlFile, getVersionInputFromFile])(
'Version from standard pyproject.toml test', 'Version from standard pyproject.toml test',
async _fn => { async _fn => {
await io.mkdirP(tempDir); await io.mkdirP(tempDir);
const pythonVersionFileName = 'pyproject.toml'; const pythonVersionFileName = 'pyproject.toml';
const pythonVersionFilePath = path.join(tempDir, pythonVersionFileName); const pythonVersionFilePath = path.join(tempDir, pythonVersionFileName);
const pythonVersion = '>=3.7.0'; const pythonVersion = '>=3.13.0';
const pythonVersionFileContent = `[project]\nrequires-python = "${pythonVersion}"`; const pythonVersionFileContent = `[project]\nrequires-python = "${pythonVersion}"`;
fs.writeFileSync(pythonVersionFilePath, pythonVersionFileContent); fs.writeFileSync(pythonVersionFilePath, pythonVersionFileContent);
expect(_fn(pythonVersionFilePath)).toEqual([pythonVersion]); expect(_fn(pythonVersionFilePath)).toEqual([pythonVersion]);
@ -124,7 +152,7 @@ describe('Version from file test', () => {
await io.mkdirP(tempDir); await io.mkdirP(tempDir);
const pythonVersionFileName = 'pyproject.toml'; const pythonVersionFileName = 'pyproject.toml';
const pythonVersionFilePath = path.join(tempDir, pythonVersionFileName); const pythonVersionFilePath = path.join(tempDir, pythonVersionFileName);
const pythonVersion = '>=3.7.0'; const pythonVersion = '>=3.13.0';
const pythonVersionFileContent = `[tool.poetry.dependencies]\npython = "${pythonVersion}"`; const pythonVersionFileContent = `[tool.poetry.dependencies]\npython = "${pythonVersion}"`;
fs.writeFileSync(pythonVersionFilePath, pythonVersionFileContent); fs.writeFileSync(pythonVersionFilePath, pythonVersionFileContent);
expect(_fn(pythonVersionFilePath)).toEqual([pythonVersion]); expect(_fn(pythonVersionFilePath)).toEqual([pythonVersion]);
@ -145,9 +173,9 @@ describe('Version from file test', () => {
async _fn => { async _fn => {
const toolVersionFileName = '.tool-versions'; const toolVersionFileName = '.tool-versions';
const toolVersionFilePath = path.join(tempDir, toolVersionFileName); const toolVersionFilePath = path.join(tempDir, toolVersionFileName);
const toolVersionContent = 'python 3.9.10\nnodejs 16'; const toolVersionContent = 'python 3.13.2\nnodejs 16';
fs.writeFileSync(toolVersionFilePath, toolVersionContent); fs.writeFileSync(toolVersionFilePath, toolVersionContent);
expect(_fn(toolVersionFilePath)).toEqual(['3.9.10']); expect(_fn(toolVersionFilePath)).toEqual(['3.13.2']);
} }
); );
@ -156,9 +184,9 @@ describe('Version from file test', () => {
async _fn => { async _fn => {
const toolVersionFileName = '.tool-versions'; const toolVersionFileName = '.tool-versions';
const toolVersionFilePath = path.join(tempDir, toolVersionFileName); const toolVersionFilePath = path.join(tempDir, toolVersionFileName);
const toolVersionContent = '# python 3.8\npython 3.9'; const toolVersionContent = '# python 3.13\npython 3.12';
fs.writeFileSync(toolVersionFilePath, toolVersionContent); fs.writeFileSync(toolVersionFilePath, toolVersionContent);
expect(_fn(toolVersionFilePath)).toEqual(['3.9']); expect(_fn(toolVersionFilePath)).toEqual(['3.12']);
} }
); );
@ -167,9 +195,9 @@ describe('Version from file test', () => {
async _fn => { async _fn => {
const toolVersionFileName = '.tool-versions'; const toolVersionFileName = '.tool-versions';
const toolVersionFilePath = path.join(tempDir, toolVersionFileName); const toolVersionFilePath = path.join(tempDir, toolVersionFileName);
const toolVersionContent = ' python 3.10 '; const toolVersionContent = ' python 3.13 ';
fs.writeFileSync(toolVersionFilePath, toolVersionContent); fs.writeFileSync(toolVersionFilePath, toolVersionContent);
expect(_fn(toolVersionFilePath)).toEqual(['3.10']); expect(_fn(toolVersionFilePath)).toEqual(['3.13']);
} }
); );
@ -178,9 +206,9 @@ describe('Version from file test', () => {
async _fn => { async _fn => {
const toolVersionFileName = '.tool-versions'; const toolVersionFileName = '.tool-versions';
const toolVersionFilePath = path.join(tempDir, toolVersionFileName); const toolVersionFilePath = path.join(tempDir, toolVersionFileName);
const toolVersionContent = 'python v3.9.10'; const toolVersionContent = 'python v3.13.2';
fs.writeFileSync(toolVersionFilePath, toolVersionContent); fs.writeFileSync(toolVersionFilePath, toolVersionContent);
expect(_fn(toolVersionFilePath)).toEqual(['3.9.10']); expect(_fn(toolVersionFilePath)).toEqual(['3.13.2']);
} }
); );
@ -189,9 +217,9 @@ describe('Version from file test', () => {
async _fn => { async _fn => {
const toolVersionFileName = '.tool-versions'; const toolVersionFileName = '.tool-versions';
const toolVersionFilePath = path.join(tempDir, toolVersionFileName); const toolVersionFilePath = path.join(tempDir, toolVersionFileName);
const toolVersionContent = 'python pypy3.10-7.3.14'; const toolVersionContent = 'python pypy3.10-7.3.19';
fs.writeFileSync(toolVersionFilePath, toolVersionContent); fs.writeFileSync(toolVersionFilePath, toolVersionContent);
expect(_fn(toolVersionFilePath)).toEqual(['pypy3.10-7.3.14']); expect(_fn(toolVersionFilePath)).toEqual(['pypy3.10-7.3.19']);
} }
); );

View File

@ -29,6 +29,8 @@ inputs:
freethreaded: freethreaded:
description: "When 'true', use the freethreaded version of Python." description: "When 'true', use the freethreaded version of Python."
default: false default: false
pip-version:
description: "Used to specify the version of pip to install with the Python. Supported format: major[.minor][.patch]."
outputs: outputs:
python-version: python-version:
description: "The installed Python or PyPy version. Useful when given a version range as input." description: "The installed Python or PyPy version. Useful when given a version range as input."

210
dist/setup/index.js vendored
View File

@ -10251,7 +10251,11 @@ function copyFile(srcFile, destFile, force) {
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k; if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) { }) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k; if (k2 === undefined) k2 = k;
o[k2] = m[k]; o[k2] = m[k];
@ -10264,7 +10268,7 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
var __importStar = (this && this.__importStar) || function (mod) { var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod; if (mod && mod.__esModule) return mod;
var result = {}; var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod); __setModuleDefault(result, mod);
return result; return result;
}; };
@ -10294,11 +10298,11 @@ function _findMatch(versionSpec, stable, candidates, archFilter) {
let file; let file;
for (const candidate of candidates) { for (const candidate of candidates) {
const version = candidate.version; const version = candidate.version;
core_1.debug(`check ${version} satisfies ${versionSpec}`); (0, core_1.debug)(`check ${version} satisfies ${versionSpec}`);
if (semver.satisfies(version, versionSpec) && if (semver.satisfies(version, versionSpec) &&
(!stable || candidate.stable === stable)) { (!stable || candidate.stable === stable)) {
file = candidate.files.find(item => { file = candidate.files.find(item => {
core_1.debug(`${item.arch}===${archFilter} && ${item.platform}===${platFilter}`); (0, core_1.debug)(`${item.arch}===${archFilter} && ${item.platform}===${platFilter}`);
let chk = item.arch === archFilter && item.platform === platFilter; let chk = item.arch === archFilter && item.platform === platFilter;
if (chk && item.platform_version) { if (chk && item.platform_version) {
const osVersion = module.exports._getOsVersion(); const osVersion = module.exports._getOsVersion();
@ -10312,7 +10316,7 @@ function _findMatch(versionSpec, stable, candidates, archFilter) {
return chk; return chk;
}); });
if (file) { if (file) {
core_1.debug(`matched ${candidate.version}`); (0, core_1.debug)(`matched ${candidate.version}`);
match = candidate; match = candidate;
break; break;
} }
@ -10350,10 +10354,7 @@ function _getOsVersion() {
if (parts.length === 2 && if (parts.length === 2 &&
(parts[0].trim() === 'VERSION_ID' || (parts[0].trim() === 'VERSION_ID' ||
parts[0].trim() === 'DISTRIB_RELEASE')) { parts[0].trim() === 'DISTRIB_RELEASE')) {
version = parts[1] version = parts[1].trim().replace(/^"/, '').replace(/"$/, '');
.trim()
.replace(/^"/, '')
.replace(/"$/, '');
break; break;
} }
} }
@ -10386,7 +10387,11 @@ exports._readLinuxVersionFile = _readLinuxVersionFile;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k; if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) { }) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k; if (k2 === undefined) k2 = k;
o[k2] = m[k]; o[k2] = m[k];
@ -10399,7 +10404,7 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
var __importStar = (this && this.__importStar) || function (mod) { var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod; if (mod && mod.__esModule) return mod;
var result = {}; var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod); __setModuleDefault(result, mod);
return result; return result;
}; };
@ -10476,7 +10481,11 @@ exports.RetryHelper = RetryHelper;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k; if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) { }) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k; if (k2 === undefined) k2 = k;
o[k2] = m[k]; o[k2] = m[k];
@ -10489,7 +10498,7 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
var __importStar = (this && this.__importStar) || function (mod) { var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod; if (mod && mod.__esModule) return mod;
var result = {}; var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod); __setModuleDefault(result, mod);
return result; return result;
}; };
@ -10502,13 +10511,11 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
step((generator = generator.apply(thisArg, _arguments || [])).next()); step((generator = generator.apply(thisArg, _arguments || [])).next());
}); });
}; };
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", ({ value: true })); Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.evaluateVersions = exports.isExplicitVersion = exports.findFromManifest = exports.getManifestFromRepo = exports.findAllVersions = exports.find = exports.cacheFile = exports.cacheDir = exports.extractZip = exports.extractXar = exports.extractTar = exports.extract7z = exports.downloadTool = exports.HTTPError = void 0; exports.evaluateVersions = exports.isExplicitVersion = exports.findFromManifest = exports.getManifestFromRepo = exports.findAllVersions = exports.find = exports.cacheFile = exports.cacheDir = exports.extractZip = exports.extractXar = exports.extractTar = exports.extract7z = exports.downloadTool = exports.HTTPError = void 0;
const core = __importStar(__nccwpck_require__(7484)); const core = __importStar(__nccwpck_require__(7484));
const io = __importStar(__nccwpck_require__(4994)); const io = __importStar(__nccwpck_require__(4994));
const crypto = __importStar(__nccwpck_require__(6982));
const fs = __importStar(__nccwpck_require__(9896)); const fs = __importStar(__nccwpck_require__(9896));
const mm = __importStar(__nccwpck_require__(8036)); const mm = __importStar(__nccwpck_require__(8036));
const os = __importStar(__nccwpck_require__(857)); const os = __importStar(__nccwpck_require__(857));
@ -10518,7 +10525,6 @@ const semver = __importStar(__nccwpck_require__(6193));
const stream = __importStar(__nccwpck_require__(2203)); const stream = __importStar(__nccwpck_require__(2203));
const util = __importStar(__nccwpck_require__(9023)); const util = __importStar(__nccwpck_require__(9023));
const assert_1 = __nccwpck_require__(2613); const assert_1 = __nccwpck_require__(2613);
const v4_1 = __importDefault(__nccwpck_require__(9021));
const exec_1 = __nccwpck_require__(5236); const exec_1 = __nccwpck_require__(5236);
const retry_helper_1 = __nccwpck_require__(7380); const retry_helper_1 = __nccwpck_require__(7380);
class HTTPError extends Error { class HTTPError extends Error {
@ -10543,7 +10549,7 @@ const userAgent = 'actions/tool-cache';
*/ */
function downloadTool(url, dest, auth, headers) { function downloadTool(url, dest, auth, headers) {
return __awaiter(this, void 0, void 0, function* () { return __awaiter(this, void 0, void 0, function* () {
dest = dest || path.join(_getTempDirectory(), v4_1.default()); dest = dest || path.join(_getTempDirectory(), crypto.randomUUID());
yield io.mkdirP(path.dirname(dest)); yield io.mkdirP(path.dirname(dest));
core.debug(`Downloading ${url}`); core.debug(`Downloading ${url}`);
core.debug(`Destination ${dest}`); core.debug(`Destination ${dest}`);
@ -10632,8 +10638,8 @@ function downloadToolAttempt(url, dest, auth, headers) {
*/ */
function extract7z(file, dest, _7zPath) { function extract7z(file, dest, _7zPath) {
return __awaiter(this, void 0, void 0, function* () { return __awaiter(this, void 0, void 0, function* () {
assert_1.ok(IS_WINDOWS, 'extract7z() not supported on current OS'); (0, assert_1.ok)(IS_WINDOWS, 'extract7z() not supported on current OS');
assert_1.ok(file, 'parameter "file" is required'); (0, assert_1.ok)(file, 'parameter "file" is required');
dest = yield _createExtractFolder(dest); dest = yield _createExtractFolder(dest);
const originalCwd = process.cwd(); const originalCwd = process.cwd();
process.chdir(dest); process.chdir(dest);
@ -10650,7 +10656,7 @@ function extract7z(file, dest, _7zPath) {
const options = { const options = {
silent: true silent: true
}; };
yield exec_1.exec(`"${_7zPath}"`, args, options); yield (0, exec_1.exec)(`"${_7zPath}"`, args, options);
} }
finally { finally {
process.chdir(originalCwd); process.chdir(originalCwd);
@ -10679,7 +10685,7 @@ function extract7z(file, dest, _7zPath) {
}; };
try { try {
const powershellPath = yield io.which('powershell', true); const powershellPath = yield io.which('powershell', true);
yield exec_1.exec(`"${powershellPath}"`, args, options); yield (0, exec_1.exec)(`"${powershellPath}"`, args, options);
} }
finally { finally {
process.chdir(originalCwd); process.chdir(originalCwd);
@ -10707,7 +10713,7 @@ function extractTar(file, dest, flags = 'xz') {
// Determine whether GNU tar // Determine whether GNU tar
core.debug('Checking tar --version'); core.debug('Checking tar --version');
let versionOutput = ''; let versionOutput = '';
yield exec_1.exec('tar --version', [], { yield (0, exec_1.exec)('tar --version', [], {
ignoreReturnCode: true, ignoreReturnCode: true,
silent: true, silent: true,
listeners: { listeners: {
@ -10743,7 +10749,7 @@ function extractTar(file, dest, flags = 'xz') {
args.push('--overwrite'); args.push('--overwrite');
} }
args.push('-C', destArg, '-f', fileArg); args.push('-C', destArg, '-f', fileArg);
yield exec_1.exec(`tar`, args); yield (0, exec_1.exec)(`tar`, args);
return dest; return dest;
}); });
} }
@ -10758,8 +10764,8 @@ exports.extractTar = extractTar;
*/ */
function extractXar(file, dest, flags = []) { function extractXar(file, dest, flags = []) {
return __awaiter(this, void 0, void 0, function* () { return __awaiter(this, void 0, void 0, function* () {
assert_1.ok(IS_MAC, 'extractXar() not supported on current OS'); (0, assert_1.ok)(IS_MAC, 'extractXar() not supported on current OS');
assert_1.ok(file, 'parameter "file" is required'); (0, assert_1.ok)(file, 'parameter "file" is required');
dest = yield _createExtractFolder(dest); dest = yield _createExtractFolder(dest);
let args; let args;
if (flags instanceof Array) { if (flags instanceof Array) {
@ -10773,7 +10779,7 @@ function extractXar(file, dest, flags = []) {
args.push('-v'); args.push('-v');
} }
const xarPath = yield io.which('xar', true); const xarPath = yield io.which('xar', true);
yield exec_1.exec(`"${xarPath}"`, _unique(args)); yield (0, exec_1.exec)(`"${xarPath}"`, _unique(args));
return dest; return dest;
}); });
} }
@ -10827,7 +10833,7 @@ function extractZipWin(file, dest) {
pwshCommand pwshCommand
]; ];
core.debug(`Using pwsh at path: ${pwshPath}`); core.debug(`Using pwsh at path: ${pwshPath}`);
yield exec_1.exec(`"${pwshPath}"`, args); yield (0, exec_1.exec)(`"${pwshPath}"`, args);
} }
else { else {
const powershellCommand = [ const powershellCommand = [
@ -10848,7 +10854,7 @@ function extractZipWin(file, dest) {
]; ];
const powershellPath = yield io.which('powershell', true); const powershellPath = yield io.which('powershell', true);
core.debug(`Using powershell at path: ${powershellPath}`); core.debug(`Using powershell at path: ${powershellPath}`);
yield exec_1.exec(`"${powershellPath}"`, args); yield (0, exec_1.exec)(`"${powershellPath}"`, args);
} }
}); });
} }
@ -10860,7 +10866,7 @@ function extractZipNix(file, dest) {
args.unshift('-q'); args.unshift('-q');
} }
args.unshift('-o'); //overwrite with -o, otherwise a prompt is shown which freezes the run args.unshift('-o'); //overwrite with -o, otherwise a prompt is shown which freezes the run
yield exec_1.exec(`"${unzipPath}"`, args, { cwd: dest }); yield (0, exec_1.exec)(`"${unzipPath}"`, args, { cwd: dest });
}); });
} }
/** /**
@ -11037,7 +11043,7 @@ function _createExtractFolder(dest) {
return __awaiter(this, void 0, void 0, function* () { return __awaiter(this, void 0, void 0, function* () {
if (!dest) { if (!dest) {
// create a temp dir // create a temp dir
dest = path.join(_getTempDirectory(), v4_1.default()); dest = path.join(_getTempDirectory(), crypto.randomUUID());
} }
yield io.mkdirP(dest); yield io.mkdirP(dest);
return dest; return dest;
@ -11110,7 +11116,7 @@ exports.evaluateVersions = evaluateVersions;
*/ */
function _getCacheDirectory() { function _getCacheDirectory() {
const cacheDirectory = process.env['RUNNER_TOOL_CACHE'] || ''; const cacheDirectory = process.env['RUNNER_TOOL_CACHE'] || '';
assert_1.ok(cacheDirectory, 'Expected RUNNER_TOOL_CACHE to be defined'); (0, assert_1.ok)(cacheDirectory, 'Expected RUNNER_TOOL_CACHE to be defined');
return cacheDirectory; return cacheDirectory;
} }
/** /**
@ -11118,7 +11124,7 @@ function _getCacheDirectory() {
*/ */
function _getTempDirectory() { function _getTempDirectory() {
const tempDirectory = process.env['RUNNER_TEMP'] || ''; const tempDirectory = process.env['RUNNER_TEMP'] || '';
assert_1.ok(tempDirectory, 'Expected RUNNER_TEMP to be defined'); (0, assert_1.ok)(tempDirectory, 'Expected RUNNER_TEMP to be defined');
return tempDirectory; return tempDirectory;
} }
/** /**
@ -88177,90 +88183,6 @@ module.exports = {
} }
/***/ }),
/***/ 8682:
/***/ ((module) => {
/**
* Convert array of 16 byte values to UUID string format of the form:
* XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
*/
var byteToHex = [];
for (var i = 0; i < 256; ++i) {
byteToHex[i] = (i + 0x100).toString(16).substr(1);
}
function bytesToUuid(buf, offset) {
var i = offset || 0;
var bth = byteToHex;
// join used to fix memory issue caused by concatenation: https://bugs.chromium.org/p/v8/issues/detail?id=3175#c4
return ([
bth[buf[i++]], bth[buf[i++]],
bth[buf[i++]], bth[buf[i++]], '-',
bth[buf[i++]], bth[buf[i++]], '-',
bth[buf[i++]], bth[buf[i++]], '-',
bth[buf[i++]], bth[buf[i++]], '-',
bth[buf[i++]], bth[buf[i++]],
bth[buf[i++]], bth[buf[i++]],
bth[buf[i++]], bth[buf[i++]]
]).join('');
}
module.exports = bytesToUuid;
/***/ }),
/***/ 1694:
/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => {
// Unique ID creation requires a high quality random # generator. In node.js
// this is pretty straight-forward - we use the crypto API.
var crypto = __nccwpck_require__(6982);
module.exports = function nodeRNG() {
return crypto.randomBytes(16);
};
/***/ }),
/***/ 9021:
/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => {
var rng = __nccwpck_require__(1694);
var bytesToUuid = __nccwpck_require__(8682);
function v4(options, buf, offset) {
var i = buf && offset || 0;
if (typeof(options) == 'string') {
buf = options === 'binary' ? new Array(16) : null;
options = null;
}
options = options || {};
var rnds = options.random || (options.rng || rng)();
// Per 4.4, set bits for version and `clock_seq_hi_and_reserved`
rnds[6] = (rnds[6] & 0x0f) | 0x40;
rnds[8] = (rnds[8] & 0x3f) | 0x80;
// Copy bytes to buffer, if provided
if (buf) {
for (var ii = 0; ii < 16; ++ii) {
buf[i + ii] = rnds[ii];
}
}
return buf || bytesToUuid(rnds);
}
module.exports = v4;
/***/ }), /***/ }),
/***/ 7125: /***/ 7125:
@ -96068,6 +95990,7 @@ const semver = __importStar(__nccwpck_require__(2088));
const installer = __importStar(__nccwpck_require__(1919)); const installer = __importStar(__nccwpck_require__(1919));
const core = __importStar(__nccwpck_require__(7484)); const core = __importStar(__nccwpck_require__(7484));
const tc = __importStar(__nccwpck_require__(3472)); const tc = __importStar(__nccwpck_require__(3472));
const exec = __importStar(__nccwpck_require__(5236));
// Python has "scripts" or "bin" directories where command-line tools that come with packages are installed. // 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. // This is where pip is, along with anything that pip installs.
// There is a separate directory for `pip install --user`. // There is a separate directory for `pip install --user`.
@ -96088,6 +96011,20 @@ function binDir(installDir) {
return path.join(installDir, 'bin'); return path.join(installDir, 'bin');
} }
} }
function installPip(pythonLocation) {
return __awaiter(this, void 0, void 0, function* () {
const pipVersion = core.getInput('pip-version');
// Validate pip-version format: major[.minor][.patch]
const versionRegex = /^\d+(\.\d+)?(\.\d+)?$/;
if (pipVersion && !versionRegex.test(pipVersion)) {
throw new Error(`Invalid pip-version "${pipVersion}". Please specify a version in the format major[.minor][.patch].`);
}
if (pipVersion) {
core.info(`pip-version input is specified. Installing pip version ${pipVersion}`);
yield exec.exec(`${pythonLocation}/python -m pip install --upgrade pip==${pipVersion} --disable-pip-version-check --no-warn-script-location`);
}
});
}
function useCpythonVersion(version, architecture, updateEnvironment, checkLatest, allowPreReleases, freethreaded) { function useCpythonVersion(version, architecture, updateEnvironment, checkLatest, allowPreReleases, freethreaded) {
return __awaiter(this, void 0, void 0, function* () { return __awaiter(this, void 0, void 0, function* () {
var _a; var _a;
@ -96183,6 +96120,8 @@ function useCpythonVersion(version, architecture, updateEnvironment, checkLatest
} }
core.setOutput('python-version', pythonVersion); core.setOutput('python-version', pythonVersion);
core.setOutput('python-path', pythonPath); core.setOutput('python-path', pythonPath);
const binaryPath = utils_1.IS_WINDOWS ? installDir : _binDir;
yield installPip(binaryPath);
return { impl: 'CPython', version: pythonVersion }; return { impl: 'CPython', version: pythonVersion };
}); });
} }
@ -96929,7 +96868,7 @@ function cacheDependencies(cache, pythonVersion) {
} }
function resolveVersionInputFromDefaultFile() { function resolveVersionInputFromDefaultFile() {
const couples = [ const couples = [
['.python-version', utils_1.getVersionInputFromPlainFile] ['.python-version', utils_1.getVersionsInputFromPlainFile]
]; ];
for (const [versionFile, _fn] of couples) { for (const [versionFile, _fn] of couples) {
(0, utils_1.logWarning)(`Neither 'python-version' nor 'python-version-file' inputs were supplied. Attempting to find '${versionFile}' file.`); (0, utils_1.logWarning)(`Neither 'python-version' nor 'python-version-file' inputs were supplied. Attempting to find '${versionFile}' file.`);
@ -97066,7 +97005,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod }; return (mod && mod.__esModule) ? mod : { "default": mod };
}; };
Object.defineProperty(exports, "__esModule", ({ value: true })); Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.getDownloadFileName = exports.getNextPageUrl = exports.getBinaryDirectory = exports.getVersionInputFromFile = exports.getVersionInputFromToolVersions = exports.getVersionInputFromPlainFile = exports.getVersionInputFromTomlFile = exports.getOSInfo = exports.getLinuxInfo = exports.logWarning = exports.isCacheFeatureAvailable = exports.isGhes = exports.validatePythonVersionFormatForPyPy = exports.writeExactPyPyVersionFile = exports.readExactPyPyVersionFile = exports.getPyPyVersionFromPath = exports.isNightlyKeyword = exports.validateVersion = exports.createSymlinkInFolder = exports.WINDOWS_PLATFORMS = exports.WINDOWS_ARCHS = exports.IS_MAC = exports.IS_LINUX = exports.IS_WINDOWS = void 0; exports.getDownloadFileName = exports.getNextPageUrl = exports.getBinaryDirectory = exports.getVersionInputFromFile = exports.getVersionInputFromToolVersions = exports.getVersionsInputFromPlainFile = exports.getVersionInputFromTomlFile = exports.getOSInfo = exports.getLinuxInfo = exports.logWarning = exports.isCacheFeatureAvailable = exports.isGhes = exports.validatePythonVersionFormatForPyPy = exports.writeExactPyPyVersionFile = exports.readExactPyPyVersionFile = exports.getPyPyVersionFromPath = exports.isNightlyKeyword = exports.validateVersion = exports.createSymlinkInFolder = exports.WINDOWS_PLATFORMS = exports.WINDOWS_ARCHS = exports.IS_MAC = exports.IS_LINUX = exports.IS_WINDOWS = void 0;
/* eslint no-unsafe-finally: "off" */ /* eslint no-unsafe-finally: "off" */
const cache = __importStar(__nccwpck_require__(5116)); const cache = __importStar(__nccwpck_require__(5116));
const core = __importStar(__nccwpck_require__(7484)); const core = __importStar(__nccwpck_require__(7484));
@ -97247,7 +97186,7 @@ function extractValue(obj, keys) {
* If none is present, returns an empty list. * If none is present, returns an empty list.
*/ */
function getVersionInputFromTomlFile(versionFile) { function getVersionInputFromTomlFile(versionFile) {
core.debug(`Trying to resolve version form ${versionFile}`); core.debug(`Trying to resolve version from ${versionFile}`);
let pyprojectFile = fs_1.default.readFileSync(versionFile, 'utf8'); let pyprojectFile = fs_1.default.readFileSync(versionFile, 'utf8');
// Normalize the line endings in the pyprojectFile // Normalize the line endings in the pyprojectFile
pyprojectFile = pyprojectFile.replace(/\r\n/g, '\n'); pyprojectFile = pyprojectFile.replace(/\r\n/g, '\n');
@ -97280,15 +97219,30 @@ function getVersionInputFromTomlFile(versionFile) {
} }
exports.getVersionInputFromTomlFile = getVersionInputFromTomlFile; exports.getVersionInputFromTomlFile = getVersionInputFromTomlFile;
/** /**
* Python version extracted from a plain text file. * Python versions extracted from a plain text file.
* - Resolves multiple versions from multiple lines.
* - Handles pyenv-virtualenv pointers (e.g. `3.10/envs/virtualenv`).
* - Ignores empty lines and lines starting with `#`
* - Trims whitespace.
*/ */
function getVersionInputFromPlainFile(versionFile) { function getVersionsInputFromPlainFile(versionFile) {
core.debug(`Trying to resolve version form ${versionFile}`); core.debug(`Trying to resolve versions from ${versionFile}`);
const version = fs_1.default.readFileSync(versionFile, 'utf8').trim(); const content = fs_1.default.readFileSync(versionFile, 'utf8').trim();
core.info(`Resolved ${versionFile} as ${version}`); const lines = content.split(/\r\n|\r|\n/);
return [version]; const versions = lines
.map(line => {
if (line.startsWith('#') || line.trim() === '') {
return undefined;
} }
exports.getVersionInputFromPlainFile = getVersionInputFromPlainFile; let version = line.trim();
version = version.split('/')[0];
return version;
})
.filter(version => version !== undefined);
core.info(`Resolved ${versionFile} as ${versions.join(', ')}`);
return versions;
}
exports.getVersionsInputFromPlainFile = getVersionsInputFromPlainFile;
/** /**
* Python version extracted from a .tool-versions file. * Python version extracted from a .tool-versions file.
*/ */
@ -97331,7 +97285,7 @@ function getVersionInputFromFile(versionFile) {
return getVersionInputFromToolVersions(versionFile); return getVersionInputFromToolVersions(versionFile);
} }
else { else {
return getVersionInputFromPlainFile(versionFile); return getVersionsInputFromPlainFile(versionFile);
} }
} }
exports.getVersionInputFromFile = getVersionInputFromFile; exports.getVersionInputFromFile = getVersionInputFromFile;

View File

@ -22,6 +22,7 @@
- [macOS](advanced-usage.md#macos) - [macOS](advanced-usage.md#macos)
- [Using `setup-python` on GHES](advanced-usage.md#using-setup-python-on-ghes) - [Using `setup-python` on GHES](advanced-usage.md#using-setup-python-on-ghes)
- [Allow pre-releases](advanced-usage.md#allow-pre-releases) - [Allow pre-releases](advanced-usage.md#allow-pre-releases)
- [Using the pip-version input](advanced-usage.md#using-the-pip-version-input)
## Using the `python-version` input ## Using the `python-version` input
@ -643,3 +644,22 @@ jobs:
- run: pipx run nox --error-on-missing-interpreters -s tests-${{ matrix.python_version }} - run: pipx run nox --error-on-missing-interpreters -s tests-${{ matrix.python_version }}
``` ```
## Using the pip-version input
The `pip-version` input allows you to specify the desired version of **Pip** to use with the standard Python version.
The version of Pip should be specified in the format `major`, `major.minor`, or `major.minor.patch` (for example: 25, 25.1, or 25.0.1).
```yaml
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.13'
pip-version: '25.0.1'
- name: Display Pip version
run: pip --version
```
> The `pip-version` input is supported only with standard Python versions. It is not available when using PyPy or GraalPy.
> Using a specific or outdated version of pip may result in compatibility or security issues and can cause job failures. For best practices and guidance, refer to the official [pip documentation](https://pip.pypa.io/en/stable/).

29
package-lock.json generated
View File

@ -15,7 +15,7 @@
"@actions/glob": "^0.5.0", "@actions/glob": "^0.5.0",
"@actions/http-client": "^2.2.3", "@actions/http-client": "^2.2.3",
"@actions/io": "^1.0.2", "@actions/io": "^1.0.2",
"@actions/tool-cache": "^2.0.1", "@actions/tool-cache": "^2.0.2",
"@iarna/toml": "^3.0.0", "@iarna/toml": "^3.0.0",
"semver": "^7.7.1" "semver": "^7.7.1"
}, },
@ -123,16 +123,16 @@
"integrity": "sha512-wi9JjgKLYS7U/z8PPbco+PvTb/nRWjeoFlJ1Qer83k/3C5PHQi28hiVdeE2kHXmIL99mQFawx8qt/JPjZilJ8Q==" "integrity": "sha512-wi9JjgKLYS7U/z8PPbco+PvTb/nRWjeoFlJ1Qer83k/3C5PHQi28hiVdeE2kHXmIL99mQFawx8qt/JPjZilJ8Q=="
}, },
"node_modules/@actions/tool-cache": { "node_modules/@actions/tool-cache": {
"version": "2.0.1", "version": "2.0.2",
"resolved": "https://registry.npmjs.org/@actions/tool-cache/-/tool-cache-2.0.1.tgz", "resolved": "https://registry.npmjs.org/@actions/tool-cache/-/tool-cache-2.0.2.tgz",
"integrity": "sha512-iPU+mNwrbA8jodY8eyo/0S/QqCKDajiR8OxWTnSk/SnYg0sj8Hp4QcUEVC1YFpHWXtrfbQrE13Jz4k4HXJQKcA==", "integrity": "sha512-fBhNNOWxuoLxztQebpOaWu6WeVmuwa77Z+DxIZ1B+OYvGkGQon6kTVg6Z32Cb13WCuw0szqonK+hh03mJV7Z6w==",
"license": "MIT",
"dependencies": { "dependencies": {
"@actions/core": "^1.2.6", "@actions/core": "^1.11.1",
"@actions/exec": "^1.0.0", "@actions/exec": "^1.0.0",
"@actions/http-client": "^2.0.1", "@actions/http-client": "^2.0.1",
"@actions/io": "^1.1.1", "@actions/io": "^1.1.1",
"semver": "^6.1.0", "semver": "^6.1.0"
"uuid": "^3.3.2"
} }
}, },
"node_modules/@actions/tool-cache/node_modules/semver": { "node_modules/@actions/tool-cache/node_modules/semver": {
@ -5268,9 +5268,9 @@
} }
}, },
"node_modules/undici": { "node_modules/undici": {
"version": "5.29.0", "version": "5.28.5",
"resolved": "https://registry.npmjs.org/undici/-/undici-5.29.0.tgz", "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.5.tgz",
"integrity": "sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg==", "integrity": "sha512-zICwjrDrcrUE0pyyJc1I2QzBkLM8FINsgOrt6WjA+BgajVq9Nxu2PbFFXUrAggLfDXlZGZBVZYw7WNV5KiBiBA==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@fastify/busboy": "^2.0.0" "@fastify/busboy": "^2.0.0"
@ -5323,15 +5323,6 @@
"punycode": "^2.1.0" "punycode": "^2.1.0"
} }
}, },
"node_modules/uuid": {
"version": "3.4.0",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==",
"deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.",
"bin": {
"uuid": "bin/uuid"
}
},
"node_modules/v8-to-istanbul": { "node_modules/v8-to-istanbul": {
"version": "9.1.3", "version": "9.1.3",
"resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.1.3.tgz", "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.1.3.tgz",

View File

@ -31,7 +31,7 @@
"@actions/glob": "^0.5.0", "@actions/glob": "^0.5.0",
"@actions/http-client": "^2.2.3", "@actions/http-client": "^2.2.3",
"@actions/io": "^1.0.2", "@actions/io": "^1.0.2",
"@actions/tool-cache": "^2.0.1", "@actions/tool-cache": "^2.0.2",
"@iarna/toml": "^3.0.0", "@iarna/toml": "^3.0.0",
"semver": "^7.7.1" "semver": "^7.7.1"
}, },

View File

@ -8,6 +8,7 @@ import * as installer from './install-python';
import * as core from '@actions/core'; import * as core from '@actions/core';
import * as tc from '@actions/tool-cache'; import * as tc from '@actions/tool-cache';
import * as exec from '@actions/exec';
// Python has "scripts" or "bin" directories where command-line tools that come with packages are installed. // 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. // This is where pip is, along with anything that pip installs.
@ -30,6 +31,27 @@ function binDir(installDir: string): string {
} }
} }
async function installPip(pythonLocation: string) {
const pipVersion = core.getInput('pip-version');
// Validate pip-version format: major[.minor][.patch]
const versionRegex = /^\d+(\.\d+)?(\.\d+)?$/;
if (pipVersion && !versionRegex.test(pipVersion)) {
throw new Error(
`Invalid pip-version "${pipVersion}". Please specify a version in the format major[.minor][.patch].`
);
}
if (pipVersion) {
core.info(
`pip-version input is specified. Installing pip version ${pipVersion}`
);
await exec.exec(
`${pythonLocation}/python -m pip install --upgrade pip==${pipVersion} --disable-pip-version-check --no-warn-script-location`
);
}
}
export async function useCpythonVersion( export async function useCpythonVersion(
version: string, version: string,
architecture: string, architecture: string,
@ -179,6 +201,9 @@ export async function useCpythonVersion(
core.setOutput('python-version', pythonVersion); core.setOutput('python-version', pythonVersion);
core.setOutput('python-path', pythonPath); core.setOutput('python-path', pythonPath);
const binaryPath = IS_WINDOWS ? installDir : _binDir;
await installPip(binaryPath);
return {impl: 'CPython', version: pythonVersion}; return {impl: 'CPython', version: pythonVersion};
} }

View File

@ -11,7 +11,7 @@ import {
logWarning, logWarning,
IS_MAC, IS_MAC,
getVersionInputFromFile, getVersionInputFromFile,
getVersionInputFromPlainFile getVersionsInputFromPlainFile
} from './utils'; } from './utils';
function isPyPyVersion(versionSpec: string) { function isPyPyVersion(versionSpec: string) {
@ -35,7 +35,7 @@ async function cacheDependencies(cache: string, pythonVersion: string) {
function resolveVersionInputFromDefaultFile(): string[] { function resolveVersionInputFromDefaultFile(): string[] {
const couples: [string, (versionFile: string) => string[]][] = [ const couples: [string, (versionFile: string) => string[]][] = [
['.python-version', getVersionInputFromPlainFile] ['.python-version', getVersionsInputFromPlainFile]
]; ];
for (const [versionFile, _fn] of couples) { for (const [versionFile, _fn] of couples) {
logWarning( logWarning(

View File

@ -228,7 +228,7 @@ function extractValue(obj: any, keys: string[]): string | undefined {
* If none is present, returns an empty list. * If none is present, returns an empty list.
*/ */
export function getVersionInputFromTomlFile(versionFile: string): string[] { export function getVersionInputFromTomlFile(versionFile: string): string[] {
core.debug(`Trying to resolve version form ${versionFile}`); core.debug(`Trying to resolve version from ${versionFile}`);
let pyprojectFile = fs.readFileSync(versionFile, 'utf8'); let pyprojectFile = fs.readFileSync(versionFile, 'utf8');
// Normalize the line endings in the pyprojectFile // Normalize the line endings in the pyprojectFile
@ -269,13 +269,28 @@ export function getVersionInputFromTomlFile(versionFile: string): string[] {
} }
/** /**
* Python version extracted from a plain text file. * Python versions extracted from a plain text file.
* - Resolves multiple versions from multiple lines.
* - Handles pyenv-virtualenv pointers (e.g. `3.10/envs/virtualenv`).
* - Ignores empty lines and lines starting with `#`
* - Trims whitespace.
*/ */
export function getVersionInputFromPlainFile(versionFile: string): string[] { export function getVersionsInputFromPlainFile(versionFile: string): string[] {
core.debug(`Trying to resolve version form ${versionFile}`); core.debug(`Trying to resolve versions from ${versionFile}`);
const version = fs.readFileSync(versionFile, 'utf8').trim(); const content = fs.readFileSync(versionFile, 'utf8').trim();
core.info(`Resolved ${versionFile} as ${version}`); const lines = content.split(/\r\n|\r|\n/);
return [version]; const versions = lines
.map(line => {
if (line.startsWith('#') || line.trim() === '') {
return undefined;
}
let version: string = line.trim();
version = version.split('/')[0];
return version;
})
.filter(version => version !== undefined) as string[];
core.info(`Resolved ${versionFile} as ${versions.join(', ')}`);
return versions;
} }
/** /**
@ -319,7 +334,7 @@ export function getVersionInputFromFile(versionFile: string): string[] {
} else if (versionFile.match('.tool-versions')) { } else if (versionFile.match('.tool-versions')) {
return getVersionInputFromToolVersions(versionFile); return getVersionInputFromToolVersions(versionFile);
} else { } else {
return getVersionInputFromPlainFile(versionFile); return getVersionsInputFromPlainFile(versionFile);
} }
} }