diff --git a/.github/workflows/check-dist.yml b/.github/workflows/check-dist.yml index 4c3d69e22..6274fd288 100644 --- a/.github/workflows/check-dist.yml +++ b/.github/workflows/check-dist.yml @@ -21,7 +21,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Set Node.js 16.x uses: actions/setup-node@v3 @@ -45,7 +45,7 @@ jobs: id: diff # If index.js was different than expected, upload the expected version as an artifact - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v3 if: ${{ failure() && steps.diff.conclusion == 'failure' }} with: name: dist diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index c30fab46e..3ea240d83 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -18,11 +18,11 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v2 + uses: actions/checkout@v3 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@v1 + uses: github/codeql-action/init@v2 # Override language selection by uncommenting this and choosing your languages # with: # languages: go, javascript, csharp, python, cpp, java @@ -30,7 +30,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@v1 + uses: github/codeql-action/autobuild@v2 # ℹī¸ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -44,4 +44,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v1 + uses: github/codeql-action/analyze@v2 diff --git a/.github/workflows/licensed.yml b/.github/workflows/licensed.yml index a78560b8b..6f4cd9223 100644 --- a/.github/workflows/licensed.yml +++ b/.github/workflows/licensed.yml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-latest name: Check licenses steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Set Node.js 16.x uses: actions/setup-node@v3 with: diff --git a/.github/workflows/release-new-action-version.yml b/.github/workflows/release-new-action-version.yml index 955ced7e6..968c77fb3 100644 --- a/.github/workflows/release-new-action-version.yml +++ b/.github/workflows/release-new-action-version.yml @@ -21,7 +21,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Update the ${{ env.TAG_NAME }} tag - uses: actions/publish-action@v0.1.0 + uses: actions/publish-action@v0.2.0 with: source-tag: ${{ env.TAG_NAME }} - slack-webhook: ${{ secrets.SLACK_WEBHOOK }} \ No newline at end of file + slack-webhook: ${{ secrets.SLACK_WEBHOOK }} diff --git a/.github/workflows/test-pypy.yml b/.github/workflows/test-pypy.yml index e4a53bb2f..4800662e3 100644 --- a/.github/workflows/test-pypy.yml +++ b/.github/workflows/test-pypy.yml @@ -34,7 +34,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: setup-python ${{ matrix.pypy }} id: setup-python diff --git a/.github/workflows/workflow.yml b/.github/workflows/workflow.yml index 171e20552..5c8cc77f9 100644 --- a/.github/workflows/workflow.yml +++ b/.github/workflows/workflow.yml @@ -17,7 +17,7 @@ jobs: operating-system: [ubuntu-latest, windows-latest] steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Set Node.js 16.x uses: actions/setup-node@v3 diff --git a/README.md b/README.md index 84b2e642e..6e178e2f6 100644 --- a/README.md +++ b/README.md @@ -127,6 +127,26 @@ steps: - run: python my_script.py ``` +Download and set up the latest patch version of Python (for specified major & minor versions): +```yaml +steps: +- uses: actions/checkout@v3 +- uses: actions/setup-python@v4 + with: + python-version: '3.11-dev' +- run: python my_script.py +``` + +Download and set up the latest stable version of Python (for specified major version): +```yaml +steps: +- uses: actions/checkout@v3 +- uses: actions/setup-python@v4 + with: + python-version: '3.x' +- run: python my_script.py +``` + Download and set up PyPy: ```yaml @@ -320,6 +340,21 @@ steps: - run: pipenv install ``` +**Using a list of wildcard patterns to cache dependencies** +```yaml +steps: +- uses: actions/checkout@v3 +- uses: actions/setup-python@v4 + with: + python-version: '3.10' + cache: 'pip' + cache-dependency-path: | + **/setup.cfg + **/requirements*.txt +- run: pip install -e . -r subdirectory/requirements-dev.txt +``` + + # Environment variables The `update-environment` flag defaults to `true`. @@ -357,7 +392,7 @@ If you are experiencing problems while configuring Python on your self-hosted ru ### Linux - The Python packages that are downloaded from `actions/python-versions` are originally compiled from source in `/opt/hostedtoolcache/` with the [--enable-shared](https://github.com/actions/python-versions/blob/94f04ae6806c6633c82db94c6406a16e17decd5c/builders/ubuntu-python-builder.psm1#L35) flag, which makes them non-relocatable. -- Create an environment variable called `AGENT_TOOLSDIRECTORY` and set it to `/opt/hostedtoolcache`. This controls where the runner downloads and installs tools. +- By default runner downloads and install the tools to `/opt/hostedtoolcache`. The environment variable called `AGENT_TOOLSDIRECTORY` can be set to change this location. - In the same shell that your runner is using, type `export AGENT_TOOLSDIRECTORY=/opt/hostedtoolcache`. - A more permanent way of setting the environment variable is to create a `.env` file in the same directory as your runner and to add `AGENT_TOOLSDIRECTORY=/opt/hostedtoolcache`. This ensures the variable is always set if your runner is configured as a service. - Create a directory called `hostedtoolcache` inside `/opt`. diff --git a/__tests__/find-pypy.test.ts b/__tests__/find-pypy.test.ts index 04a27cf3c..3da9a226e 100644 --- a/__tests__/find-pypy.test.ts +++ b/__tests__/find-pypy.test.ts @@ -151,8 +151,11 @@ describe('findPyPyVersion', () => { let spyChmodSync: jest.SpyInstance; let spyCoreAddPath: jest.SpyInstance; let spyCoreExportVariable: jest.SpyInstance; + const env = process.env; beforeEach(() => { + jest.resetModules(); + process.env = {...env}; tcFind = jest.spyOn(tc, 'find'); tcFind.mockImplementation((tool: string, version: string) => { const semverRange = new semver.Range(version); @@ -214,6 +217,7 @@ describe('findPyPyVersion', () => { jest.resetAllMocks(); jest.clearAllMocks(); jest.restoreAllMocks(); + process.env = env; }); it('found PyPy in toolcache', async () => { diff --git a/__tests__/finder.test.ts b/__tests__/finder.test.ts index cf07a234d..3bd279f11 100644 --- a/__tests__/finder.test.ts +++ b/__tests__/finder.test.ts @@ -28,10 +28,12 @@ const manifestData = require('./data/versions-manifest.json'); describe('Finder tests', () => { let spyCoreAddPath: jest.SpyInstance; let spyCoreExportVariable: jest.SpyInstance; + const env = process.env; beforeEach(() => { + jest.resetModules(); + process.env = {...env}; spyCoreAddPath = jest.spyOn(core, 'addPath'); - spyCoreExportVariable = jest.spyOn(core, 'exportVariable'); }); @@ -39,6 +41,7 @@ describe('Finder tests', () => { jest.resetAllMocks(); jest.clearAllMocks(); jest.restoreAllMocks(); + process.env = env; }); it('Finds Python if it is installed', async () => { @@ -66,7 +69,6 @@ describe('Finder tests', () => { await finder.useCpythonVersion('3.x', 'x64', false); expect(spyCoreAddPath).not.toHaveBeenCalled(); expect(spyCoreExportVariable).not.toHaveBeenCalled(); - expect(spyCoreExportVariable).not.toHaveBeenCalled(); }); it('Finds stable Python version if it is not installed, but exists in the manifest', async () => { diff --git a/dist/setup/index.js b/dist/setup/index.js index af708d8a3..d55c6c52f 100644 --- a/dist/setup/index.js +++ b/dist/setup/index.js @@ -64845,15 +64845,6 @@ function useCpythonVersion(version, architecture, updateEnvironment) { `The list of all available versions can be found here: ${installer.MANIFEST_URL}` ].join(os.EOL)); } - if (utils_1.IS_LINUX) { - const libPath = process.env.LD_LIBRARY_PATH - ? `:${process.env.LD_LIBRARY_PATH}` - : ''; - const pyLibPath = path.join(installDir, 'lib'); - if (!libPath.split(':').includes(pyLibPath)) { - core.exportVariable('LD_LIBRARY_PATH', pyLibPath + libPath); - } - } const _binDir = binDir(installDir); const binaryExtension = utils_1.IS_WINDOWS ? '.exe' : ''; const pythonPath = path.join(utils_1.IS_WINDOWS ? installDir : _binDir, `python${binaryExtension}`); @@ -65241,6 +65232,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.logWarning = void 0; const core = __importStar(__nccwpck_require__(2186)); const finder = __importStar(__nccwpck_require__(9996)); const finderPyPy = __importStar(__nccwpck_require__(4003)); @@ -65263,29 +65255,39 @@ function resolveVersionInput() { let version = core.getInput('python-version'); let versionFile = core.getInput('python-version-file'); if (version && versionFile) { - core.warning('Both python-version and python-version-file inputs are specified, only python-version will be used'); + core.warning('Both python-version and python-version-file inputs are specified, only python-version will be used.'); } if (version) { return version; } - versionFile = versionFile || '.python-version'; - if (!fs_1.default.existsSync(versionFile)) { - throw new Error(`The specified python version file at: ${versionFile} does not exist`); + if (versionFile) { + if (!fs_1.default.existsSync(versionFile)) { + logWarning(`The specified python version file at: ${versionFile} doesn't exist. Attempting to find .python-version file.`); + versionFile = '.python-version'; + if (!fs_1.default.existsSync(versionFile)) { + throw new Error(`The ${versionFile} doesn't exist.`); + } + } + version = fs_1.default.readFileSync(versionFile, 'utf8'); + core.info(`Resolved ${versionFile} as ${version}`); + return version; } - version = fs_1.default.readFileSync(versionFile, 'utf8'); - core.info(`Resolved ${versionFile} as ${version}`); + core.warning("Neither 'python-version' nor 'python-version-file' inputs were supplied."); return version; } function run() { var _a; return __awaiter(this, void 0, void 0, function* () { - if ((_a = process.env.AGENT_TOOLSDIRECTORY) === null || _a === void 0 ? void 0 : _a.trim()) { - core.debug(`Python is expected to be installed into AGENT_TOOLSDIRECTORY=${process.env['AGENT_TOOLSDIRECTORY']}`); + // According to the README windows binaries do not require to be installed + // in the specific location, but Mac and Linux do + if (!utils_1.IS_WINDOWS && !((_a = process.env.AGENT_TOOLSDIRECTORY) === null || _a === void 0 ? void 0 : _a.trim())) { + if (utils_1.IS_LINUX) + process.env['AGENT_TOOLSDIRECTORY'] = '/opt/hostedtoolcache'; + else + process.env['AGENT_TOOLSDIRECTORY'] = '/Users/runner/hostedtoolcache'; process.env['RUNNER_TOOL_CACHE'] = process.env['AGENT_TOOLSDIRECTORY']; } - else { - core.debug(`Python is expected to be installed into RUNNER_TOOL_CACHE==${process.env['RUNNER_TOOL_CACHE']}`); - } + core.debug(`Python is expected to be installed into RUNNER_TOOL_CACHE=${process.env['RUNNER_TOOL_CACHE']}`); try { const version = resolveVersionInput(); if (version) { @@ -65318,6 +65320,11 @@ function run() { } }); } +function logWarning(message) { + const warningPrefix = '[warning]'; + core.info(`${warningPrefix}${message}`); +} +exports.logWarning = logWarning; run(); diff --git a/src/find-python.ts b/src/find-python.ts index 8c085d61a..e1add9533 100644 --- a/src/find-python.ts +++ b/src/find-python.ts @@ -70,17 +70,6 @@ export async function useCpythonVersion( ); } - if (IS_LINUX) { - const libPath = process.env.LD_LIBRARY_PATH - ? `:${process.env.LD_LIBRARY_PATH}` - : ''; - const pyLibPath = path.join(installDir, 'lib'); - - if (!libPath.split(':').includes(pyLibPath)) { - core.exportVariable('LD_LIBRARY_PATH', pyLibPath + libPath); - } - } - const _binDir = binDir(installDir); const binaryExtension = IS_WINDOWS ? '.exe' : ''; const pythonPath = path.join( diff --git a/src/setup-python.ts b/src/setup-python.ts index a7728714d..db17735b4 100644 --- a/src/setup-python.ts +++ b/src/setup-python.ts @@ -5,7 +5,7 @@ import * as path from 'path'; import * as os from 'os'; import fs from 'fs'; import {getCacheDistributor} from './cache-distributions/cache-factory'; -import {isCacheFeatureAvailable} from './utils'; +import {isCacheFeatureAvailable, IS_LINUX, IS_WINDOWS} from './utils'; function isPyPyVersion(versionSpec: string) { return versionSpec.startsWith('pypy'); @@ -28,7 +28,7 @@ function resolveVersionInput(): string { if (version && versionFile) { core.warning( - 'Both python-version and python-version-file inputs are specified, only python-version will be used' + 'Both python-version and python-version-file inputs are specified, only python-version will be used.' ); } @@ -36,29 +36,41 @@ function resolveVersionInput(): string { return version; } - versionFile = versionFile || '.python-version'; - if (!fs.existsSync(versionFile)) { - throw new Error( - `The specified python version file at: ${versionFile} does not exist` - ); + if (versionFile) { + if (!fs.existsSync(versionFile)) { + logWarning( + `The specified python version file at: ${versionFile} doesn't exist. Attempting to find .python-version file.` + ); + versionFile = '.python-version'; + if (!fs.existsSync(versionFile)) { + throw new Error(`The ${versionFile} doesn't exist.`); + } + } + + version = fs.readFileSync(versionFile, 'utf8'); + core.info(`Resolved ${versionFile} as ${version}`); + + return version; } - version = fs.readFileSync(versionFile, 'utf8'); - core.info(`Resolved ${versionFile} as ${version}`); + + core.warning( + "Neither 'python-version' nor 'python-version-file' inputs were supplied." + ); return version; } async function run() { - if (process.env.AGENT_TOOLSDIRECTORY?.trim()) { - core.debug( - `Python is expected to be installed into AGENT_TOOLSDIRECTORY=${process.env['AGENT_TOOLSDIRECTORY']}` - ); + // According to the README windows binaries do not require to be installed + // in the specific location, but Mac and Linux do + if (!IS_WINDOWS && !process.env.AGENT_TOOLSDIRECTORY?.trim()) { + if (IS_LINUX) process.env['AGENT_TOOLSDIRECTORY'] = '/opt/hostedtoolcache'; + else process.env['AGENT_TOOLSDIRECTORY'] = '/Users/runner/hostedtoolcache'; process.env['RUNNER_TOOL_CACHE'] = process.env['AGENT_TOOLSDIRECTORY']; - } else { - core.debug( - `Python is expected to be installed into RUNNER_TOOL_CACHE==${process.env['RUNNER_TOOL_CACHE']}` - ); } + core.debug( + `Python is expected to be installed into RUNNER_TOOL_CACHE=${process.env['RUNNER_TOOL_CACHE']}` + ); try { const version = resolveVersionInput(); if (version) { @@ -101,4 +113,9 @@ async function run() { } } +export function logWarning(message: string): void { + const warningPrefix = '[warning]'; + core.info(`${warningPrefix}${message}`); +} + run();