diff --git a/.github/workflows/e2e-cache-freethreaded.yml b/.github/workflows/e2e-cache-freethreaded.yml index d3beb5ba..e3b298cc 100644 --- a/.github/workflows/e2e-cache-freethreaded.yml +++ b/.github/workflows/e2e-cache-freethreaded.yml @@ -162,60 +162,3 @@ jobs: run: curl https://raw.githubusercontent.com/pypa/pipenv/master/get-pipenv.py | python - name: Install dependencies 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 diff --git a/.github/workflows/e2e-cache.yml b/.github/workflows/e2e-cache.yml index 76a8f8c5..a3c9a2ba 100644 --- a/.github/workflows/e2e-cache.yml +++ b/.github/workflows/e2e-cache.yml @@ -249,60 +249,3 @@ jobs: } - name: Run Python Script 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 diff --git a/.github/workflows/test-pypy.yml b/.github/workflows/test-pypy.yml index 6433b7c5..54466e52 100644 --- a/.github/workflows/test-pypy.yml +++ b/.github/workflows/test-pypy.yml @@ -88,6 +88,7 @@ jobs: - macos-13 - macos-14 - macos-15 + - windows-2019 - windows-2022 - windows-2025 - ubuntu-22.04 diff --git a/.licenses/npm/@actions/tool-cache.dep.yml b/.licenses/npm/@actions/tool-cache.dep.yml index 8a9ca1fd..fbf911fe 100644 --- a/.licenses/npm/@actions/tool-cache.dep.yml +++ b/.licenses/npm/@actions/tool-cache.dep.yml @@ -1,6 +1,6 @@ --- name: "@actions/tool-cache" -version: 2.0.2 +version: 2.0.1 type: npm summary: Actions tool-cache lib homepage: https://github.com/actions/toolkit/tree/main/packages/tool-cache diff --git a/.licenses/npm/uuid-3.4.0.dep.yml b/.licenses/npm/uuid-3.4.0.dep.yml new file mode 100644 index 00000000..45970fef --- /dev/null +++ b/.licenses/npm/uuid-3.4.0.dep.yml @@ -0,0 +1,39 @@ +--- +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 + Christoph Tavan + AJ ONeal + Vincent Voyer + Roman Shtylman diff --git a/.licenses/npm/uuid.dep.yml b/.licenses/npm/uuid-8.3.2.dep.yml similarity index 96% rename from .licenses/npm/uuid.dep.yml rename to .licenses/npm/uuid-8.3.2.dep.yml index 1aa22dea..bf84da08 100644 --- a/.licenses/npm/uuid.dep.yml +++ b/.licenses/npm/uuid-8.3.2.dep.yml @@ -3,7 +3,7 @@ name: uuid version: 8.3.2 type: npm summary: RFC4122 (v1, v4, and v5) UUIDs -homepage: +homepage: https://github.com/uuidjs/uuid#readme license: mit licenses: - sources: LICENSE.md diff --git a/README.md b/README.md index 8dc6d08f..a91964a7 100644 --- a/README.md +++ b/README.md @@ -108,7 +108,6 @@ 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` on GHES](docs/advanced-usage.md#using-setup-python-on-ghes) - [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 diff --git a/__tests__/setup-python.test.ts b/__tests__/setup-python.test.ts deleted file mode 100644 index bb27289d..00000000 --- a/__tests__/setup-python.test.ts +++ /dev/null @@ -1,149 +0,0 @@ -import * as core from '@actions/core'; -import * as fs from 'fs'; -import * as path from 'path'; -import {cacheDependencies} from '../src/setup-python'; -import {getCacheDistributor} from '../src/cache-distributions/cache-factory'; - -jest.mock('fs', () => { - const actualFs = jest.requireActual('fs'); - return { - ...actualFs, - promises: { - access: jest.fn(), - mkdir: jest.fn(), - copyFile: jest.fn(), - writeFile: jest.fn(), - appendFile: jest.fn() - } - }; -}); -jest.mock('@actions/core'); -jest.mock('../src/cache-distributions/cache-factory'); - -const mockedFsPromises = fs.promises as jest.Mocked; -const mockedCore = core as jest.Mocked; -const mockedGetCacheDistributor = getCacheDistributor as jest.Mock; - -describe('cacheDependencies', () => { - const mockRestoreCache = jest.fn(); - - beforeEach(() => { - jest.clearAllMocks(); - process.env.GITHUB_ACTION_PATH = '/github/action'; - process.env.GITHUB_WORKSPACE = '/github/workspace'; - - mockedCore.getInput.mockReturnValue('nested/deps.lock'); - - // Simulate file exists by resolving access without error - mockedFsPromises.access.mockImplementation(async p => { - const pathStr = typeof p === 'string' ? p : p.toString(); - if (pathStr === '/github/action/nested/deps.lock') { - return Promise.resolve(); - } - // Simulate directory doesn't exist to test mkdir - if (pathStr === path.dirname('/github/workspace/nested/deps.lock')) { - return Promise.reject(new Error('no dir')); - } - return Promise.resolve(); - }); - - // Simulate mkdir success - mockedFsPromises.mkdir.mockResolvedValue(undefined); - - // Simulate copyFile success - mockedFsPromises.copyFile.mockResolvedValue(undefined); - - mockedGetCacheDistributor.mockReturnValue({restoreCache: mockRestoreCache}); - }); - - it('copies the dependency file and resolves the path with directory structure', async () => { - await cacheDependencies('pip', '3.12'); - - const sourcePath = path.resolve('/github/action', 'nested/deps.lock'); - const targetPath = path.resolve('/github/workspace', 'nested/deps.lock'); - - expect(mockedFsPromises.access).toHaveBeenCalledWith( - sourcePath, - fs.constants.F_OK - ); - expect(mockedFsPromises.mkdir).toHaveBeenCalledWith( - path.dirname(targetPath), - { - recursive: true - } - ); - expect(mockedFsPromises.copyFile).toHaveBeenCalledWith( - sourcePath, - targetPath - ); - expect(mockedCore.info).toHaveBeenCalledWith( - `Copied ${sourcePath} to ${targetPath}` - ); - expect(mockedCore.info).toHaveBeenCalledWith( - `Resolved cache-dependency-path: nested/deps.lock` - ); - expect(mockRestoreCache).toHaveBeenCalled(); - }); - - it('warns if the dependency file does not exist', async () => { - // Simulate file does not exist by rejecting access - mockedFsPromises.access.mockRejectedValue(new Error('file not found')); - - await cacheDependencies('pip', '3.12'); - - expect(mockedCore.warning).toHaveBeenCalledWith( - expect.stringContaining('does not exist') - ); - expect(mockedFsPromises.copyFile).not.toHaveBeenCalled(); - expect(mockRestoreCache).toHaveBeenCalled(); - }); - - it('warns if file copy fails', async () => { - // Simulate copyFile failure - mockedFsPromises.copyFile.mockRejectedValue(new Error('copy failed')); - - await cacheDependencies('pip', '3.12'); - - expect(mockedCore.warning).toHaveBeenCalledWith( - expect.stringContaining('Failed to copy file') - ); - expect(mockRestoreCache).toHaveBeenCalled(); - }); - - it('skips path logic if no input is provided', async () => { - mockedCore.getInput.mockReturnValue(''); - - await cacheDependencies('pip', '3.12'); - - expect(mockedFsPromises.copyFile).not.toHaveBeenCalled(); - expect(mockedCore.warning).not.toHaveBeenCalled(); - expect(mockRestoreCache).toHaveBeenCalled(); - }); - - it('does not copy if dependency file is already inside the workspace but still sets resolved path', async () => { - // Simulate cacheDependencyPath inside workspace - mockedCore.getInput.mockReturnValue('deps.lock'); - - // Override sourcePath and targetPath to be equal - const actionPath = '/github/workspace'; // same path for action and workspace - process.env.GITHUB_ACTION_PATH = actionPath; - process.env.GITHUB_WORKSPACE = actionPath; - - // access resolves to simulate file exists - mockedFsPromises.access.mockResolvedValue(); - - await cacheDependencies('pip', '3.12'); - - const sourcePath = path.resolve(actionPath, 'deps.lock'); - const targetPath = sourcePath; // same path - - expect(mockedFsPromises.copyFile).not.toHaveBeenCalled(); - expect(mockedCore.info).toHaveBeenCalledWith( - `Dependency file is already inside the workspace: ${sourcePath}` - ); - expect(mockedCore.info).toHaveBeenCalledWith( - `Resolved cache-dependency-path: deps.lock` - ); - expect(mockRestoreCache).toHaveBeenCalled(); - }); -}); diff --git a/__tests__/utils.test.ts b/__tests__/utils.test.ts index 009749c6..6c0f0e13 100644 --- a/__tests__/utils.test.ts +++ b/__tests__/utils.test.ts @@ -10,7 +10,7 @@ import { validatePythonVersionFormatForPyPy, isCacheFeatureAvailable, getVersionInputFromFile, - getVersionsInputFromPlainFile, + getVersionInputFromPlainFile, getVersionInputFromTomlFile, getNextPageUrl, isGhes, @@ -24,10 +24,10 @@ jest.mock('@actions/core'); describe('validatePythonVersionFormatForPyPy', () => { it.each([ - ['3.12', true], - ['3.13', true], - ['3.12.x', false], - ['3.13.x', false], + ['3.6', true], + ['3.7', true], + ['3.6.x', false], + ['3.7.x', false], ['3.x', false], ['3', false] ])('%s -> %s', (input, expected) => { @@ -95,52 +95,24 @@ const tempDir = path.join( ); describe('Version from file test', () => { - it.each([getVersionsInputFromPlainFile, getVersionInputFromFile])( + it.each([getVersionInputFromPlainFile, getVersionInputFromFile])( 'Version from plain file test', async _fn => { await io.mkdirP(tempDir); const pythonVersionFileName = 'python-version.file'; const pythonVersionFilePath = path.join(tempDir, pythonVersionFileName); - const pythonVersionFileContent = '3.13'; + const pythonVersionFileContent = '3.7'; fs.writeFileSync(pythonVersionFilePath, 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])( 'Version from standard pyproject.toml test', async _fn => { await io.mkdirP(tempDir); const pythonVersionFileName = 'pyproject.toml'; const pythonVersionFilePath = path.join(tempDir, pythonVersionFileName); - const pythonVersion = '>=3.13.0'; + const pythonVersion = '>=3.7.0'; const pythonVersionFileContent = `[project]\nrequires-python = "${pythonVersion}"`; fs.writeFileSync(pythonVersionFilePath, pythonVersionFileContent); expect(_fn(pythonVersionFilePath)).toEqual([pythonVersion]); @@ -152,7 +124,7 @@ describe('Version from file test', () => { await io.mkdirP(tempDir); const pythonVersionFileName = 'pyproject.toml'; const pythonVersionFilePath = path.join(tempDir, pythonVersionFileName); - const pythonVersion = '>=3.13.0'; + const pythonVersion = '>=3.7.0'; const pythonVersionFileContent = `[tool.poetry.dependencies]\npython = "${pythonVersion}"`; fs.writeFileSync(pythonVersionFilePath, pythonVersionFileContent); expect(_fn(pythonVersionFilePath)).toEqual([pythonVersion]); @@ -173,9 +145,9 @@ describe('Version from file test', () => { async _fn => { const toolVersionFileName = '.tool-versions'; const toolVersionFilePath = path.join(tempDir, toolVersionFileName); - const toolVersionContent = 'python 3.13.2\nnodejs 16'; + const toolVersionContent = 'python 3.9.10\nnodejs 16'; fs.writeFileSync(toolVersionFilePath, toolVersionContent); - expect(_fn(toolVersionFilePath)).toEqual(['3.13.2']); + expect(_fn(toolVersionFilePath)).toEqual(['3.9.10']); } ); @@ -184,9 +156,9 @@ describe('Version from file test', () => { async _fn => { const toolVersionFileName = '.tool-versions'; const toolVersionFilePath = path.join(tempDir, toolVersionFileName); - const toolVersionContent = '# python 3.13\npython 3.12'; + const toolVersionContent = '# python 3.8\npython 3.9'; fs.writeFileSync(toolVersionFilePath, toolVersionContent); - expect(_fn(toolVersionFilePath)).toEqual(['3.12']); + expect(_fn(toolVersionFilePath)).toEqual(['3.9']); } ); @@ -195,9 +167,9 @@ describe('Version from file test', () => { async _fn => { const toolVersionFileName = '.tool-versions'; const toolVersionFilePath = path.join(tempDir, toolVersionFileName); - const toolVersionContent = ' python 3.13 '; + const toolVersionContent = ' python 3.10 '; fs.writeFileSync(toolVersionFilePath, toolVersionContent); - expect(_fn(toolVersionFilePath)).toEqual(['3.13']); + expect(_fn(toolVersionFilePath)).toEqual(['3.10']); } ); @@ -206,9 +178,9 @@ describe('Version from file test', () => { async _fn => { const toolVersionFileName = '.tool-versions'; const toolVersionFilePath = path.join(tempDir, toolVersionFileName); - const toolVersionContent = 'python v3.13.2'; + const toolVersionContent = 'python v3.9.10'; fs.writeFileSync(toolVersionFilePath, toolVersionContent); - expect(_fn(toolVersionFilePath)).toEqual(['3.13.2']); + expect(_fn(toolVersionFilePath)).toEqual(['3.9.10']); } ); @@ -217,9 +189,9 @@ describe('Version from file test', () => { async _fn => { const toolVersionFileName = '.tool-versions'; const toolVersionFilePath = path.join(tempDir, toolVersionFileName); - const toolVersionContent = 'python pypy3.10-7.3.19'; + const toolVersionContent = 'python pypy3.10-7.3.14'; fs.writeFileSync(toolVersionFilePath, toolVersionContent); - expect(_fn(toolVersionFilePath)).toEqual(['pypy3.10-7.3.19']); + expect(_fn(toolVersionFilePath)).toEqual(['pypy3.10-7.3.14']); } ); diff --git a/action.yml b/action.yml index e469b7b2..efa8de90 100644 --- a/action.yml +++ b/action.yml @@ -29,8 +29,6 @@ inputs: freethreaded: description: "When 'true', use the freethreaded version of Python." default: false - pip-version: - description: "Used to specify the version of pip to install with the Python. Supported format: major[.minor][.patch]." outputs: python-version: description: "The installed Python or PyPy version. Useful when given a version range as input." diff --git a/dist/setup/index.js b/dist/setup/index.js index c2f220c0..87c6a816 100644 --- a/dist/setup/index.js +++ b/dist/setup/index.js @@ -10251,11 +10251,7 @@ function copyFile(srcFile, destFile, force) { var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = 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); + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; @@ -10268,7 +10264,7 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? ( var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; - if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; @@ -10298,11 +10294,11 @@ function _findMatch(versionSpec, stable, candidates, archFilter) { let file; for (const candidate of candidates) { const version = candidate.version; - (0, core_1.debug)(`check ${version} satisfies ${versionSpec}`); + core_1.debug(`check ${version} satisfies ${versionSpec}`); if (semver.satisfies(version, versionSpec) && (!stable || candidate.stable === stable)) { file = candidate.files.find(item => { - (0, core_1.debug)(`${item.arch}===${archFilter} && ${item.platform}===${platFilter}`); + core_1.debug(`${item.arch}===${archFilter} && ${item.platform}===${platFilter}`); let chk = item.arch === archFilter && item.platform === platFilter; if (chk && item.platform_version) { const osVersion = module.exports._getOsVersion(); @@ -10316,7 +10312,7 @@ function _findMatch(versionSpec, stable, candidates, archFilter) { return chk; }); if (file) { - (0, core_1.debug)(`matched ${candidate.version}`); + core_1.debug(`matched ${candidate.version}`); match = candidate; break; } @@ -10354,7 +10350,10 @@ function _getOsVersion() { if (parts.length === 2 && (parts[0].trim() === 'VERSION_ID' || parts[0].trim() === 'DISTRIB_RELEASE')) { - version = parts[1].trim().replace(/^"/, '').replace(/"$/, ''); + version = parts[1] + .trim() + .replace(/^"/, '') + .replace(/"$/, ''); break; } } @@ -10387,11 +10386,7 @@ exports._readLinuxVersionFile = _readLinuxVersionFile; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = 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); + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; @@ -10404,7 +10399,7 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? ( var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; - if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; @@ -10481,11 +10476,7 @@ exports.RetryHelper = RetryHelper; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = 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); + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; @@ -10498,7 +10489,7 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? ( var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; - if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; @@ -10511,11 +10502,13 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge 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 })); 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 io = __importStar(__nccwpck_require__(4994)); -const crypto = __importStar(__nccwpck_require__(6982)); const fs = __importStar(__nccwpck_require__(9896)); const mm = __importStar(__nccwpck_require__(8036)); const os = __importStar(__nccwpck_require__(857)); @@ -10525,6 +10518,7 @@ const semver = __importStar(__nccwpck_require__(6193)); const stream = __importStar(__nccwpck_require__(2203)); const util = __importStar(__nccwpck_require__(9023)); const assert_1 = __nccwpck_require__(2613); +const v4_1 = __importDefault(__nccwpck_require__(9021)); const exec_1 = __nccwpck_require__(5236); const retry_helper_1 = __nccwpck_require__(7380); class HTTPError extends Error { @@ -10549,7 +10543,7 @@ const userAgent = 'actions/tool-cache'; */ function downloadTool(url, dest, auth, headers) { return __awaiter(this, void 0, void 0, function* () { - dest = dest || path.join(_getTempDirectory(), crypto.randomUUID()); + dest = dest || path.join(_getTempDirectory(), v4_1.default()); yield io.mkdirP(path.dirname(dest)); core.debug(`Downloading ${url}`); core.debug(`Destination ${dest}`); @@ -10638,8 +10632,8 @@ function downloadToolAttempt(url, dest, auth, headers) { */ function extract7z(file, dest, _7zPath) { return __awaiter(this, void 0, void 0, function* () { - (0, assert_1.ok)(IS_WINDOWS, 'extract7z() not supported on current OS'); - (0, assert_1.ok)(file, 'parameter "file" is required'); + assert_1.ok(IS_WINDOWS, 'extract7z() not supported on current OS'); + assert_1.ok(file, 'parameter "file" is required'); dest = yield _createExtractFolder(dest); const originalCwd = process.cwd(); process.chdir(dest); @@ -10656,7 +10650,7 @@ function extract7z(file, dest, _7zPath) { const options = { silent: true }; - yield (0, exec_1.exec)(`"${_7zPath}"`, args, options); + yield exec_1.exec(`"${_7zPath}"`, args, options); } finally { process.chdir(originalCwd); @@ -10685,7 +10679,7 @@ function extract7z(file, dest, _7zPath) { }; try { const powershellPath = yield io.which('powershell', true); - yield (0, exec_1.exec)(`"${powershellPath}"`, args, options); + yield exec_1.exec(`"${powershellPath}"`, args, options); } finally { process.chdir(originalCwd); @@ -10713,7 +10707,7 @@ function extractTar(file, dest, flags = 'xz') { // Determine whether GNU tar core.debug('Checking tar --version'); let versionOutput = ''; - yield (0, exec_1.exec)('tar --version', [], { + yield exec_1.exec('tar --version', [], { ignoreReturnCode: true, silent: true, listeners: { @@ -10749,7 +10743,7 @@ function extractTar(file, dest, flags = 'xz') { args.push('--overwrite'); } args.push('-C', destArg, '-f', fileArg); - yield (0, exec_1.exec)(`tar`, args); + yield exec_1.exec(`tar`, args); return dest; }); } @@ -10764,8 +10758,8 @@ exports.extractTar = extractTar; */ function extractXar(file, dest, flags = []) { return __awaiter(this, void 0, void 0, function* () { - (0, assert_1.ok)(IS_MAC, 'extractXar() not supported on current OS'); - (0, assert_1.ok)(file, 'parameter "file" is required'); + assert_1.ok(IS_MAC, 'extractXar() not supported on current OS'); + assert_1.ok(file, 'parameter "file" is required'); dest = yield _createExtractFolder(dest); let args; if (flags instanceof Array) { @@ -10779,7 +10773,7 @@ function extractXar(file, dest, flags = []) { args.push('-v'); } const xarPath = yield io.which('xar', true); - yield (0, exec_1.exec)(`"${xarPath}"`, _unique(args)); + yield exec_1.exec(`"${xarPath}"`, _unique(args)); return dest; }); } @@ -10833,7 +10827,7 @@ function extractZipWin(file, dest) { pwshCommand ]; core.debug(`Using pwsh at path: ${pwshPath}`); - yield (0, exec_1.exec)(`"${pwshPath}"`, args); + yield exec_1.exec(`"${pwshPath}"`, args); } else { const powershellCommand = [ @@ -10854,7 +10848,7 @@ function extractZipWin(file, dest) { ]; const powershellPath = yield io.which('powershell', true); core.debug(`Using powershell at path: ${powershellPath}`); - yield (0, exec_1.exec)(`"${powershellPath}"`, args); + yield exec_1.exec(`"${powershellPath}"`, args); } }); } @@ -10866,7 +10860,7 @@ function extractZipNix(file, dest) { args.unshift('-q'); } args.unshift('-o'); //overwrite with -o, otherwise a prompt is shown which freezes the run - yield (0, exec_1.exec)(`"${unzipPath}"`, args, { cwd: dest }); + yield exec_1.exec(`"${unzipPath}"`, args, { cwd: dest }); }); } /** @@ -11043,7 +11037,7 @@ function _createExtractFolder(dest) { return __awaiter(this, void 0, void 0, function* () { if (!dest) { // create a temp dir - dest = path.join(_getTempDirectory(), crypto.randomUUID()); + dest = path.join(_getTempDirectory(), v4_1.default()); } yield io.mkdirP(dest); return dest; @@ -11116,7 +11110,7 @@ exports.evaluateVersions = evaluateVersions; */ function _getCacheDirectory() { const cacheDirectory = process.env['RUNNER_TOOL_CACHE'] || ''; - (0, assert_1.ok)(cacheDirectory, 'Expected RUNNER_TOOL_CACHE to be defined'); + assert_1.ok(cacheDirectory, 'Expected RUNNER_TOOL_CACHE to be defined'); return cacheDirectory; } /** @@ -11124,7 +11118,7 @@ function _getCacheDirectory() { */ function _getTempDirectory() { const tempDirectory = process.env['RUNNER_TEMP'] || ''; - (0, assert_1.ok)(tempDirectory, 'Expected RUNNER_TEMP to be defined'); + assert_1.ok(tempDirectory, 'Expected RUNNER_TEMP to be defined'); return tempDirectory; } /** @@ -88183,6 +88177,90 @@ 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: @@ -95990,7 +96068,6 @@ const semver = __importStar(__nccwpck_require__(2088)); const installer = __importStar(__nccwpck_require__(1919)); const core = __importStar(__nccwpck_require__(7484)); 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. // This is where pip is, along with anything that pip installs. // There is a separate directory for `pip install --user`. @@ -96011,20 +96088,6 @@ function binDir(installDir) { 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) { return __awaiter(this, void 0, void 0, function* () { var _a; @@ -96120,8 +96183,6 @@ function useCpythonVersion(version, architecture, updateEnvironment, checkLatest } core.setOutput('python-version', pythonVersion); core.setOutput('python-path', pythonPath); - const binaryPath = utils_1.IS_WINDOWS ? installDir : _binDir; - yield installPip(binaryPath); return { impl: 'CPython', version: pythonVersion }; }); } @@ -96844,7 +96905,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.cacheDependencies = void 0; const core = __importStar(__nccwpck_require__(7484)); const finder = __importStar(__nccwpck_require__(6843)); const finderPyPy = __importStar(__nccwpck_require__(2625)); @@ -96863,53 +96923,13 @@ function isGraalPyVersion(versionSpec) { function cacheDependencies(cache, pythonVersion) { return __awaiter(this, void 0, void 0, function* () { const cacheDependencyPath = core.getInput('cache-dependency-path') || undefined; - let resolvedDependencyPath = undefined; - if (cacheDependencyPath) { - const actionPath = process.env.GITHUB_ACTION_PATH || ''; - const workspace = process.env.GITHUB_WORKSPACE || process.cwd(); - const sourcePath = path.resolve(actionPath, cacheDependencyPath); - const relativePath = path.relative(actionPath, sourcePath); - const targetPath = path.resolve(workspace, relativePath); - try { - const sourceExists = yield fs_1.default.promises - .access(sourcePath, fs_1.default.constants.F_OK) - .then(() => true) - .catch(() => false); - if (!sourceExists) { - core.warning(`The resolved cache-dependency-path does not exist: ${sourcePath}`); - } - else { - if (sourcePath !== targetPath) { - const targetDir = path.dirname(targetPath); - // Create target directory if it doesn't exist - yield fs_1.default.promises.mkdir(targetDir, { recursive: true }); - // Copy file asynchronously - yield fs_1.default.promises.copyFile(sourcePath, targetPath); - core.info(`Copied ${sourcePath} to ${targetPath}`); - } - else { - core.info(`Dependency file is already inside the workspace: ${sourcePath}`); - } - resolvedDependencyPath = path - .relative(workspace, targetPath) - .replace(/\\/g, '/'); - core.info(`Resolved cache-dependency-path: ${resolvedDependencyPath}`); - } - } - catch (error) { - core.warning(`Failed to copy file from ${sourcePath} to ${targetPath}: ${error}`); - } - } - // Pass resolvedDependencyPath if available, else fallback to original input - const dependencyPathForCache = resolvedDependencyPath !== null && resolvedDependencyPath !== void 0 ? resolvedDependencyPath : cacheDependencyPath; - const cacheDistributor = (0, cache_factory_1.getCacheDistributor)(cache, pythonVersion, dependencyPathForCache); + const cacheDistributor = (0, cache_factory_1.getCacheDistributor)(cache, pythonVersion, cacheDependencyPath); yield cacheDistributor.restoreCache(); }); } -exports.cacheDependencies = cacheDependencies; function resolveVersionInputFromDefaultFile() { const couples = [ - ['.python-version', utils_1.getVersionsInputFromPlainFile] + ['.python-version', utils_1.getVersionInputFromPlainFile] ]; 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.`); @@ -97046,7 +97066,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", ({ value: true })); -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; +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; /* eslint no-unsafe-finally: "off" */ const cache = __importStar(__nccwpck_require__(5116)); const core = __importStar(__nccwpck_require__(7484)); @@ -97227,7 +97247,7 @@ function extractValue(obj, keys) { * If none is present, returns an empty list. */ function getVersionInputFromTomlFile(versionFile) { - core.debug(`Trying to resolve version from ${versionFile}`); + core.debug(`Trying to resolve version form ${versionFile}`); let pyprojectFile = fs_1.default.readFileSync(versionFile, 'utf8'); // Normalize the line endings in the pyprojectFile pyprojectFile = pyprojectFile.replace(/\r\n/g, '\n'); @@ -97260,30 +97280,15 @@ function getVersionInputFromTomlFile(versionFile) { } exports.getVersionInputFromTomlFile = getVersionInputFromTomlFile; /** - * 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. + * Python version extracted from a plain text file. */ -function getVersionsInputFromPlainFile(versionFile) { - core.debug(`Trying to resolve versions from ${versionFile}`); - const content = fs_1.default.readFileSync(versionFile, 'utf8').trim(); - const lines = content.split(/\r\n|\r|\n/); - const versions = lines - .map(line => { - if (line.startsWith('#') || line.trim() === '') { - return undefined; - } - let version = line.trim(); - version = version.split('/')[0]; - return version; - }) - .filter(version => version !== undefined); - core.info(`Resolved ${versionFile} as ${versions.join(', ')}`); - return versions; +function getVersionInputFromPlainFile(versionFile) { + core.debug(`Trying to resolve version form ${versionFile}`); + const version = fs_1.default.readFileSync(versionFile, 'utf8').trim(); + core.info(`Resolved ${versionFile} as ${version}`); + return [version]; } -exports.getVersionsInputFromPlainFile = getVersionsInputFromPlainFile; +exports.getVersionInputFromPlainFile = getVersionInputFromPlainFile; /** * Python version extracted from a .tool-versions file. */ @@ -97326,7 +97331,7 @@ function getVersionInputFromFile(versionFile) { return getVersionInputFromToolVersions(versionFile); } else { - return getVersionsInputFromPlainFile(versionFile); + return getVersionInputFromPlainFile(versionFile); } } exports.getVersionInputFromFile = getVersionInputFromFile; diff --git a/docs/advanced-usage.md b/docs/advanced-usage.md index 96524823..72b35016 100644 --- a/docs/advanced-usage.md +++ b/docs/advanced-usage.md @@ -22,7 +22,6 @@ - [macOS](advanced-usage.md#macos) - [Using `setup-python` on GHES](advanced-usage.md#using-setup-python-on-ghes) - [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 @@ -412,7 +411,7 @@ steps: - run: pip install -e . # Or pip install -e '.[test]' to install test dependencies ``` -Note: cache-dependency-path supports files located outside the workspace root by copying them into the workspace to enable proper caching. + # Outputs and environment variables ## Outputs @@ -644,22 +643,3 @@ jobs: - 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/). \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index bfbb0d3c..6b05a120 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,7 +15,7 @@ "@actions/glob": "^0.5.0", "@actions/http-client": "^2.2.3", "@actions/io": "^1.0.2", - "@actions/tool-cache": "^2.0.2", + "@actions/tool-cache": "^2.0.1", "@iarna/toml": "^3.0.0", "semver": "^7.7.1" }, @@ -123,16 +123,16 @@ "integrity": "sha512-wi9JjgKLYS7U/z8PPbco+PvTb/nRWjeoFlJ1Qer83k/3C5PHQi28hiVdeE2kHXmIL99mQFawx8qt/JPjZilJ8Q==" }, "node_modules/@actions/tool-cache": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@actions/tool-cache/-/tool-cache-2.0.2.tgz", - "integrity": "sha512-fBhNNOWxuoLxztQebpOaWu6WeVmuwa77Z+DxIZ1B+OYvGkGQon6kTVg6Z32Cb13WCuw0szqonK+hh03mJV7Z6w==", - "license": "MIT", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@actions/tool-cache/-/tool-cache-2.0.1.tgz", + "integrity": "sha512-iPU+mNwrbA8jodY8eyo/0S/QqCKDajiR8OxWTnSk/SnYg0sj8Hp4QcUEVC1YFpHWXtrfbQrE13Jz4k4HXJQKcA==", "dependencies": { - "@actions/core": "^1.11.1", + "@actions/core": "^1.2.6", "@actions/exec": "^1.0.0", "@actions/http-client": "^2.0.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": { @@ -5323,6 +5323,15 @@ "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": { "version": "9.1.3", "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.1.3.tgz", diff --git a/package.json b/package.json index 1017bddd..a21ccb9f 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,7 @@ "@actions/glob": "^0.5.0", "@actions/http-client": "^2.2.3", "@actions/io": "^1.0.2", - "@actions/tool-cache": "^2.0.2", + "@actions/tool-cache": "^2.0.1", "@iarna/toml": "^3.0.0", "semver": "^7.7.1" }, diff --git a/src/find-python.ts b/src/find-python.ts index 88e530f4..ddb027cb 100644 --- a/src/find-python.ts +++ b/src/find-python.ts @@ -8,7 +8,6 @@ import * as installer from './install-python'; import * as core from '@actions/core'; 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. // This is where pip is, along with anything that pip installs. @@ -31,27 +30,6 @@ 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( version: string, architecture: string, @@ -201,9 +179,6 @@ export async function useCpythonVersion( core.setOutput('python-version', pythonVersion); core.setOutput('python-path', pythonPath); - const binaryPath = IS_WINDOWS ? installDir : _binDir; - await installPip(binaryPath); - return {impl: 'CPython', version: pythonVersion}; } diff --git a/src/setup-python.ts b/src/setup-python.ts index 106b415a..ab5931b8 100644 --- a/src/setup-python.ts +++ b/src/setup-python.ts @@ -11,7 +11,7 @@ import { logWarning, IS_MAC, getVersionInputFromFile, - getVersionsInputFromPlainFile + getVersionInputFromPlainFile } from './utils'; function isPyPyVersion(versionSpec: string) { @@ -22,69 +22,20 @@ function isGraalPyVersion(versionSpec: string) { return versionSpec.startsWith('graalpy'); } -export async function cacheDependencies(cache: string, pythonVersion: string) { +async function cacheDependencies(cache: string, pythonVersion: string) { const cacheDependencyPath = core.getInput('cache-dependency-path') || undefined; - let resolvedDependencyPath: string | undefined = undefined; - - if (cacheDependencyPath) { - const actionPath = process.env.GITHUB_ACTION_PATH || ''; - const workspace = process.env.GITHUB_WORKSPACE || process.cwd(); - - const sourcePath = path.resolve(actionPath, cacheDependencyPath); - const relativePath = path.relative(actionPath, sourcePath); - const targetPath = path.resolve(workspace, relativePath); - - try { - const sourceExists = await fs.promises - .access(sourcePath, fs.constants.F_OK) - .then(() => true) - .catch(() => false); - - if (!sourceExists) { - core.warning( - `The resolved cache-dependency-path does not exist: ${sourcePath}` - ); - } else { - if (sourcePath !== targetPath) { - const targetDir = path.dirname(targetPath); - // Create target directory if it doesn't exist - await fs.promises.mkdir(targetDir, {recursive: true}); - // Copy file asynchronously - await fs.promises.copyFile(sourcePath, targetPath); - core.info(`Copied ${sourcePath} to ${targetPath}`); - } else { - core.info( - `Dependency file is already inside the workspace: ${sourcePath}` - ); - } - - resolvedDependencyPath = path - .relative(workspace, targetPath) - .replace(/\\/g, '/'); - core.info(`Resolved cache-dependency-path: ${resolvedDependencyPath}`); - } - } catch (error) { - core.warning( - `Failed to copy file from ${sourcePath} to ${targetPath}: ${error}` - ); - } - } - - // Pass resolvedDependencyPath if available, else fallback to original input - const dependencyPathForCache = resolvedDependencyPath ?? cacheDependencyPath; - const cacheDistributor = getCacheDistributor( cache, pythonVersion, - dependencyPathForCache + cacheDependencyPath ); await cacheDistributor.restoreCache(); } function resolveVersionInputFromDefaultFile(): string[] { const couples: [string, (versionFile: string) => string[]][] = [ - ['.python-version', getVersionsInputFromPlainFile] + ['.python-version', getVersionInputFromPlainFile] ]; for (const [versionFile, _fn] of couples) { logWarning( diff --git a/src/utils.ts b/src/utils.ts index f39006d9..6274895e 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -228,7 +228,7 @@ function extractValue(obj: any, keys: string[]): string | undefined { * If none is present, returns an empty list. */ export function getVersionInputFromTomlFile(versionFile: string): string[] { - core.debug(`Trying to resolve version from ${versionFile}`); + core.debug(`Trying to resolve version form ${versionFile}`); let pyprojectFile = fs.readFileSync(versionFile, 'utf8'); // Normalize the line endings in the pyprojectFile @@ -269,28 +269,13 @@ export function getVersionInputFromTomlFile(versionFile: string): string[] { } /** - * 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. + * Python version extracted from a plain text file. */ -export function getVersionsInputFromPlainFile(versionFile: string): string[] { - core.debug(`Trying to resolve versions from ${versionFile}`); - const content = fs.readFileSync(versionFile, 'utf8').trim(); - const lines = content.split(/\r\n|\r|\n/); - 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; +export function getVersionInputFromPlainFile(versionFile: string): string[] { + core.debug(`Trying to resolve version form ${versionFile}`); + const version = fs.readFileSync(versionFile, 'utf8').trim(); + core.info(`Resolved ${versionFile} as ${version}`); + return [version]; } /** @@ -334,7 +319,7 @@ export function getVersionInputFromFile(versionFile: string): string[] { } else if (versionFile.match('.tool-versions')) { return getVersionInputFromToolVersions(versionFile); } else { - return getVersionsInputFromPlainFile(versionFile); + return getVersionInputFromPlainFile(versionFile); } }