Compare commits

..

88 Commits

Author SHA1 Message Date
c4e89fac7e Improve readme for 3.x and 3.11-dev style python-version (#441) 2022-07-07 23:34:44 +02:00
0ad0f6a0a5 Merge pull request #452 from mayeut/fix-env
Remove duplicate code introduced in #440
2022-07-06 16:11:51 +02:00
f0bcf8be03 Merge pull request #456 from akx/patch-1
doc: Add multiple wildcards example to readme
2022-07-05 08:23:25 +02:00
af97157ae6 doc: Add multiple wildcards example to readme
Based on https://www.npmjs.com/package/@actions/glob (the library used for cache file globbing), newline-separating multiple patterns is accepted.
2022-07-04 12:24:58 +03:00
364e819741 Merge pull request #394 from akv-platform/v-sedoli/set-env-by-default
Assign default value of AGENT_TOOLSDIRECTORY if not set
2022-07-04 10:35:46 +02:00
782f81b91d Merge pull request #450 from IvanZosimov/ResolveVersionFix
Rearranged logic of the ResolveVersionInput()
2022-07-04 08:20:42 +02:00
2c9de4ed41 Remove duplicate code introduced in #440
#440 duplicated a block of code outside of `if (updateEnvironment) {` condition. This was probably an oversight when merging `main` back on the PR branch. The tests should have seen that `core.exportVariable` was being called and should have failed.
2022-07-02 11:50:48 +02:00
412091c1e0 Fix tests for update-environment==false 2022-07-02 11:50:48 +02:00
78a2330b92 Merge pull request #451 from dmitry-shibanov/fx-pipenv-python-version
Fx pipenv python version
2022-07-01 16:57:38 +02:00
96f494e18c trigger checks 2022-07-01 10:28:46 +02:00
099ed898be Optimize code 2022-06-30 18:42:04 +02:00
ccb7da8ae9 Change warning handler to default 2022-06-30 18:28:17 +02:00
5fbb819407 Optimize logic, rebuild action 2022-06-30 17:32:12 +02:00
82eddc4023 Add warning in case the versionFile isn't found 2022-06-30 16:34:29 +02:00
d97b6edda3 Fix typos 2022-06-30 16:25:46 +02:00
a6b01c4e40 Rebuild action with new changes 2022-06-30 16:22:51 +02:00
84087f5301 Rearrange logic 2022-06-30 16:21:14 +02:00
56f6060254 Fix naming 2022-06-30 14:41:09 +02:00
e29a7c89f6 Merge branch 'main' into ResolveVersionFix 2022-06-30 14:40:24 +02:00
5407bf6e69 Merge pull request #448 from IvanZosimov/CacheLibVersionUpdate
Add support for the @actions/cache library 3.0.0
2022-06-30 14:38:10 +02:00
41b91104ea Rebuild action 2022-06-30 14:26:40 +02:00
08116500d0 Rebuild action 2022-06-30 14:19:36 +02:00
161c3a68f0 Merge branch 'main' into CacheLibVersionUpdate 2022-06-30 14:18:06 +02:00
6733fc44ec Fix typo 2022-06-30 13:44:10 +02:00
afd3e72a25 Fix bug in resolveVersionInput() 2022-06-30 13:38:43 +02:00
ab6deb310f Merge pull request #440 from akv-platform/v-sdolin/issue-231
Add CMake hints
2022-06-30 08:56:04 +02:00
e629242ad4 Fix failed check 2022-06-30 07:56:08 +02:00
63086c6ded rebase main 2022-06-30 07:46:53 +02:00
69b94463f5 Add CMake hints 2022-06-30 07:43:57 +02:00
d7db8259d9 update pypy versions 2022-06-29 23:41:39 +02:00
27091d50ca minor fix 2022-06-29 20:38:02 +02:00
d358f9e3d7 fix check 2022-06-29 20:28:20 +02:00
1e52de40a4 fixing pipenv 2022-06-29 20:16:07 +02:00
2a20d9b5e0 add --python 3 2022-06-29 19:36:35 +02:00
766e8c6088 Fixing pipenv CI (#444)
* work on fixing pipenv

* change installation of pipenv to curl

* add different logs

* regenerate pipefile.lock

* change pipenv ci
2022-06-29 13:09:14 -04:00
00a5248c77 feature: add update-environment input (#411)
This option allows to specify if the action shall update environment variables (default) or not.
This allows to use the setup-python action in a composite action without side effect (except downloading/installing python if version is missing).
2022-06-29 11:00:51 -04:00
9c76df2a90 Build after rebase 2022-06-29 11:24:02 +02:00
958897304a Exclude windows from the fix 2022-06-29 11:22:07 +02:00
5d9fdcab75 Handle each OS in its own way 2022-06-29 11:22:07 +02:00
7199395312 Fix dist folder 2022-06-29 11:22:06 +02:00
5ad79022bc Change README 2022-06-29 11:21:25 +02:00
a8da2a66aa Use /opt/hostedtoolcache as default value AGENT_TOOLSDIRECTORY 2022-06-29 11:21:21 +02:00
c61bc3d08e Update licenses 2022-06-28 15:40:29 +02:00
01408cef88 Update cache-save.ts to support @actions/cache v3.0.0 lib
Made package.json and package-lock.json to use @actions/cache v3.0.0,
updated logic of the cache-save operation and added unit-tests
2022-06-28 15:17:50 +02:00
ffcd00020c Allow python-version-file to be a relative path (#431) 2022-06-20 16:04:59 +02:00
cf86e08a31 Revert "Pass the token input through on GHES (#427)" (#437)
This reverts commit 7e4abae443.
2022-06-16 11:08:06 -04:00
8fb4cbf7c8 README: Document pypy2 and pypy3 are deprecated (#265) 2022-06-15 14:03:21 +02:00
7e4abae443 Pass the token input through on GHES (#427)
* Pass the`token` input through on GHES

* Update the description for `token`

* Fix dist files

* Update package-lock.json

* Update README

* Fix indent level in YAML snippet

* secret names can't start with GITHUB_
2022-06-13 14:55:47 -04:00
813f9b1556 Merge pull request #423 from vsafonkin/v-vsafonkin/update-docs-v4
Update docs to v4 version
2022-06-09 10:56:24 +02:00
775367df99 Update docs to v4 version 2022-06-09 09:54:52 +02:00
d09bd5e600 fix: 3.x-dev can install a 3.y version (#417)
* fix: 3.x-dev can install a 3.y version

* Update README section for `-dev`
2022-06-08 14:58:05 +02:00
f72db171ab Made env.var pythonLocation consistent for Python and PyPy (#418)
* Change find-pypy.ts to redefine pythonLocaction environment variable

* Change README.md in order to add sentence about pythonLocation envvar

* Change sentence about pythonLocation envvar in README.md

* Rephrase the definition of pythonLocation env.var
2022-06-08 14:57:23 +02:00
53e15292cd add support for python-version-file (#336)
* add support for python-version-file

* Update action.yml

* update to v4, remove python-version default

* python-version overrides python-version-file, like setup-node
* checks '.python-version' by default if nothing else specified

* update tests, update to checkout@v3

* update build

* appease the linter

* remove old test for default python version

* revert readme changes

* update build
2022-06-02 16:37:57 +02:00
3f82819745 Fix output for prerelease version of poetry (#409) 2022-05-31 15:48:54 +02:00
397252c582 Update zeit/ncc to vercel/ncc (#393) 2022-05-31 12:56:29 +02:00
de977ad132 Merge pull request #412 from vsafonkin/v-vsafonkin/fix-poetry-cache-test
Fix e2e test for poetry cache and PyPy-3.7
2022-05-31 09:41:08 +02:00
22c6af91ce Change PyPy version to rebuild cache 2022-05-30 15:02:04 +02:00
081a3cf1a5 Merge pull request #405 from mayeut/interpreter-path
feature: add a `python-path` output
2022-05-25 11:02:46 +02:00
ff706563d7 feature: add a python-path output
Expose a `python-path` output containing the chosen Python executable path.
2022-05-24 21:02:03 +02:00
fff15a21cc Use pypyX.Y for PyPy python-version input (#349)
This versioning scheme is consistent with other
tools in the python ecosystem so it feels more natural
and allows better interaction with other tools.

fixes #346
2022-05-18 15:20:53 +02:00
c57f79353b Merge pull request #318 from neutrinoceros/document_dev_sugar
DOC: document -dev syntactic sugar
2022-05-06 13:03:34 +02:00
fd8f0a9fb8 Merge pull request #396 from akv-platform/v-sedoli/issue-241
Add warning if python version set to empty value
2022-05-04 15:21:43 +02:00
ae11205ec6 Merge pull request #400 from akv-platform/v-sedoli/pkg-config
set PKG_CONFIG_PATH environment var
2022-05-04 09:56:28 +02:00
8f73c1495f Formatting 2022-05-04 12:55:36 +05:00
e31727ce0a Improve warning message
Co-authored-by: Brian Cristante <33549821+brcrista@users.noreply.github.com>
2022-05-04 12:43:58 +05:00
a69041ca9f Successfully set up (#399) 2022-05-03 08:43:53 -04:00
5e1e05c694 set PKG_CONFIG_PATH environment var 2022-05-03 16:04:39 +05:00
0b56b76337 Improve wording 2022-04-29 12:49:49 +05:00
22daa094b8 Add generated files 2022-04-29 09:29:36 +05:00
ac4e858835 Add warning if python version set to empty value 2022-04-29 09:14:59 +05:00
1ce308808a Create missing pypyX.Y symlinks (#347)
`pypyX.Y.exe` executables are missing from PyPy archives on Windows before v7.3.9 (X.Y < 3.9)
`pypy2.7` symlinks are also missing from macOS/Linux PyPy archives before v7.3.9

relates to #346
2022-04-28 09:26:17 -04:00
c36dc43e7b Fix conflicts (#389) 2022-04-26 16:50:29 +02:00
4e6b5f40fc Merge pull request #384 from akv-platform/main
Add CODE_OF_CONDUCT
2022-04-21 08:59:12 +02:00
bcc31375e1 Throw exe on empty python-version 2022-04-21 08:19:23 +05:00
85a7430316 Merge branch 'actions:main' into main 2022-04-21 08:16:01 +05:00
6a4c6c1309 adjust documentation for python versions (#388) 2022-04-20 14:48:22 +02:00
3a63f5d525 Merge branch 'actions:main' into main 2022-04-20 12:09:38 +05:00
4a33d3c467 Merge pull request #387 from vsafonkin/v-vsafonkin/fix-readme-outdated-links
Fix virtual-env toolcache outdated links
2022-04-19 17:06:22 +03:00
abfd16b121 Fix virtual-env toolcache links 2022-04-19 15:21:09 +02:00
4176166af9 Add CODE_OF_CONDUCT 2022-04-18 16:04:39 +05:00
91712e11bb Merge pull request #338 from akv-demo/main
Force TOOLCACHE_ROOT to be equal AGENT_TOOLSDIRECTORY
2022-04-15 09:54:33 +02:00
98f2ad02fd Updated @actions/cache (#382) 2022-04-11 19:06:33 +05:30
5d6f0c8a87 ci(workflow): add 'npm' cache for actions/setup-node in .github/workflows (#379) 2022-04-07 12:16:24 +02:00
f4b66dec00 Merge branch 'actions:main' into main 2022-04-06 12:51:31 +05:00
65fe6a82c7 Use template literals instead of string concatenation 2022-02-21 05:26:51 +00:00
011c443f81 prettier 2022-02-17 19:21:13 +00:00
3250b5373c Force RUNNER_TOOL_CACHE to be equal AGENT_TOOLSDIRECTORY 2022-02-17 18:35:19 +00:00
0bcf8ef2ba DOC: document -dev syntactic sugar 2022-01-12 10:35:17 +01:00
31 changed files with 60543 additions and 58785 deletions

View File

@ -24,9 +24,10 @@ jobs:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- name: Set Node.js 16.x - name: Set Node.js 16.x
uses: actions/setup-node@v1 uses: actions/setup-node@v3
with: with:
node-version: 16.x node-version: 16.x
cache: npm
- name: Install dependencies - name: Install dependencies
run: npm ci run: npm ci

View File

@ -39,7 +39,7 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
os: [ubuntu-latest, windows-latest, macos-latest] os: [ubuntu-latest, windows-latest, macos-latest]
python-version: ['3.9', 'pypy-3.7-v7.x'] python-version: ['3.9', 'pypy-3.9-v7.x']
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- name: Setup Python - name: Setup Python
@ -48,11 +48,17 @@ jobs:
python-version: ${{ matrix.python-version }} python-version: ${{ matrix.python-version }}
cache: 'pipenv' cache: 'pipenv'
- name: Install pipenv - name: Install pipenv
run: pipx install pipenv run: curl https://raw.githubusercontent.com/pypa/pipenv/master/get-pipenv.py | python
- name: Install dependencies - name: Install dependencies
shell: pwsh
run: | run: |
cd __tests__/data mv ./__tests__/data/Pipfile.lock .
pipenv install --verbose mv ./__tests__/data/Pipfile .
if ("${{ matrix.python-version }}" -Match "pypy") {
pipenv install --keep-outdated --python pypy
} else {
pipenv install --keep-outdated --python ${{ matrix.python-version }}
}
python-poetry-dependencies-caching: python-poetry-dependencies-caching:
name: Test poetry (Python ${{ matrix.python-version}}, ${{ matrix.os }}) name: Test poetry (Python ${{ matrix.python-version}}, ${{ matrix.os }})
@ -61,7 +67,7 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
os: [ubuntu-latest, windows-latest, macos-latest] os: [ubuntu-latest, windows-latest, macos-latest]
python-version: ['3.9', 'pypy-3.7-v7.x'] python-version: ['3.9', 'pypy-3.8']
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- name: Install poetry - name: Install poetry
@ -102,7 +108,7 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
os: [ubuntu-latest, windows-latest, macos-latest] os: [ubuntu-latest, windows-latest, macos-latest]
python-version: ['3.9', 'pypy-3.7-v7.x'] python-version: ['3.9', 'pypy-3.9-v7.x']
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- name: Setup Python - name: Setup Python
@ -112,8 +118,14 @@ jobs:
cache: 'pipenv' cache: 'pipenv'
cache-dependency-path: '**/pipenv-requirements.txt' cache-dependency-path: '**/pipenv-requirements.txt'
- name: Install pipenv - name: Install pipenv
run: pipx install pipenv run: curl https://raw.githubusercontent.com/pypa/pipenv/master/get-pipenv.py | python
- name: Install dependencies - name: Install dependencies
shell: pwsh
run: | run: |
cd __tests__/data mv ./__tests__/data/Pipfile.lock .
pipenv install --verbose mv ./__tests__/data/Pipfile .
if ("${{ matrix.python-version }}" -Match "pypy") {
pipenv install --keep-outdated --python pypy
} else {
pipenv install --keep-outdated --python ${{ matrix.python-version }}
}

View File

@ -15,9 +15,10 @@ jobs:
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- name: Set Node.js 16.x - name: Set Node.js 16.x
uses: actions/setup-node@v2 uses: actions/setup-node@v3
with: with:
node-version: 16.x node-version: 16.x
cache: npm
- run: npm ci - run: npm ci
- name: Install licensed - name: Install licensed
run: | run: |

View File

@ -22,6 +22,7 @@ jobs:
pypy: pypy:
- 'pypy-2.7' - 'pypy-2.7'
- 'pypy-3.7' - 'pypy-3.7'
- 'pypy3.9'
- 'pypy-2.7-v7.3.4' - 'pypy-2.7-v7.3.4'
- 'pypy-3.7-v7.3.5' - 'pypy-3.7-v7.3.5'
- 'pypy-3.7-v7.3.4' - 'pypy-3.7-v7.3.4'
@ -29,18 +30,64 @@ jobs:
- 'pypy-3.7-v7.x' - 'pypy-3.7-v7.x'
- 'pypy-2.7-v7.3.4rc1' - 'pypy-2.7-v7.3.4rc1'
- 'pypy-3.7-nightly' - 'pypy-3.7-nightly'
- 'pypy3.8-v7.3.7'
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v2 uses: actions/checkout@v2
- name: setup-python ${{ matrix.pypy }} - name: setup-python ${{ matrix.pypy }}
id: setup-python
uses: ./ uses: ./
with: with:
python-version: ${{ matrix.pypy }} python-version: ${{ matrix.pypy }}
- name: Check python-path
run: ./__tests__/check-python-path.sh '${{ steps.setup-python.outputs.python-path }}'
shell: bash
- name: PyPy and Python version - name: PyPy and Python version
run: python --version run: python --version
- name: Run simple code - name: Run simple code
run: python -c 'import math; print(math.factorial(5))' run: python -c 'import math; print(math.factorial(5))'
- name: Assert PyPy is running
run: |
import platform
assert platform.python_implementation().lower() == "pypy"
shell: python
- name: Assert expected binaries (or symlinks) are present
run: |
EXECUTABLE=${{ matrix.pypy }}
EXECUTABLE=${EXECUTABLE/pypy-/pypy} # remove the first '-' in "pypy-X.Y" -> "pypyX.Y" to match executable name
EXECUTABLE=${EXECUTABLE%%-*} # remove any -* suffixe
${EXECUTABLE} --version
shell: bash
setup-pypy-noenv:
name: Setup PyPy ${{ matrix.pypy }} ${{ matrix.os }} (noenv)
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [macos-latest, windows-latest, ubuntu-18.04, ubuntu-latest]
pypy: ['pypy2.7', 'pypy3.7', 'pypy3.8', 'pypy3.9-nightly']
steps:
- name: Checkout
uses: actions/checkout@v3
- name: setup-python ${{ matrix.pypy }}
id: setup-python
uses: ./
with:
python-version: ${{ matrix.pypy }}
update-environment: false
- name: PyPy and Python version
run: ${{ steps.setup-python.outputs.python-path }} --version
- name: Run simple code
run: ${{ steps.setup-python.outputs.python-path }} -c 'import math; print(math.factorial(5))'

View File

@ -1,5 +1,5 @@
name: Validate Python e2e name: Validate Python e2e
on: on:
push: push:
branches: branches:
- main - main
@ -10,28 +10,9 @@ on:
- '**.md' - '**.md'
schedule: schedule:
- cron: 30 3 * * * - cron: 30 3 * * *
workflow_dispatch:
jobs: jobs:
default-version:
name: Setup default version
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [macos-latest, windows-latest, ubuntu-18.04, ubuntu-20.04]
steps:
- name: Checkout
uses: actions/checkout@v2
- name: setup default python
uses: ./
- name: Validate version
run: python --version
- name: Run simple python code
run: python -c 'import math; print(math.factorial(5))'
setup-versions-from-manifest: setup-versions-from-manifest:
name: Setup ${{ matrix.python }} ${{ matrix.os }} name: Setup ${{ matrix.python }} ${{ matrix.os }}
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
@ -42,13 +23,56 @@ jobs:
python: [3.5.4, 3.6.7, 3.7.5, 3.8.1] python: [3.5.4, 3.6.7, 3.7.5, 3.8.1]
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v2 uses: actions/checkout@v3
- name: setup-python ${{ matrix.python }} - name: setup-python ${{ matrix.python }}
id: setup-python
uses: ./ uses: ./
with: with:
python-version: ${{ matrix.python }} python-version: ${{ matrix.python }}
- name: Check python-path
run: ./__tests__/check-python-path.sh '${{ steps.setup-python.outputs.python-path }}'
shell: bash
- name: Validate version
run: |
$pythonVersion = (python --version)
if ("Python ${{ matrix.python }}" -ne "$pythonVersion"){
Write-Host "The current version is $pythonVersion; expected version is ${{ matrix.python }}"
exit 1
}
$pythonVersion
shell: pwsh
- name: Run simple code
run: python -c 'import math; print(math.factorial(5))'
setup-versions-from-file:
name: Setup ${{ matrix.python }} ${{ matrix.os }} version file
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [macos-latest, windows-latest, ubuntu-18.04, ubuntu-20.04]
python: [3.5.4, 3.6.7, 3.7.5, 3.8.1]
steps:
- name: Checkout
uses: actions/checkout@v3
- name: build-version-file ${{ matrix.python }}
run: echo ${{ matrix.python }} > .python-version
- name: setup-python ${{ matrix.python }}
id: setup-python
uses: ./
with:
python-version-file: '.python-version'
- name: Check python-path
run: ./__tests__/check-python-path.sh '${{ steps.setup-python.outputs.python-path }}'
shell: bash
- name: Validate version - name: Validate version
run: | run: |
$pythonVersion = (python --version) $pythonVersion = (python --version)
@ -71,13 +95,18 @@ jobs:
os: [macos-latest, windows-latest, ubuntu-18.04, ubuntu-20.04] os: [macos-latest, windows-latest, ubuntu-18.04, ubuntu-20.04]
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v2 uses: actions/checkout@v3
- name: setup-python 3.9.0-beta.4 - name: setup-python 3.9.0-beta.4
id: setup-python
uses: ./ uses: ./
with: with:
python-version: '3.9.0-beta.4' python-version: '3.9.0-beta.4'
- name: Check python-path
run: ./__tests__/check-python-path.sh '${{ steps.setup-python.outputs.python-path }}'
shell: bash
- name: Validate version - name: Validate version
run: | run: |
$pythonVersion = (python --version) $pythonVersion = (python --version)
@ -91,3 +120,55 @@ jobs:
- name: Run simple code - name: Run simple code
run: python -c 'import math; print(math.factorial(5))' run: python -c 'import math; print(math.factorial(5))'
setup-dev-version:
name: Setup 3.9-dev ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [macos-latest, windows-latest, ubuntu-latest]
steps:
- name: Checkout
uses: actions/checkout@v3
- name: setup-python 3.9-dev
id: setup-python
uses: ./
with:
python-version: '3.9-dev'
- name: Check python-path
run: ./__tests__/check-python-path.sh '${{ steps.setup-python.outputs.python-path }}'
shell: bash
- name: Validate version
run: ${{ startsWith(steps.setup-python.outputs.python-version, '3.9.') }}
shell: bash
- name: Run simple code
run: python -c 'import math; print(math.factorial(5))'
setup-versions-noenv:
name: Setup ${{ matrix.python }} ${{ matrix.os }} (noenv)
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [macos-latest, windows-latest, ubuntu-18.04, ubuntu-20.04]
python: ["3.7", "3.8", "3.9", "3.10"]
steps:
- name: Checkout
uses: actions/checkout@v3
- name: setup-python ${{ matrix.python }}
id: setup-python
uses: ./
with:
python-version: ${{ matrix.python }}
update-environment: false
- name: Python version
run: ${{ steps.setup-python.outputs.python-path }} --version
- name: Run simple code
run: ${{ steps.setup-python.outputs.python-path }} -c 'import math; print(math.factorial(5))'

View File

@ -20,9 +20,10 @@ jobs:
uses: actions/checkout@v2 uses: actions/checkout@v2
- name: Set Node.js 16.x - name: Set Node.js 16.x
uses: actions/setup-node@v1 uses: actions/setup-node@v3
with: with:
node-version: 16.x node-version: 16.x
cache: npm
- name: npm ci - name: npm ci
run: npm ci run: npm ci
@ -88,3 +89,13 @@ jobs:
python-version: 3.8.1 python-version: 3.8.1
- name: Verify 3.8.1 - name: Verify 3.8.1
run: python __tests__/verify-python.py 3.8.1 run: python __tests__/verify-python.py 3.8.1
- name: Run with setup-python 3.10
id: cp310
uses: ./
with:
python-version: "3.10"
- name: Verify 3.10
run: python __tests__/verify-python.py 3.10
- name: Run python-path sample 3.10
run: pipx run --python '${{ steps.cp310.outputs.python-path }}' nox --version

View File

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

View File

@ -1,6 +1,6 @@
--- ---
name: "@actions/core" name: "@actions/core"
version: 1.2.6 version: 1.7.0
type: npm type: npm
summary: Actions core lib summary: Actions core lib
homepage: https://github.com/actions/toolkit/tree/main/packages/core homepage: https://github.com/actions/toolkit/tree/main/packages/core

View File

@ -1,6 +1,6 @@
--- ---
name: "@actions/http-client" name: "@actions/http-client"
version: 1.0.8 version: 2.0.1
type: npm type: npm
summary: Actions Http Client summary: Actions Http Client
homepage: https://github.com/actions/http-client#readme homepage: https://github.com/actions/http-client#readme

View File

@ -0,0 +1,32 @@
---
name: "@actions/http-client"
version: 1.0.11
type: npm
summary: Actions Http Client
homepage: https://github.com/actions/http-client#readme
license: mit
licenses:
- sources: LICENSE
text: |
Actions Http Client for Node.js
Copyright (c) GitHub, Inc.
All rights reserved.
MIT License
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: []

76
CODE_OF_CONDUCT.md Normal file
View File

@ -0,0 +1,76 @@
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to make participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, sex characteristics, gender identity and expression,
level of experience, education, socio-economic status, nationality, personal
appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment
include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or
advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic
address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.
## Scope
This Code of Conduct applies within all project spaces, and it also applies when
an individual is representing the project or its community in public spaces.
Examples of representing a project or community include using an official
project e-mail address, posting via an official social media account, or acting
as an appointed representative at an online or offline event. Representation of
a project may be further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team at opensource+actions/setup-python@github.com. All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident.
Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see
https://www.contributor-covenant.org/faq

155
README.md
View File

@ -1,4 +1,4 @@
# setup-python V3 # setup-python V4
<p align="left"> <p align="left">
<a href="https://github.com/actions/setup-python"><img alt="GitHub Actions status" src="https://github.com/actions/setup-python/workflows/Main%20workflow/badge.svg"></a> <a href="https://github.com/actions/setup-python"><img alt="GitHub Actions status" src="https://github.com/actions/setup-python/workflows/Main%20workflow/badge.svg"></a>
@ -20,6 +20,7 @@ This action sets up a Python environment for use in actions by:
- Support for pre-release versions of Python. - Support for pre-release versions of Python.
- Support for installing any version of PyPy on-flight - Support for installing any version of PyPy on-flight
- Support for built-in caching of pip, pipenv and poetry dependencies - Support for built-in caching of pip, pipenv and poetry dependencies
- Support for `.python-version` file
# Usage # Usage
@ -29,13 +30,23 @@ Basic:
```yaml ```yaml
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- uses: actions/setup-python@v3 - uses: actions/setup-python@v4
with: with:
python-version: '3.x' # Version range or exact version of a Python version to use, using SemVer's version range syntax python-version: '3.x' # Version range or exact version of a Python version to use, using SemVer's version range syntax
architecture: 'x64' # optional x64 or x86. Defaults to x64 if not specified architecture: 'x64' # optional x64 or x86. Defaults to x64 if not specified
- run: python my_script.py - run: python my_script.py
``` ```
Read Python version from file:
```yaml
steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
with:
python-version-file: '.python-version' # Read python version from a file
- run: python my_script.py
```
Matrix Testing: Matrix Testing:
```yaml ```yaml
jobs: jobs:
@ -43,12 +54,12 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
strategy: strategy:
matrix: matrix:
python-version: [ '2.x', '3.x', 'pypy-2.7', 'pypy-3.7', 'pypy-3.8' ] python-version: [ '2.x', '3.x', 'pypy2.7', 'pypy3.7', 'pypy3.8' ]
name: Python ${{ matrix.python-version }} sample name: Python ${{ matrix.python-version }} sample
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- name: Set up Python - name: Set up Python
uses: actions/setup-python@v3 uses: actions/setup-python@v4
with: with:
python-version: ${{ matrix.python-version }} python-version: ${{ matrix.python-version }}
architecture: x64 architecture: x64
@ -63,7 +74,7 @@ jobs:
strategy: strategy:
matrix: matrix:
os: [ubuntu-latest, macos-latest, windows-latest] os: [ubuntu-latest, macos-latest, windows-latest]
python-version: ['2.7', '3.7', '3.8', '3.9', '3.10', 'pypy-2.7', 'pypy-3.8'] python-version: ['2.7', '3.7', '3.8', '3.9', '3.10', 'pypy2.7', 'pypy3.8']
exclude: exclude:
- os: macos-latest - os: macos-latest
python-version: '3.8' python-version: '3.8'
@ -72,7 +83,7 @@ jobs:
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- name: Set up Python - name: Set up Python
uses: actions/setup-python@v3 uses: actions/setup-python@v4
with: with:
python-version: ${{ matrix.python-version }} python-version: ${{ matrix.python-version }}
- name: Display Python version - name: Display Python version
@ -90,7 +101,7 @@ jobs:
python-version: ['3.7.4', '3.8', '3.9', '3.10'] python-version: ['3.7.4', '3.8', '3.9', '3.10']
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- uses: actions/setup-python@v3 - uses: actions/setup-python@v4
with: with:
python-version: ${{ matrix.python-version }} python-version: ${{ matrix.python-version }}
- run: python my_script.py - run: python my_script.py
@ -100,7 +111,7 @@ Download and set up an accurate pre-release version of Python:
```yaml ```yaml
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- uses: actions/setup-python@v3 - uses: actions/setup-python@v4
with: with:
python-version: '3.11.0-alpha.1' python-version: '3.11.0-alpha.1'
- run: python my_script.py - run: python my_script.py
@ -110,12 +121,32 @@ Download and set up the latest available version of Python (includes both pre-re
```yaml ```yaml
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- uses: actions/setup-python@v3 - uses: actions/setup-python@v4
with: with:
python-version: '3.11.0-alpha - 3.11.0' # SemVer's version range syntax python-version: '3.11.0-alpha - 3.11.0' # SemVer's version range syntax
- run: python my_script.py - 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: Download and set up PyPy:
```yaml ```yaml
@ -125,18 +156,34 @@ jobs:
strategy: strategy:
matrix: matrix:
python-version: python-version:
- 'pypy-3.7' # the latest available version of PyPy that supports Python 3.7 - 'pypy3.7' # the latest available version of PyPy that supports Python 3.7
- 'pypy-3.7-v7.3.3' # Python 3.7 and PyPy 7.3.3 - 'pypy3.7-v7.3.3' # Python 3.7 and PyPy 7.3.3
- 'pypy-3.8' # the latest available version of PyPy that supports Python 3.8 - 'pypy3.8' # the latest available version of PyPy that supports Python 3.8
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- uses: actions/setup-python@v3 - uses: actions/setup-python@v4
with: with:
python-version: ${{ matrix.python-version }} python-version: ${{ matrix.python-version }}
- run: python my_script.py - run: python my_script.py
``` ```
More details on PyPy syntax and examples of using preview / nightly versions of PyPy can be found in the [Available versions of PyPy](#available-versions-of-pypy) section. More details on PyPy syntax and examples of using preview / nightly versions of PyPy can be found in the [Available versions of PyPy](#available-versions-of-pypy) section.
An output is available with the absolute path of the python interpreter executable if you need it:
```yaml
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
id: cp310
with:
python-version: "3.10"
- run: pipx run --python '${{ steps.cp310.outputs.python-path }}' nox --version
```
>The environment variable `pythonLocation` also becomes available after Python or PyPy installation. It contains the absolute path to the folder where the desired version of Python or PyPy is installed.
# Getting started with Python + Actions # Getting started with Python + Actions
Check out our detailed guide on using [Python with GitHub Actions](https://help.github.com/en/actions/automating-your-workflow-with-github-actions/using-python-with-github-actions). Check out our detailed guide on using [Python with GitHub Actions](https://help.github.com/en/actions/automating-your-workflow-with-github-actions/using-python-with-github-actions).
@ -150,10 +197,13 @@ Check out our detailed guide on using [Python with GitHub Actions](https://help.
- For every minor version of Python, expect only the latest patch to be preinstalled. - For every minor version of Python, expect only the latest patch to be preinstalled.
- If `3.8.1` is installed for example, and `3.8.2` is released, expect `3.8.1` to be removed and replaced by `3.8.2` in the tools cache. - If `3.8.1` is installed for example, and `3.8.2` is released, expect `3.8.1` to be removed and replaced by `3.8.2` in the tools cache.
- If the exact patch version doesn't matter to you, specifying just the major and minor version will get you the latest preinstalled patch version. In the previous example, the version spec `3.8` will use the `3.8.2` Python version found in the cache. - If the exact patch version doesn't matter to you, specifying just the major and minor version will get you the latest preinstalled patch version. In the previous example, the version spec `3.8` will use the `3.8.2` Python version found in the cache.
- Use `-dev` instead of a patch number (e.g., `3.11-dev`) to install the latest patch version release for a given minor version, *alpha and beta releases included*.
- Downloadable Python versions from GitHub Releases ([actions/python-versions](https://github.com/actions/python-versions/releases)). - Downloadable Python versions from GitHub Releases ([actions/python-versions](https://github.com/actions/python-versions/releases)).
- All available versions are listed in the [version-manifest.json](https://github.com/actions/python-versions/blob/main/versions-manifest.json) file. - All available versions are listed in the [version-manifest.json](https://github.com/actions/python-versions/blob/main/versions-manifest.json) file.
- If there is a specific version of Python that is not available, you can open an issue here - If there is a specific version of Python that is not available, you can open an issue here
**Note:** Python versions used in this action are generated in the [python-versions](https://github.com/actions/python-versions) repository. For macOS and Ubuntu images python versions are built from the source code. For Windows the python-versions repository uses installation executable. For more information please refer to the [python-versions](https://github.com/actions/python-versions) repository.
# Available versions of PyPy # Available versions of PyPy
`setup-python` is able to configure PyPy from two sources: `setup-python` is able to configure PyPy from two sources:
@ -161,7 +211,7 @@ Check out our detailed guide on using [Python with GitHub Actions](https://help.
- Preinstalled versions of PyPy in the tools cache on GitHub-hosted runners - Preinstalled versions of PyPy in the tools cache on GitHub-hosted runners
- For detailed information regarding the available versions of PyPy that are installed, see [Supported software](https://docs.github.com/en/actions/reference/specifications-for-github-hosted-runners#supported-software). - For detailed information regarding the available versions of PyPy that are installed, see [Supported software](https://docs.github.com/en/actions/reference/specifications-for-github-hosted-runners#supported-software).
- For the latest PyPy release, all versions of Python are cached. - For the latest PyPy release, all versions of Python are cached.
- Cache is updated with a 1-2 week delay. If you specify the PyPy version as `pypy-3.7`, the cached version will be used although a newer version is available. If you need to start using the recently released version right after release, you should specify the exact PyPy version using `pypy-3.7-v7.3.3`. - Cache is updated with a 1-2 week delay. If you specify the PyPy version as `pypy3.7` or `pypy-3.7`, the cached version will be used although a newer version is available. If you need to start using the recently released version right after release, you should specify the exact PyPy version using `pypy3.7-v7.3.3` or `pypy-3.7-v7.3.3`.
- Downloadable PyPy versions from the [official PyPy site](https://downloads.python.org/pypy/). - Downloadable PyPy versions from the [official PyPy site](https://downloads.python.org/pypy/).
- All available versions that we can download are listed in [versions.json](https://downloads.python.org/pypy/versions.json) file. - All available versions that we can download are listed in [versions.json](https://downloads.python.org/pypy/versions.json) file.
@ -179,8 +229,8 @@ GitHub hosted runners have a tools cache that comes with a few versions of Pytho
|**PyPy Tool Cache**|`RUNNER_TOOL_CACHE/PyPy/*`| |**PyPy Tool Cache**|`RUNNER_TOOL_CACHE/PyPy/*`|
GitHub virtual environments are setup in [actions/virtual-environments](https://github.com/actions/virtual-environments). During the setup, the available versions of Python and PyPy are automatically downloaded, setup and documented. GitHub virtual environments are setup in [actions/virtual-environments](https://github.com/actions/virtual-environments). During the setup, the available versions of Python and PyPy are automatically downloaded, setup and documented.
- [Tools cache setup for Ubuntu](https://github.com/actions/virtual-environments/blob/main/images/linux/scripts/installers/hosted-tool-cache.sh) - Tools cache setup for Ubuntu: [Install-Toolset.ps1](https://github.com/actions/virtual-environments/blob/main/images/linux/scripts/installers/Install-Toolset.ps1) [Configure-Toolset.ps1](https://github.com/actions/virtual-environments/blob/main/images/linux/scripts/installers/Configure-Toolset.ps1)
- [Tools cache setup for Windows](https://github.com/actions/virtual-environments/blob/main/images/win/scripts/Installers/Download-ToolCache.ps1) - Tools cache setup for Windows: [Install-Toolset.ps1](https://github.com/actions/virtual-environments/blob/main/images/win/scripts/Installers/Install-Toolset.ps1) [Configure-Toolset.ps1](https://github.com/actions/virtual-environments/blob/main/images/win/scripts/Installers/Configure-Toolset.ps1)
# Specifying a Python version # Specifying a Python version
@ -194,19 +244,21 @@ You should specify only a major and minor version if you are okay with the most
- Using the most recent patch version will result in a very quick setup since no downloads will be required since a locally installed version Python on the runner will be used. - Using the most recent patch version will result in a very quick setup since no downloads will be required since a locally installed version Python on the runner will be used.
# Specifying a PyPy version # Specifying a PyPy version
The version of PyPy should be specified in the format `pypy-<python_version>[-v<pypy_version>]`. The version of PyPy should be specified in the format `pypy<python_version>[-v<pypy_version>]` or `pypy-<python_version>[-v<pypy_version>]`.
The `<pypy_version>` parameter is optional and can be skipped. The latest version will be used in this case. The `<pypy_version>` parameter is optional and can be skipped. The latest version will be used in this case.
``` ```
pypy-3.7 # the latest available version of PyPy that supports Python 3.7 pypy3.7 or pypy-3.7 # the latest available version of PyPy that supports Python 3.7
pypy-3.8 # the latest available version of PyPy that supports Python 3.8 pypy3.8 or pypy-3.8 # the latest available version of PyPy that supports Python 3.8
pypy-2.7 # the latest available version of PyPy that supports Python 2.7 pypy2.7 or pypy-2.7 # the latest available version of PyPy that supports Python 2.7
pypy-3.7-v7.3.3 # Python 3.7 and PyPy 7.3.3 pypy3.7-v7.3.3 or pypy-3.7-v7.3.3 # Python 3.7 and PyPy 7.3.3
pypy-3.7-v7.x # Python 3.7 and the latest available PyPy 7.x pypy3.7-v7.x or pypy-3.7-v7.x # Python 3.7 and the latest available PyPy 7.x
pypy-3.7-v7.3.3rc1 # Python 3.7 and preview version of PyPy pypy3.7-v7.3.3rc1 or pypy-3.7-v7.3.3rc1 # Python 3.7 and preview version of PyPy
pypy-3.7-nightly # Python 3.7 and nightly PyPy pypy3.7-nightly or pypy-3.7-nightly # Python 3.7 and nightly PyPy
``` ```
Note: `pypy2` and `pypy3` have been removed in v3. Use the format above instead.
# Caching packages dependencies # Caching packages dependencies
The action has built-in functionality for caching and restoring dependencies. It uses [actions/cache](https://github.com/actions/toolkit/tree/main/packages/cache) under the hood for caching dependencies but requires less configuration settings. Supported package managers are `pip`, `pipenv` and `poetry`. The `cache` input is optional, and caching is turned off by default. The action has built-in functionality for caching and restoring dependencies. It uses [actions/cache](https://github.com/actions/toolkit/tree/main/packages/cache) under the hood for caching dependencies but requires less configuration settings. Supported package managers are `pip`, `pipenv` and `poetry`. The `cache` input is optional, and caching is turned off by default.
@ -226,7 +278,7 @@ The requirements file format allows to specify dependency versions using logical
```yaml ```yaml
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- uses: actions/setup-python@v3 - uses: actions/setup-python@v4
with: with:
python-version: '3.9' python-version: '3.9'
cache: 'pip' cache: 'pip'
@ -237,12 +289,12 @@ steps:
```yaml ```yaml
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- name: Install pipenv - uses: actions/setup-python@v4
run: pipx install pipenv
- uses: actions/setup-python@v3
with: with:
python-version: '3.9' python-version: '3.9'
cache: 'pipenv' cache: 'pipenv'
- name: Install pipenv
run: curl https://raw.githubusercontent.com/pypa/pipenv/master/get-pipenv.py | python
- run: pipenv install - run: pipenv install
``` ```
@ -252,7 +304,7 @@ steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- name: Install poetry - name: Install poetry
run: pipx install poetry run: pipx install poetry
- uses: actions/setup-python@v3 - uses: actions/setup-python@v4
with: with:
python-version: '3.9' python-version: '3.9'
cache: 'poetry' cache: 'poetry'
@ -264,7 +316,7 @@ steps:
```yaml ```yaml
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- uses: actions/setup-python@v3 - uses: actions/setup-python@v4
with: with:
python-version: '3.9' python-version: '3.9'
cache: 'pip' cache: 'pip'
@ -276,18 +328,53 @@ steps:
```yaml ```yaml
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- name: Install pipenv - uses: actions/setup-python@v4
run: pipx install pipenv
- uses: actions/setup-python@v3
with: with:
python-version: '3.9' python-version: '3.9'
cache: 'pipenv' cache: 'pipenv'
cache-dependency-path: | cache-dependency-path: |
server/app/Pipfile.lock server/app/Pipfile.lock
__test__/app/Pipfile.lock __test__/app/Pipfile.lock
- name: Install pipenv
run: curl https://raw.githubusercontent.com/pypa/pipenv/master/get-pipenv.py | python
- run: pipenv install - 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`.
With this setting, the action will add/update environment variables (e.g. `PATH`, `PKG_CONFIG_PATH`, `pythonLocation`) for `python` to just work out of the box.
If `update-environment` is set to `false`, the action will not add/update environment variables.
This can prove useful if you want the only side-effect to be to ensure python is installed and rely on the `python-path` output to run python.
Such a requirement on side-effect could be because you don't want your composite action messing with your user's workflows.
```yaml
steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
id: cp310
with:
python-version: '3.10'
update-environment: false
- run: ${{ steps.cp310.outputs.python-path }} my_script.py
```
# Using `setup-python` with a self hosted runner # Using `setup-python` with a self hosted runner
Python distributions are only available for the same [environments](https://github.com/actions/virtual-environments#available-environments) that GitHub Actions hosted environments are available for. If you are using an unsupported version of Ubuntu such as `19.04` or another Linux distribution such as Fedora, `setup-python` will not work. If you have a supported self-hosted runner and you would like to use `setup-python`, there are a few extra things you need to make sure are set up so that new versions of Python can be downloaded and configured on your runner. Python distributions are only available for the same [environments](https://github.com/actions/virtual-environments#available-environments) that GitHub Actions hosted environments are available for. If you are using an unsupported version of Ubuntu such as `19.04` or another Linux distribution such as Fedora, `setup-python` will not work. If you have a supported self-hosted runner and you would like to use `setup-python`, there are a few extra things you need to make sure are set up so that new versions of Python can be downloaded and configured on your runner.
@ -305,7 +392,7 @@ If you are experiencing problems while configuring Python on your self-hosted ru
### Linux ### 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. - 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`. - 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. - 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`. - Create a directory called `hostedtoolcache` inside `/opt`.

View File

@ -5,7 +5,7 @@ import {getCacheDistributor} from '../src/cache-distributions/cache-factory';
describe('restore-cache', () => { describe('restore-cache', () => {
const pipFileLockHash = const pipFileLockHash =
'd1dd6218299d8a6db5fc2001d988b34a8b31f1e9d0bb4534d377dde7c19f64b3'; 'a3bdcc71289e4979ca9e051810d81999cc99823109faf6912e17ff14c8e621a6';
const requirementsHash = const requirementsHash =
'd8110e0006d7fb5ee76365d565eef9d37df1d11598b912d3eb66d398d57a1121'; 'd8110e0006d7fb5ee76365d565eef9d37df1d11598b912d3eb66d398d57a1121';
const requirementsLinuxHash = const requirementsLinuxHash =

View File

@ -212,6 +212,59 @@ describe('run', () => {
); );
expect(setFailedSpy).not.toHaveBeenCalled(); expect(setFailedSpy).not.toHaveBeenCalled();
}); });
it('saves with -1 cacheId , should not fail workflow', async () => {
inputs['cache'] = 'poetry';
getStateSpy.mockImplementation((name: string) => {
if (name === State.STATE_CACHE_PRIMARY_KEY) {
return poetryLockHash;
} else if (name === State.CACHE_PATHS) {
return JSON.stringify([__dirname]);
} else {
return requirementsHash;
}
});
saveCacheSpy.mockImplementation(() => {
return -1;
});
await run();
expect(getInputSpy).toHaveBeenCalled();
expect(getStateSpy).toHaveBeenCalledTimes(3);
expect(infoSpy).not.toHaveBeenCalled();
expect(saveCacheSpy).toHaveBeenCalled();
expect(infoSpy).not.toHaveBeenLastCalledWith(
`Cache saved with the key: ${poetryLockHash}`
);
expect(setFailedSpy).not.toHaveBeenCalled();
});
it('saves with error from toolkit, should fail workflow', async () => {
inputs['cache'] = 'npm';
getStateSpy.mockImplementation((name: string) => {
if (name === State.STATE_CACHE_PRIMARY_KEY) {
return poetryLockHash;
} else if (name === State.CACHE_PATHS) {
return JSON.stringify([__dirname]);
} else {
return requirementsHash;
}
});
saveCacheSpy.mockImplementation(() => {
throw new cache.ValidationError('Validation failed');
});
await run();
expect(getInputSpy).toHaveBeenCalled();
expect(getStateSpy).toHaveBeenCalledTimes(3);
expect(infoSpy).not.toHaveBeenCalledWith();
expect(saveCacheSpy).toHaveBeenCalled();
expect(setFailedSpy).toHaveBeenCalled();
});
}); });
afterEach(() => { afterEach(() => {

14
__tests__/check-python-path.sh Executable file
View File

@ -0,0 +1,14 @@
#!/bin/bash
set -euo pipefail
PYTHON_PATH="$1"
PATH_EXECUTABLE=$(python -c 'import sys; print(sys.executable)')
PYTHON_PATH_EXECUTABLE=$("${PYTHON_PATH}" -c 'import sys; print(sys.executable)')
if [ "${PATH_EXECUTABLE}" != "${PYTHON_PATH_EXECUTABLE}" ]; then
echo "Executable mismatch."
echo "python in PATH is: ${PATH_EXECUTABLE}"
echo "python-path (${PYTHON_PATH}) is: ${PYTHON_PATH_EXECUTABLE}"
exit 1
fi
echo "python-path: ${PYTHON_PATH}"

View File

@ -4,8 +4,8 @@ verify_ssl = true
name = "pypi" name = "pypi"
[packages] [packages]
numpy = "1.22.3" flake8 = "==4.0.1"
pandas = "1.4.2" numpy = "==1.23.0"
[dev-packages] [dev-packages]

View File

@ -1,7 +1,7 @@
{ {
"_meta": { "_meta": {
"hash": { "hash": {
"sha256": "33e3640eff8b2b6c7149b85568151f39a66c544033b4b3f3f2ec9ad5ce6dfe7e" "sha256": "e9c37110984955621040e2dc8548c026eb8466c23db1b8e69430289b10be8938"
}, },
"pipfile-spec": 6, "pipfile-spec": 6,
"requires": { "requires": {
@ -16,81 +16,64 @@
] ]
}, },
"default": { "default": {
"flake8": {
"hashes": [
"sha256:479b1304f72536a55948cb40a32dce8bb0ffe3501e26eaf292c7e60eb5e0428d",
"sha256:806e034dda44114815e23c16ef92f95c91e4c71100ff52813adf7132a6ad870d"
],
"index": "pypi",
"version": "==4.0.1"
},
"mccabe": {
"hashes": [
"sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42",
"sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"
],
"version": "==0.6.1"
},
"numpy": { "numpy": {
"hashes": [ "hashes": [
"sha256:07a8c89a04997625236c5ecb7afe35a02af3896c8aa01890a849913a2309c676", "sha256:092f5e6025813e64ad6d1b52b519165d08c730d099c114a9247c9bb635a2a450",
"sha256:08d9b008d0156c70dc392bb3ab3abb6e7a711383c3247b410b39962263576cd4", "sha256:196cd074c3f97c4121601790955f915187736f9cf458d3ee1f1b46aff2b1ade0",
"sha256:201b4d0552831f7250a08d3b38de0d989d6f6e4658b709a02a73c524ccc6ffce", "sha256:1c29b44905af288b3919803aceb6ec7fec77406d8b08aaa2e8b9e63d0fe2f160",
"sha256:2c10a93606e0b4b95c9b04b77dc349b398fdfbda382d2a39ba5a822f669a0123", "sha256:2b2da66582f3a69c8ce25ed7921dcd8010d05e59ac8d89d126a299be60421171",
"sha256:3ca688e1b9b95d80250bca34b11a05e389b1420d00e87a0d12dc45f131f704a1", "sha256:5043bcd71fcc458dfb8a0fc5509bbc979da0131b9d08e3d5f50fb0bbb36f169a",
"sha256:48a3aecd3b997bf452a2dedb11f4e79bc5bfd21a1d4cc760e703c31d57c84b3e", "sha256:58bfd40eb478f54ff7a5710dd61c8097e169bc36cc68333d00a9bcd8def53b38",
"sha256:568dfd16224abddafb1cbcce2ff14f522abe037268514dd7e42c6776a1c3f8e5", "sha256:79a506cacf2be3a74ead5467aee97b81fca00c9c4c8b3ba16dbab488cd99ba10",
"sha256:5bfb1bb598e8229c2d5d48db1860bcf4311337864ea3efdbe1171fb0c5da515d", "sha256:94b170b4fa0168cd6be4becf37cb5b127bd12a795123984385b8cd4aca9857e5",
"sha256:639b54cdf6aa4f82fe37ebf70401bbb74b8508fddcf4797f9fe59615b8c5813a", "sha256:97a76604d9b0e79f59baeca16593c711fddb44936e40310f78bfef79ee9a835f",
"sha256:8251ed96f38b47b4295b1ae51631de7ffa8260b5b087808ef09a39a9d66c97ab", "sha256:98e8e0d8d69ff4d3fa63e6c61e8cfe2d03c29b16b58dbef1f9baa175bbed7860",
"sha256:92bfa69cfbdf7dfc3040978ad09a48091143cffb778ec3b03fa170c494118d75", "sha256:ac86f407873b952679f5f9e6c0612687e51547af0e14ddea1eedfcb22466babd",
"sha256:97098b95aa4e418529099c26558eeb8486e66bd1e53a6b606d684d0c3616b168", "sha256:ae8adff4172692ce56233db04b7ce5792186f179c415c37d539c25de7298d25d",
"sha256:a3bae1a2ed00e90b3ba5f7bd0a7c7999b55d609e0c54ceb2b076a25e345fa9f4", "sha256:bd3fa4fe2e38533d5336e1272fc4e765cabbbde144309ccee8675509d5cd7b05",
"sha256:c34ea7e9d13a70bf2ab64a2532fe149a9aced424cd05a2c4ba662fd989e3e45f", "sha256:d0d2094e8f4d760500394d77b383a1b06d3663e8892cdf5df3c592f55f3bff66",
"sha256:dbc7601a3b7472d559dc7b933b18b4b66f9aa7452c120e87dfb33d02008c8a18", "sha256:d54b3b828d618a19779a84c3ad952e96e2c2311b16384e973e671aa5be1f6187",
"sha256:e7927a589df200c5e23c57970bafbd0cd322459aa7b1ff73b7c2e84d6e3eae62", "sha256:d6ca8dabe696c2785d0c8c9b0d8a9b6e5fdbe4f922bde70d57fa1a2848134f95",
"sha256:f8c1f39caad2c896bc0018f699882b345b2a63708008be29b1f355ebf6f933fe", "sha256:d8cc87bed09de55477dba9da370c1679bd534df9baa171dd01accbb09687dac3",
"sha256:f950f8845b480cffe522913d35567e29dd381b0dc7e4ce6a4a9f9156417d2430", "sha256:f0f18804df7370571fb65db9b98bf1378172bd4e962482b857e612d1fec0f53e",
"sha256:fade0d4f4d292b6f39951b6836d7a3c7ef5b2347f3c420cd9820a1d90d794802", "sha256:f1d88ef79e0a7fa631bb2c3dda1ea46b32b1fe614e10fedd611d3d5398447f2f",
"sha256:fdf3c08bce27132395d3c3ba1503cac12e17282358cb4bddc25cc46b0aca07aa" "sha256:f9c3fc2adf67762c9fe1849c859942d23f8d3e0bee7b5ed3d4a9c3eeb50a2f07",
"sha256:fc431493df245f3c627c0c05c2bd134535e7929dbe2e602b80e42bf52ff760bc",
"sha256:fe8b9683eb26d2c4d5db32cd29b38fdcf8381324ab48313b5b69088e0e355379"
], ],
"index": "pypi", "index": "pypi",
"version": "==1.22.3" "version": "==1.23.0"
}, },
"pandas": { "pycodestyle": {
"hashes": [ "hashes": [
"sha256:0010771bd9223f7afe5f051eb47c4a49534345dfa144f2f5470b27189a4dd3b5", "sha256:720f8b39dde8b293825e7ff02c475f3077124006db4f440dcbc9a20b76548a20",
"sha256:061609334a8182ab500a90fe66d46f6f387de62d3a9cb9aa7e62e3146c712167", "sha256:eddd5847ef438ea1c7870ca7eb78a9d47ce0cdb4851a5523949f2601d0cbbe7f"
"sha256:09d8be7dd9e1c4c98224c4dfe8abd60d145d934e9fc1f5f411266308ae683e6a",
"sha256:295872bf1a09758aba199992c3ecde455f01caf32266d50abc1a073e828a7b9d",
"sha256:3228198333dd13c90b6434ddf61aa6d57deaca98cf7b654f4ad68a2db84f8cfe",
"sha256:385c52e85aaa8ea6a4c600a9b2821181a51f8be0aee3af6f2dcb41dafc4fc1d0",
"sha256:51649ef604a945f781105a6d2ecf88db7da0f4868ac5d45c51cb66081c4d9c73",
"sha256:5586cc95692564b441f4747c47c8a9746792e87b40a4680a2feb7794defb1ce3",
"sha256:5a206afa84ed20e07603f50d22b5f0db3fb556486d8c2462d8bc364831a4b417",
"sha256:5b79af3a69e5175c6fa7b4e046b21a646c8b74e92c6581a9d825687d92071b51",
"sha256:5c54ea4ef3823108cd4ec7fb27ccba4c3a775e0f83e39c5e17f5094cb17748bc",
"sha256:8c5bf555b6b0075294b73965adaafb39cf71c312e38c5935c93d78f41c19828a",
"sha256:92bc1fc585f1463ca827b45535957815b7deb218c549b7c18402c322c7549a12",
"sha256:95c1e422ced0199cf4a34385ff124b69412c4bc912011ce895582bee620dfcaa",
"sha256:b8134651258bce418cb79c71adeff0a44090c98d955f6953168ba16cc285d9f7",
"sha256:be67c782c4f1b1f24c2f16a157e12c2693fd510f8df18e3287c77f33d124ed07",
"sha256:c072c7f06b9242c855ed8021ff970c0e8f8b10b35e2640c657d2a541c5950f59",
"sha256:d0d4f13e4be7ce89d7057a786023c461dd9370040bdb5efa0a7fe76b556867a0",
"sha256:df82739e00bb6daf4bba4479a40f38c718b598a84654cbd8bb498fd6b0aa8c16",
"sha256:f549097993744ff8c41b5e8f2f0d3cbfaabe89b4ae32c8c08ead6cc535b80139",
"sha256:ff08a14ef21d94cdf18eef7c569d66f2e24e0bc89350bcd7d243dd804e3b5eb2"
], ],
"index": "pypi", "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
"version": "==1.4.2" "version": "==2.8.0"
}, },
"python-dateutil": { "pyflakes": {
"hashes": [ "hashes": [
"sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86", "sha256:05a85c2872edf37a4ed30b0cce2f6093e1d0581f8c19d7393122da7e25b2b24c",
"sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9" "sha256:3bb3a3f256f4b7968c9c788781e4ff07dce46bdf12339dcda61053375426ee2e"
], ],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2'", "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
"version": "==2.8.2" "version": "==2.4.0"
},
"pytz": {
"hashes": [
"sha256:1e760e2fe6a8163bc0b3d9a19c4f84342afa0a2affebfaa84b01b978a02ecaa7",
"sha256:e68985985296d9a66a881eb3193b0906246245294a881e7c8afe623866ac6a5c"
],
"version": "==2022.1"
},
"six": {
"hashes": [
"sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926",
"sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"
],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2'",
"version": "==1.16.0"
} }
}, },
"develop": {} "develop": {}

View File

@ -5,6 +5,7 @@ import {HttpClient} from '@actions/http-client';
import * as ifm from '@actions/http-client/interfaces'; import * as ifm from '@actions/http-client/interfaces';
import * as tc from '@actions/tool-cache'; import * as tc from '@actions/tool-cache';
import * as exec from '@actions/exec'; import * as exec from '@actions/exec';
import * as core from '@actions/core';
import * as path from 'path'; import * as path from 'path';
import * as semver from 'semver'; import * as semver from 'semver';
@ -37,16 +38,34 @@ describe('parsePyPyVersion', () => {
['pypy-3.6-v7.x', {pythonVersion: '3.6', pypyVersion: 'v7.x'}], ['pypy-3.6-v7.x', {pythonVersion: '3.6', pypyVersion: 'v7.x'}],
['pypy-3.6', {pythonVersion: '3.6', pypyVersion: 'x'}], ['pypy-3.6', {pythonVersion: '3.6', pypyVersion: 'x'}],
['pypy-3.6-nightly', {pythonVersion: '3.6', pypyVersion: 'nightly'}], ['pypy-3.6-nightly', {pythonVersion: '3.6', pypyVersion: 'nightly'}],
['pypy-3.6-v7.3.3rc1', {pythonVersion: '3.6', pypyVersion: 'v7.3.3-rc.1'}] ['pypy-3.6-v7.3.3rc1', {pythonVersion: '3.6', pypyVersion: 'v7.3.3-rc.1'}],
['pypy3.8-v7.3.7', {pythonVersion: '3.8', pypyVersion: 'v7.3.7'}],
['pypy3.8-v7.3.x', {pythonVersion: '3.8', pypyVersion: 'v7.3.x'}],
['pypy3.8-v7.x', {pythonVersion: '3.8', pypyVersion: 'v7.x'}],
['pypy3.8', {pythonVersion: '3.8', pypyVersion: 'x'}],
['pypy3.9-nightly', {pythonVersion: '3.9', pypyVersion: 'nightly'}],
['pypy3.9-v7.3.8rc1', {pythonVersion: '3.9', pypyVersion: 'v7.3.8-rc.1'}]
])('%s -> %s', (input, expected) => { ])('%s -> %s', (input, expected) => {
expect(finder.parsePyPyVersion(input)).toEqual(expected); expect(finder.parsePyPyVersion(input)).toEqual(expected);
}); });
it('throw on invalid input', () => { it.each(['', 'pypy-', 'pypy', 'p', 'notpypy-'])(
expect(() => finder.parsePyPyVersion('pypy-')).toThrowError( 'throw on invalid input "%s"',
"Invalid 'version' property for PyPy. PyPy version should be specified as 'pypy-<python-version>'. See README for examples and documentation." input => {
); expect(() => finder.parsePyPyVersion(input)).toThrowError(
}); "Invalid 'version' property for PyPy. PyPy version should be specified as 'pypy<python-version>' or 'pypy-<python-version>'. See README for examples and documentation."
);
}
);
it.each(['pypy-2', 'pypy-3', 'pypy2', 'pypy3', 'pypy3.x', 'pypy3.8.10'])(
'throw on invalid input "%s"',
input => {
expect(() => finder.parsePyPyVersion(input)).toThrowError(
"Invalid format of Python version for PyPy. Python version should be specified in format 'x.y'. See README for examples and documentation."
);
}
);
}); });
describe('getPyPyVersionFromPath', () => { describe('getPyPyVersionFromPath', () => {
@ -130,8 +149,13 @@ describe('findPyPyVersion', () => {
let spyWriteExactPyPyVersionFile: jest.SpyInstance; let spyWriteExactPyPyVersionFile: jest.SpyInstance;
let spyCacheDir: jest.SpyInstance; let spyCacheDir: jest.SpyInstance;
let spyChmodSync: jest.SpyInstance; let spyChmodSync: jest.SpyInstance;
let spyCoreAddPath: jest.SpyInstance;
let spyCoreExportVariable: jest.SpyInstance;
const env = process.env;
beforeEach(() => { beforeEach(() => {
jest.resetModules();
process.env = {...env};
tcFind = jest.spyOn(tc, 'find'); tcFind = jest.spyOn(tc, 'find');
tcFind.mockImplementation((tool: string, version: string) => { tcFind.mockImplementation((tool: string, version: string) => {
const semverRange = new semver.Range(version); const semverRange = new semver.Range(version);
@ -183,32 +207,46 @@ describe('findPyPyVersion', () => {
spyExistsSync = jest.spyOn(fs, 'existsSync'); spyExistsSync = jest.spyOn(fs, 'existsSync');
spyExistsSync.mockReturnValue(true); spyExistsSync.mockReturnValue(true);
spyCoreAddPath = jest.spyOn(core, 'addPath');
spyCoreExportVariable = jest.spyOn(core, 'exportVariable');
}); });
afterEach(() => { afterEach(() => {
jest.resetAllMocks(); jest.resetAllMocks();
jest.clearAllMocks(); jest.clearAllMocks();
jest.restoreAllMocks(); jest.restoreAllMocks();
process.env = env;
}); });
it('found PyPy in toolcache', async () => { it('found PyPy in toolcache', async () => {
await expect( await expect(
finder.findPyPyVersion('pypy-3.6-v7.3.x', architecture) finder.findPyPyVersion('pypy-3.6-v7.3.x', architecture, true)
).resolves.toEqual({ ).resolves.toEqual({
resolvedPythonVersion: '3.6.12', resolvedPythonVersion: '3.6.12',
resolvedPyPyVersion: '7.3.3' resolvedPyPyVersion: '7.3.3'
}); });
expect(spyCoreAddPath).toHaveBeenCalled();
expect(spyCoreExportVariable).toHaveBeenCalledWith(
'pythonLocation',
expect.anything()
);
expect(spyCoreExportVariable).toHaveBeenCalledWith(
'PKG_CONFIG_PATH',
expect.anything()
);
}); });
it('throw on invalid input format', async () => { it('throw on invalid input format', async () => {
await expect( await expect(
finder.findPyPyVersion('pypy3.7-v7.3.x', architecture) finder.findPyPyVersion('pypy3.7-v7.3.x', architecture, true)
).rejects.toThrow(); ).rejects.toThrow();
}); });
it('throw on invalid input format pypy3.7-7.3.x', async () => { it('throw on invalid input format pypy3.7-7.3.x', async () => {
await expect( await expect(
finder.findPyPyVersion('pypy3.7-v7.3.x', architecture) finder.findPyPyVersion('pypy3.7-v7.3.x', architecture, true)
).rejects.toThrow(); ).rejects.toThrow();
}); });
@ -220,16 +258,42 @@ describe('findPyPyVersion', () => {
spyChmodSync = jest.spyOn(fs, 'chmodSync'); spyChmodSync = jest.spyOn(fs, 'chmodSync');
spyChmodSync.mockImplementation(() => undefined); spyChmodSync.mockImplementation(() => undefined);
await expect( await expect(
finder.findPyPyVersion('pypy-3.7-v7.3.x', architecture) finder.findPyPyVersion('pypy-3.7-v7.3.x', architecture, true)
).resolves.toEqual({ ).resolves.toEqual({
resolvedPythonVersion: '3.7.9', resolvedPythonVersion: '3.7.9',
resolvedPyPyVersion: '7.3.3' resolvedPyPyVersion: '7.3.3'
}); });
expect(spyCoreAddPath).toHaveBeenCalled();
expect(spyCoreExportVariable).toHaveBeenCalledWith(
'pythonLocation',
expect.anything()
);
expect(spyCoreExportVariable).toHaveBeenCalledWith(
'PKG_CONFIG_PATH',
expect.anything()
);
});
it('found and install successfully without environment update', async () => {
spyCacheDir = jest.spyOn(tc, 'cacheDir');
spyCacheDir.mockImplementation(() =>
path.join(toolDir, 'PyPy', '3.7.7', architecture)
);
spyChmodSync = jest.spyOn(fs, 'chmodSync');
spyChmodSync.mockImplementation(() => undefined);
await expect(
finder.findPyPyVersion('pypy-3.7-v7.3.x', architecture, false)
).resolves.toEqual({
resolvedPythonVersion: '3.7.9',
resolvedPyPyVersion: '7.3.3'
});
expect(spyCoreAddPath).not.toHaveBeenCalled();
expect(spyCoreExportVariable).not.toHaveBeenCalled();
}); });
it('throw if release is not found', async () => { it('throw if release is not found', async () => {
await expect( await expect(
finder.findPyPyVersion('pypy-3.7-v7.5.x', architecture) finder.findPyPyVersion('pypy-3.7-v7.5.x', architecture, true)
).rejects.toThrowError( ).rejects.toThrowError(
`PyPy version 3.7 (v7.5.x) with arch ${architecture} not found` `PyPy version 3.7 (v7.5.x) with arch ${architecture} not found`
); );

View File

@ -19,15 +19,29 @@ process.env['RUNNER_TOOL_CACHE'] = toolDir;
process.env['RUNNER_TEMP'] = tempDir; process.env['RUNNER_TEMP'] = tempDir;
import * as tc from '@actions/tool-cache'; import * as tc from '@actions/tool-cache';
import * as core from '@actions/core';
import * as finder from '../src/find-python'; import * as finder from '../src/find-python';
import * as installer from '../src/install-python'; import * as installer from '../src/install-python';
const manifestData = require('./data/versions-manifest.json'); const manifestData = require('./data/versions-manifest.json');
describe('Finder tests', () => { 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');
});
afterEach(() => { afterEach(() => {
jest.resetAllMocks(); jest.resetAllMocks();
jest.clearAllMocks(); jest.clearAllMocks();
jest.restoreAllMocks();
process.env = env;
}); });
it('Finds Python if it is installed', async () => { it('Finds Python if it is installed', async () => {
@ -35,7 +49,26 @@ describe('Finder tests', () => {
await io.mkdirP(pythonDir); await io.mkdirP(pythonDir);
fs.writeFileSync(`${pythonDir}.complete`, 'hello'); fs.writeFileSync(`${pythonDir}.complete`, 'hello');
// This will throw if it doesn't find it in the cache and in the manifest (because no such version exists) // This will throw if it doesn't find it in the cache and in the manifest (because no such version exists)
await finder.useCpythonVersion('3.x', 'x64'); await finder.useCpythonVersion('3.x', 'x64', true);
expect(spyCoreAddPath).toHaveBeenCalled();
expect(spyCoreExportVariable).toHaveBeenCalledWith(
'pythonLocation',
expect.anything()
);
expect(spyCoreExportVariable).toHaveBeenCalledWith(
'PKG_CONFIG_PATH',
expect.anything()
);
});
it('Finds Python if it is installed without environment update', async () => {
const pythonDir: string = path.join(toolDir, 'Python', '3.0.0', 'x64');
await io.mkdirP(pythonDir);
fs.writeFileSync(`${pythonDir}.complete`, 'hello');
// This will throw if it doesn't find it in the cache and in the manifest (because no such version exists)
await finder.useCpythonVersion('3.x', 'x64', false);
expect(spyCoreAddPath).not.toHaveBeenCalled();
expect(spyCoreExportVariable).not.toHaveBeenCalled();
}); });
it('Finds stable Python version if it is not installed, but exists in the manifest', async () => { it('Finds stable Python version if it is not installed, but exists in the manifest', async () => {
@ -52,7 +85,16 @@ describe('Finder tests', () => {
fs.writeFileSync(`${pythonDir}.complete`, 'hello'); fs.writeFileSync(`${pythonDir}.complete`, 'hello');
}); });
// This will throw if it doesn't find it in the cache and in the manifest (because no such version exists) // This will throw if it doesn't find it in the cache and in the manifest (because no such version exists)
await finder.useCpythonVersion('1.2.3', 'x64'); await finder.useCpythonVersion('1.2.3', 'x64', true);
expect(spyCoreAddPath).toHaveBeenCalled();
expect(spyCoreExportVariable).toHaveBeenCalledWith(
'pythonLocation',
expect.anything()
);
expect(spyCoreExportVariable).toHaveBeenCalledWith(
'PKG_CONFIG_PATH',
expect.anything()
);
}); });
it('Finds pre-release Python version in the manifest', async () => { it('Finds pre-release Python version in the manifest', async () => {
@ -74,17 +116,28 @@ describe('Finder tests', () => {
fs.writeFileSync(`${pythonDir}.complete`, 'hello'); fs.writeFileSync(`${pythonDir}.complete`, 'hello');
}); });
// This will throw if it doesn't find it in the manifest (because no such version exists) // This will throw if it doesn't find it in the manifest (because no such version exists)
await finder.useCpythonVersion('1.2.3-beta.2', 'x64'); await finder.useCpythonVersion('1.2.3-beta.2', 'x64', true);
expect(spyCoreAddPath).toHaveBeenCalled();
expect(spyCoreExportVariable).toHaveBeenCalledWith(
'pythonLocation',
expect.anything()
);
expect(spyCoreExportVariable).toHaveBeenCalledWith(
'PKG_CONFIG_PATH',
expect.anything()
);
}); });
it('Errors if Python is not installed', async () => { it('Errors if Python is not installed', async () => {
// This will throw if it doesn't find it in the cache and in the manifest (because no such version exists) // This will throw if it doesn't find it in the cache and in the manifest (because no such version exists)
let thrown = false; let thrown = false;
try { try {
await finder.useCpythonVersion('3.300000', 'x64'); await finder.useCpythonVersion('3.300000', 'x64', true);
} catch { } catch {
thrown = true; thrown = true;
} }
expect(thrown).toBeTruthy(); expect(thrown).toBeTruthy();
expect(spyCoreAddPath).not.toHaveBeenCalled();
expect(spyCoreExportVariable).not.toHaveBeenCalled();
}); });
}); });

View File

@ -4,8 +4,9 @@ description: 'Set up a specific version of Python and add the command-line tools
author: 'GitHub' author: 'GitHub'
inputs: inputs:
python-version: python-version:
description: "Version range or exact version of a Python version to use, using SemVer's version range syntax." description: "Version range or exact version of Python to use, using SemVer's version range syntax. Reads from .python-version if unset."
default: '3.x' python-version-file:
description: "File containing the Python version to use. Example: .python-version"
cache: cache:
description: 'Used to specify a package manager for caching in the default directory. Supported values: pip, pipenv, poetry.' description: 'Used to specify a package manager for caching in the default directory. Supported values: pip, pipenv, poetry.'
required: false required: false
@ -16,11 +17,16 @@ inputs:
default: ${{ github.token }} default: ${{ github.token }}
cache-dependency-path: cache-dependency-path:
description: 'Used to specify the path to dependency files. Supports wildcards or a list of file names for caching multiple dependencies.' description: 'Used to specify the path to dependency files. Supports wildcards or a list of file names for caching multiple dependencies.'
update-environment:
description: 'Set this option if you want the action to update environment variables.'
default: true
outputs: outputs:
python-version: python-version:
description: "The installed python version. Useful when given a version range as input." description: "The installed python version. Useful when given a version range as input."
cache-hit: cache-hit:
description: 'A boolean value to indicate a cache entry was found' description: 'A boolean value to indicate a cache entry was found'
python-path:
description: "The absolute path to the Python executable."
runs: runs:
using: 'node16' using: 'node16'
main: 'dist/setup/index.js' main: 'dist/setup/index.js'

52679
dist/cache-save/index.js vendored

File diff suppressed because one or more lines are too long

65470
dist/setup/index.js vendored

File diff suppressed because one or more lines are too long

View File

@ -45,8 +45,8 @@ We won't pursue the goal to provide wide customization of caching in the scope o
``` ```
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v3
- uses: actions/setup-python@v2 - uses: actions/setup-python@v4
with: with:
python-version: 3.9 python-version: 3.9
cache: pip cache: pip
@ -56,8 +56,8 @@ steps:
``` ```
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v3
- uses: actions/setup-python@v2 - uses: actions/setup-python@v4
with: with:
python-version: 3.9 python-version: 3.9
cache: pipenv cache: pipenv
@ -66,8 +66,8 @@ steps:
``` ```
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v3
- uses: actions/setup-python@v2 - uses: actions/setup-python@v4
with: with:
python-version: 3.9 python-version: 3.9
cache: pip cache: pip
@ -80,8 +80,8 @@ steps:
``` ```
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v3
- uses: actions/setup-python@v2 - uses: actions/setup-python@v4
with: with:
python-version: 3.9 python-version: 3.9
cache: pip cache: pip

89
package-lock.json generated
View File

@ -1,16 +1,16 @@
{ {
"name": "setup-python", "name": "setup-python",
"version": "3.1.0", "version": "4.0.0",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "setup-python", "name": "setup-python",
"version": "3.1.0", "version": "4.0.0",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@actions/cache": "^2.0.0", "@actions/cache": "^3.0.0",
"@actions/core": "^1.2.3", "@actions/core": "^1.7.0",
"@actions/exec": "^1.1.0", "@actions/exec": "^1.1.0",
"@actions/glob": "^0.2.0", "@actions/glob": "^0.2.0",
"@actions/io": "^1.0.2", "@actions/io": "^1.0.2",
@ -21,7 +21,7 @@
"@types/jest": "^27.0.2", "@types/jest": "^27.0.2",
"@types/node": "^16.11.25", "@types/node": "^16.11.25",
"@types/semver": "^7.1.0", "@types/semver": "^7.1.0",
"@zeit/ncc": "^0.22.0", "@vercel/ncc": "^0.33.4",
"husky": "^7.0.2", "husky": "^7.0.2",
"jest": "^27.2.5", "jest": "^27.2.5",
"jest-circus": "^27.2.5", "jest-circus": "^27.2.5",
@ -31,14 +31,14 @@
} }
}, },
"node_modules/@actions/cache": { "node_modules/@actions/cache": {
"version": "2.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/@actions/cache/-/cache-2.0.0.tgz", "resolved": "https://registry.npmjs.org/@actions/cache/-/cache-3.0.0.tgz",
"integrity": "sha512-d7n8ul6HjWX6oDrNEPoqn8ZvqyyDhp9Uek6WOxALyxGVsXU+8+ND+viD3UfrXVWfs/GQiqI5Eq4cOozZj0yRFQ==", "integrity": "sha512-GL9CT1Fnu+pqs8TTB621q8Xa8Cilw2n9MwvbgMedetH7L1q2n6jY61gzbwGbKgtVbp3gVJ12aNMi4osSGXx3KQ==",
"dependencies": { "dependencies": {
"@actions/core": "^1.2.6", "@actions/core": "^1.2.6",
"@actions/exec": "^1.0.1", "@actions/exec": "^1.0.1",
"@actions/glob": "^0.1.0", "@actions/glob": "^0.1.0",
"@actions/http-client": "^1.0.9", "@actions/http-client": "^2.0.1",
"@actions/io": "^1.0.1", "@actions/io": "^1.0.1",
"@azure/ms-rest-js": "^2.6.0", "@azure/ms-rest-js": "^2.6.0",
"@azure/storage-blob": "^12.8.0", "@azure/storage-blob": "^12.8.0",
@ -56,11 +56,11 @@
} }
}, },
"node_modules/@actions/cache/node_modules/@actions/http-client": { "node_modules/@actions/cache/node_modules/@actions/http-client": {
"version": "1.0.11", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-1.0.11.tgz", "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.0.1.tgz",
"integrity": "sha512-VRYHGQV1rqnROJqdMvGUbY/Kn8vriQe/F9HR2AlYHzmKuM/p3kjNuXhmdBfcVgsvRWTz5C5XW5xvndZrVBuAYg==", "integrity": "sha512-PIXiMVtz6VvyaRsGY268qvj57hXQEpsYogYOu2nrQhlf+XCGmZstmuZBbAybUl1nQGnvS1k1eEsQ69ZoD7xlSw==",
"dependencies": { "dependencies": {
"tunnel": "0.0.6" "tunnel": "^0.0.6"
} }
}, },
"node_modules/@actions/cache/node_modules/semver": { "node_modules/@actions/cache/node_modules/semver": {
@ -72,9 +72,12 @@
} }
}, },
"node_modules/@actions/core": { "node_modules/@actions/core": {
"version": "1.2.6", "version": "1.7.0",
"resolved": "https://registry.npmjs.org/@actions/core/-/core-1.2.6.tgz", "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.7.0.tgz",
"integrity": "sha512-ZQYitnqiyBc3D+k7LsgSBmMDVkOVidaagDG7j3fOym77jNunWRuYx7VSHa9GNfFZh+zh61xsCjRj4JxMZlDqTA==" "integrity": "sha512-7fPSS7yKOhTpgLMbw7lBLc1QJWvJBBAgyTX2PEhagWcKK8t0H8AKCoPMfnrHqIm5cRYH4QFPqD1/ruhuUE7YcQ==",
"dependencies": {
"@actions/http-client": "^1.0.11"
}
}, },
"node_modules/@actions/exec": { "node_modules/@actions/exec": {
"version": "1.1.0", "version": "1.1.0",
@ -94,9 +97,9 @@
} }
}, },
"node_modules/@actions/http-client": { "node_modules/@actions/http-client": {
"version": "1.0.8", "version": "1.0.11",
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-1.0.8.tgz", "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-1.0.11.tgz",
"integrity": "sha512-G4JjJ6f9Hb3Zvejj+ewLLKLf99ZC+9v+yCxoYf9vSyH+WkzPLB2LuUtRMGNkooMqdugGBFStIKXOuvH1W+EctA==", "integrity": "sha512-VRYHGQV1rqnROJqdMvGUbY/Kn8vriQe/F9HR2AlYHzmKuM/p3kjNuXhmdBfcVgsvRWTz5C5XW5xvndZrVBuAYg==",
"dependencies": { "dependencies": {
"tunnel": "0.0.6" "tunnel": "0.0.6"
} }
@ -3923,11 +3926,10 @@
"integrity": "sha512-FA/BWv8t8ZWJ+gEOnLLd8ygxH/2UFbAvgEonyfN6yWGLKc7zVjbpl2Y4CTjid9h2RfgPP6SEt6uHwEOply00yw==", "integrity": "sha512-FA/BWv8t8ZWJ+gEOnLLd8ygxH/2UFbAvgEonyfN6yWGLKc7zVjbpl2Y4CTjid9h2RfgPP6SEt6uHwEOply00yw==",
"dev": true "dev": true
}, },
"node_modules/@zeit/ncc": { "node_modules/@vercel/ncc": {
"version": "0.22.0", "version": "0.33.4",
"resolved": "https://registry.npmjs.org/@zeit/ncc/-/ncc-0.22.0.tgz", "resolved": "https://registry.npmjs.org/@vercel/ncc/-/ncc-0.33.4.tgz",
"integrity": "sha512-zaS6chwztGSLSEzsTJw9sLTYxQt57bPFBtsYlVtbqGvmDUsfW7xgXPYofzFa1kB9ur2dRop6IxCwPnWLBVCrbQ==", "integrity": "sha512-ln18hs7dMffelP47tpkaR+V5Tj6coykNyxJrlcmCormPqRQjB/Gv4cu2FfBG+PMzIfdZp2CLDsrrB1NPU22Qhg==",
"deprecated": "@zeit/ncc is no longer maintained. Please use @vercel/ncc instead.",
"dev": true, "dev": true,
"bin": { "bin": {
"ncc": "dist/ncc/cli.js" "ncc": "dist/ncc/cli.js"
@ -11338,14 +11340,14 @@
}, },
"dependencies": { "dependencies": {
"@actions/cache": { "@actions/cache": {
"version": "2.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/@actions/cache/-/cache-2.0.0.tgz", "resolved": "https://registry.npmjs.org/@actions/cache/-/cache-3.0.0.tgz",
"integrity": "sha512-d7n8ul6HjWX6oDrNEPoqn8ZvqyyDhp9Uek6WOxALyxGVsXU+8+ND+viD3UfrXVWfs/GQiqI5Eq4cOozZj0yRFQ==", "integrity": "sha512-GL9CT1Fnu+pqs8TTB621q8Xa8Cilw2n9MwvbgMedetH7L1q2n6jY61gzbwGbKgtVbp3gVJ12aNMi4osSGXx3KQ==",
"requires": { "requires": {
"@actions/core": "^1.2.6", "@actions/core": "^1.2.6",
"@actions/exec": "^1.0.1", "@actions/exec": "^1.0.1",
"@actions/glob": "^0.1.0", "@actions/glob": "^0.1.0",
"@actions/http-client": "^1.0.9", "@actions/http-client": "^2.0.1",
"@actions/io": "^1.0.1", "@actions/io": "^1.0.1",
"@azure/ms-rest-js": "^2.6.0", "@azure/ms-rest-js": "^2.6.0",
"@azure/storage-blob": "^12.8.0", "@azure/storage-blob": "^12.8.0",
@ -11363,11 +11365,11 @@
} }
}, },
"@actions/http-client": { "@actions/http-client": {
"version": "1.0.11", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-1.0.11.tgz", "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.0.1.tgz",
"integrity": "sha512-VRYHGQV1rqnROJqdMvGUbY/Kn8vriQe/F9HR2AlYHzmKuM/p3kjNuXhmdBfcVgsvRWTz5C5XW5xvndZrVBuAYg==", "integrity": "sha512-PIXiMVtz6VvyaRsGY268qvj57hXQEpsYogYOu2nrQhlf+XCGmZstmuZBbAybUl1nQGnvS1k1eEsQ69ZoD7xlSw==",
"requires": { "requires": {
"tunnel": "0.0.6" "tunnel": "^0.0.6"
} }
}, },
"semver": { "semver": {
@ -11378,9 +11380,12 @@
} }
}, },
"@actions/core": { "@actions/core": {
"version": "1.2.6", "version": "1.7.0",
"resolved": "https://registry.npmjs.org/@actions/core/-/core-1.2.6.tgz", "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.7.0.tgz",
"integrity": "sha512-ZQYitnqiyBc3D+k7LsgSBmMDVkOVidaagDG7j3fOym77jNunWRuYx7VSHa9GNfFZh+zh61xsCjRj4JxMZlDqTA==" "integrity": "sha512-7fPSS7yKOhTpgLMbw7lBLc1QJWvJBBAgyTX2PEhagWcKK8t0H8AKCoPMfnrHqIm5cRYH4QFPqD1/ruhuUE7YcQ==",
"requires": {
"@actions/http-client": "^1.0.11"
}
}, },
"@actions/exec": { "@actions/exec": {
"version": "1.1.0", "version": "1.1.0",
@ -11400,9 +11405,9 @@
} }
}, },
"@actions/http-client": { "@actions/http-client": {
"version": "1.0.8", "version": "1.0.11",
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-1.0.8.tgz", "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-1.0.11.tgz",
"integrity": "sha512-G4JjJ6f9Hb3Zvejj+ewLLKLf99ZC+9v+yCxoYf9vSyH+WkzPLB2LuUtRMGNkooMqdugGBFStIKXOuvH1W+EctA==", "integrity": "sha512-VRYHGQV1rqnROJqdMvGUbY/Kn8vriQe/F9HR2AlYHzmKuM/p3kjNuXhmdBfcVgsvRWTz5C5XW5xvndZrVBuAYg==",
"requires": { "requires": {
"tunnel": "0.0.6" "tunnel": "0.0.6"
} }
@ -14512,10 +14517,10 @@
"integrity": "sha512-FA/BWv8t8ZWJ+gEOnLLd8ygxH/2UFbAvgEonyfN6yWGLKc7zVjbpl2Y4CTjid9h2RfgPP6SEt6uHwEOply00yw==", "integrity": "sha512-FA/BWv8t8ZWJ+gEOnLLd8ygxH/2UFbAvgEonyfN6yWGLKc7zVjbpl2Y4CTjid9h2RfgPP6SEt6uHwEOply00yw==",
"dev": true "dev": true
}, },
"@zeit/ncc": { "@vercel/ncc": {
"version": "0.22.0", "version": "0.33.4",
"resolved": "https://registry.npmjs.org/@zeit/ncc/-/ncc-0.22.0.tgz", "resolved": "https://registry.npmjs.org/@vercel/ncc/-/ncc-0.33.4.tgz",
"integrity": "sha512-zaS6chwztGSLSEzsTJw9sLTYxQt57bPFBtsYlVtbqGvmDUsfW7xgXPYofzFa1kB9ur2dRop6IxCwPnWLBVCrbQ==", "integrity": "sha512-ln18hs7dMffelP47tpkaR+V5Tj6coykNyxJrlcmCormPqRQjB/Gv4cu2FfBG+PMzIfdZp2CLDsrrB1NPU22Qhg==",
"dev": true "dev": true
}, },
"abab": { "abab": {

View File

@ -1,6 +1,6 @@
{ {
"name": "setup-python", "name": "setup-python",
"version": "3.1.0", "version": "4.0.0",
"private": true, "private": true,
"description": "Setup python action", "description": "Setup python action",
"main": "dist/index.js", "main": "dist/index.js",
@ -9,7 +9,7 @@
"format": "prettier --write \"{,!(node_modules)/**/}*.ts\"", "format": "prettier --write \"{,!(node_modules)/**/}*.ts\"",
"format-check": "prettier --check \"{,!(node_modules)/**/}*.ts\"", "format-check": "prettier --check \"{,!(node_modules)/**/}*.ts\"",
"release": "ncc build -o dist/setup src/setup-python.ts && ncc build -o dist/cache-save src/cache-save.ts && git add -f dist/", "release": "ncc build -o dist/setup src/setup-python.ts && ncc build -o dist/cache-save src/cache-save.ts && git add -f dist/",
"test": "jest" "test": "jest --coverage"
}, },
"repository": { "repository": {
"type": "git", "type": "git",
@ -23,8 +23,8 @@
"author": "GitHub", "author": "GitHub",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@actions/cache": "^2.0.0", "@actions/cache": "^3.0.0",
"@actions/core": "^1.2.3", "@actions/core": "^1.7.0",
"@actions/exec": "^1.1.0", "@actions/exec": "^1.1.0",
"@actions/glob": "^0.2.0", "@actions/glob": "^0.2.0",
"@actions/io": "^1.0.2", "@actions/io": "^1.0.2",
@ -35,7 +35,7 @@
"@types/jest": "^27.0.2", "@types/jest": "^27.0.2",
"@types/node": "^16.11.25", "@types/node": "^16.11.25",
"@types/semver": "^7.1.0", "@types/semver": "^7.1.0",
"@zeit/ncc": "^0.22.0", "@vercel/ncc": "^0.33.4",
"husky": "^7.0.2", "husky": "^7.0.2",
"jest": "^27.2.5", "jest": "^27.2.5",
"jest-circus": "^27.2.5", "jest-circus": "^27.2.5",

View File

@ -58,7 +58,7 @@ class PoetryCache extends CacheDistributor {
const config: any = {}; const config: any = {};
for (let line of lines) { for (let line of lines) {
line = line.replace(/#.*$/, ''); line = line.replace(/#.*$/gm, '');
const [key, value] = line.split('=').map(part => part.trim()); const [key, value] = line.split('=').map(part => part.trim());

View File

@ -43,17 +43,11 @@ async function saveCache(packageManager: string) {
return; return;
} }
try { const cacheId = await cache.saveCache(cachePaths, primaryKey);
await cache.saveCache(cachePaths, primaryKey); if (cacheId == -1) {
core.info(`Cache saved with the key: ${primaryKey}`); return;
} catch (error) {
const err = error as Error;
if (err.name === cache.ReserveCacheError.name) {
core.info(err.message);
} else {
throw error;
}
} }
core.info(`Cache saved with the key: ${primaryKey}`);
} }
function isCacheDirectoryExists(cacheDirectory: string[]) { function isCacheDirectoryExists(cacheDirectory: string[]) {

View File

@ -20,7 +20,8 @@ interface IPyPyVersionSpec {
export async function findPyPyVersion( export async function findPyPyVersion(
versionSpec: string, versionSpec: string,
architecture: string architecture: string,
updateEnvironment: boolean
): Promise<{resolvedPyPyVersion: string; resolvedPythonVersion: string}> { ): Promise<{resolvedPyPyVersion: string; resolvedPythonVersion: string}> {
let resolvedPyPyVersion = ''; let resolvedPyPyVersion = '';
let resolvedPythonVersion = ''; let resolvedPythonVersion = '';
@ -48,11 +49,26 @@ export async function findPyPyVersion(
const pipDir = IS_WINDOWS ? 'Scripts' : 'bin'; const pipDir = IS_WINDOWS ? 'Scripts' : 'bin';
const _binDir = path.join(installDir, pipDir); const _binDir = path.join(installDir, pipDir);
const binaryExtension = IS_WINDOWS ? '.exe' : '';
const pythonPath = path.join(
IS_WINDOWS ? installDir : _binDir,
`python${binaryExtension}`
);
const pythonLocation = pypyInstall.getPyPyBinaryPath(installDir); const pythonLocation = pypyInstall.getPyPyBinaryPath(installDir);
core.exportVariable('pythonLocation', pythonLocation); if (updateEnvironment) {
core.addPath(pythonLocation); core.exportVariable('pythonLocation', installDir);
core.addPath(_binDir); // https://cmake.org/cmake/help/latest/module/FindPython.html#module:FindPython
core.exportVariable('Python_ROOT_DIR', installDir);
// https://cmake.org/cmake/help/latest/module/FindPython2.html#module:FindPython2
core.exportVariable('Python2_ROOT_DIR', installDir);
// https://cmake.org/cmake/help/latest/module/FindPython3.html#module:FindPython3
core.exportVariable('Python3_ROOT_DIR', installDir);
core.exportVariable('PKG_CONFIG_PATH', pythonLocation + '/lib/pkgconfig');
core.addPath(pythonLocation);
core.addPath(_binDir);
}
core.setOutput('python-version', 'pypy' + resolvedPyPyVersion.trim()); core.setOutput('python-version', 'pypy' + resolvedPyPyVersion.trim());
core.setOutput('python-path', pythonPath);
return {resolvedPyPyVersion, resolvedPythonVersion}; return {resolvedPyPyVersion, resolvedPythonVersion};
} }
@ -97,9 +113,14 @@ export function findPyPyToolCache(
export function parsePyPyVersion(versionSpec: string): IPyPyVersionSpec { export function parsePyPyVersion(versionSpec: string): IPyPyVersionSpec {
const versions = versionSpec.split('-').filter(item => !!item); const versions = versionSpec.split('-').filter(item => !!item);
if (/^(pypy)(.+)/.test(versions[0])) {
let pythonVersion = versions[0].replace('pypy', '');
versions.splice(0, 1, 'pypy', pythonVersion);
}
if (versions.length < 2 || versions[0] != 'pypy') { if (versions.length < 2 || versions[0] != 'pypy') {
throw new Error( throw new Error(
"Invalid 'version' property for PyPy. PyPy version should be specified as 'pypy-<python-version>'. See README for examples and documentation." "Invalid 'version' property for PyPy. PyPy version should be specified as 'pypy<python-version>' or 'pypy-<python-version>'. See README for examples and documentation."
); );
} }

View File

@ -32,7 +32,8 @@ function binDir(installDir: string): string {
export async function useCpythonVersion( export async function useCpythonVersion(
version: string, version: string,
architecture: string architecture: string,
updateEnvironment: boolean
): Promise<InstalledVersion> { ): Promise<InstalledVersion> {
const desugaredVersionSpec = desugarDevVersion(version); const desugaredVersionSpec = desugarDevVersion(version);
const semanticVersionSpec = pythonVersionToSemantic(desugaredVersionSpec); const semanticVersionSpec = pythonVersionToSemantic(desugaredVersionSpec);
@ -69,54 +70,67 @@ export async function useCpythonVersion(
); );
} }
core.exportVariable('pythonLocation', installDir); const _binDir = binDir(installDir);
const binaryExtension = IS_WINDOWS ? '.exe' : '';
const pythonPath = path.join(
IS_WINDOWS ? installDir : _binDir,
`python${binaryExtension}`
);
if (updateEnvironment) {
core.exportVariable('pythonLocation', installDir);
core.exportVariable('PKG_CONFIG_PATH', installDir + '/lib/pkgconfig');
core.exportVariable('pythonLocation', installDir);
// https://cmake.org/cmake/help/latest/module/FindPython.html#module:FindPython
core.exportVariable('Python_ROOT_DIR', installDir);
// https://cmake.org/cmake/help/latest/module/FindPython2.html#module:FindPython2
core.exportVariable('Python2_ROOT_DIR', installDir);
// https://cmake.org/cmake/help/latest/module/FindPython3.html#module:FindPython3
core.exportVariable('Python3_ROOT_DIR', installDir);
core.exportVariable('PKG_CONFIG_PATH', installDir + '/lib/pkgconfig');
if (IS_LINUX) { if (IS_LINUX) {
const libPath = process.env.LD_LIBRARY_PATH const libPath = process.env.LD_LIBRARY_PATH
? `:${process.env.LD_LIBRARY_PATH}` ? `:${process.env.LD_LIBRARY_PATH}`
: ''; : '';
const pyLibPath = path.join(installDir, 'lib'); const pyLibPath = path.join(installDir, 'lib');
if (!libPath.split(':').includes(pyLibPath)) { if (!libPath.split(':').includes(pyLibPath)) {
core.exportVariable('LD_LIBRARY_PATH', pyLibPath + libPath); core.exportVariable('LD_LIBRARY_PATH', pyLibPath + libPath);
}
} }
core.addPath(installDir);
core.addPath(_binDir);
if (IS_WINDOWS) {
// Add --user directory
// `installDir` from tool cache should look like $RUNNER_TOOL_CACHE/Python/<semantic version>/x64/
// So if `findLocalTool` succeeded above, we must have a conformant `installDir`
const version = path.basename(path.dirname(installDir));
const major = semver.major(version);
const minor = semver.minor(version);
const userScriptsDir = path.join(
process.env['APPDATA'] || '',
'Python',
`Python${major}${minor}`,
'Scripts'
);
core.addPath(userScriptsDir);
}
// On Linux and macOS, pip will create the --user directory and add it to PATH as needed.
} }
core.addPath(installDir);
core.addPath(binDir(installDir));
if (IS_WINDOWS) {
// Add --user directory
// `installDir` from tool cache should look like $RUNNER_TOOL_CACHE/Python/<semantic version>/x64/
// So if `findLocalTool` succeeded above, we must have a conformant `installDir`
const version = path.basename(path.dirname(installDir));
const major = semver.major(version);
const minor = semver.minor(version);
const userScriptsDir = path.join(
process.env['APPDATA'] || '',
'Python',
`Python${major}${minor}`,
'Scripts'
);
core.addPath(userScriptsDir);
}
// On Linux and macOS, pip will create the --user directory and add it to PATH as needed.
const installed = versionFromPath(installDir); const installed = versionFromPath(installDir);
core.setOutput('python-version', installed); core.setOutput('python-version', installed);
core.setOutput('python-path', pythonPath);
return {impl: 'CPython', version: installed}; return {impl: 'CPython', version: installed};
} }
/** Convert versions like `3.8-dev` to a version like `>= 3.8.0-a0`. */ /** Convert versions like `3.8-dev` to a version like `~3.8.0-0`. */
function desugarDevVersion(versionSpec: string) { function desugarDevVersion(versionSpec: string) {
if (versionSpec.endsWith('-dev')) { const devVersion = /^(\d+)\.(\d+)-dev$/;
const versionRoot = versionSpec.slice(0, -'-dev'.length); return versionSpec.replace(devVersion, '~$1.$2.0-0');
return `>= ${versionRoot}.0-a0`;
} else {
return versionSpec;
}
} }
/** Extracts python version from install path from hosted tool cache as described in README.md */ /** Extracts python version from install path from hosted tool cache as described in README.md */

View File

@ -98,7 +98,9 @@ async function createPyPySymlink(
) { ) {
const version = semver.coerce(pythonVersion)!; const version = semver.coerce(pythonVersion)!;
const pythonBinaryPostfix = semver.major(version); const pythonBinaryPostfix = semver.major(version);
const pythonMinor = semver.minor(version);
const pypyBinaryPostfix = pythonBinaryPostfix === 2 ? '' : '3'; const pypyBinaryPostfix = pythonBinaryPostfix === 2 ? '' : '3';
const pypyMajorMinorBinaryPostfix = `${pythonBinaryPostfix}.${pythonMinor}`;
let binaryExtension = IS_WINDOWS ? '.exe' : ''; let binaryExtension = IS_WINDOWS ? '.exe' : '';
core.info('Creating symlinks...'); core.info('Creating symlinks...');
@ -115,6 +117,13 @@ async function createPyPySymlink(
`python${binaryExtension}`, `python${binaryExtension}`,
true true
); );
createSymlinkInFolder(
pypyBinaryPath,
`pypy${pypyBinaryPostfix}${binaryExtension}`,
`pypy${pypyMajorMinorBinaryPostfix}${binaryExtension}`,
true
);
} }
async function installPip(pythonLocation: string) { async function installPip(pythonLocation: string) {

View File

@ -3,11 +3,12 @@ import * as finder from './find-python';
import * as finderPyPy from './find-pypy'; import * as finderPyPy from './find-pypy';
import * as path from 'path'; import * as path from 'path';
import * as os from 'os'; import * as os from 'os';
import fs from 'fs';
import {getCacheDistributor} from './cache-distributions/cache-factory'; import {getCacheDistributor} from './cache-distributions/cache-factory';
import {isCacheFeatureAvailable} from './utils'; import {isCacheFeatureAvailable, IS_LINUX, IS_WINDOWS} from './utils';
function isPyPyVersion(versionSpec: string) { function isPyPyVersion(versionSpec: string) {
return versionSpec.startsWith('pypy-'); return versionSpec.startsWith('pypy');
} }
async function cacheDependencies(cache: string, pythonVersion: string) { async function cacheDependencies(cache: string, pythonVersion: string) {
@ -21,28 +22,89 @@ async function cacheDependencies(cache: string, pythonVersion: string) {
await cacheDistributor.restoreCache(); await cacheDistributor.restoreCache();
} }
function resolveVersionInput(): string {
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.'
);
}
if (version) {
return version;
}
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;
}
core.warning(
"Neither 'python-version' nor 'python-version-file' inputs were supplied."
);
return version;
}
async function run() { async function run() {
// 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'];
}
core.debug(
`Python is expected to be installed into RUNNER_TOOL_CACHE=${process.env['RUNNER_TOOL_CACHE']}`
);
try { try {
const version = core.getInput('python-version'); const version = resolveVersionInput();
if (version) { if (version) {
let pythonVersion: string; let pythonVersion: string;
const arch: string = core.getInput('architecture') || os.arch(); const arch: string = core.getInput('architecture') || os.arch();
const updateEnvironment = core.getBooleanInput('update-environment');
if (isPyPyVersion(version)) { if (isPyPyVersion(version)) {
const installed = await finderPyPy.findPyPyVersion(version, arch); const installed = await finderPyPy.findPyPyVersion(
version,
arch,
updateEnvironment
);
pythonVersion = `${installed.resolvedPyPyVersion}-${installed.resolvedPythonVersion}`; pythonVersion = `${installed.resolvedPyPyVersion}-${installed.resolvedPythonVersion}`;
core.info( core.info(
`Successfully setup PyPy ${installed.resolvedPyPyVersion} with Python (${installed.resolvedPythonVersion})` `Successfully set up PyPy ${installed.resolvedPyPyVersion} with Python (${installed.resolvedPythonVersion})`
); );
} else { } else {
const installed = await finder.useCpythonVersion(version, arch); const installed = await finder.useCpythonVersion(
version,
arch,
updateEnvironment
);
pythonVersion = installed.version; pythonVersion = installed.version;
core.info(`Successfully setup ${installed.impl} (${pythonVersion})`); core.info(`Successfully set up ${installed.impl} (${pythonVersion})`);
} }
const cache = core.getInput('cache'); const cache = core.getInput('cache');
if (cache && isCacheFeatureAvailable()) { if (cache && isCacheFeatureAvailable()) {
await cacheDependencies(cache, pythonVersion); await cacheDependencies(cache, pythonVersion);
} }
} else {
core.warning(
'The `python-version` input is not set. The version of Python currently in `PATH` will be used.'
);
} }
const matchersPath = path.join(__dirname, '../..', '.github'); const matchersPath = path.join(__dirname, '../..', '.github');
core.info(`##[add-matcher]${path.join(matchersPath, 'python.json')}`); core.info(`##[add-matcher]${path.join(matchersPath, 'python.json')}`);
@ -51,4 +113,9 @@ async function run() {
} }
} }
export function logWarning(message: string): void {
const warningPrefix = '[warning]';
core.info(`${warningPrefix}${message}`);
}
run(); run();