mirror of
https://github.com/actions/setup-python.git
synced 2025-06-24 12:41:09 +02:00
Compare commits
2 Commits
Author | SHA1 | Date | |
---|---|---|---|
e9aba2c848 | |||
75f3110429 |
7
.github/workflows/check-dist.yml
vendored
7
.github/workflows/check-dist.yml
vendored
@ -23,11 +23,10 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Set Node.js 16.x
|
||||
uses: actions/setup-node@v3
|
||||
- name: Set Node.js 12.x
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 16.x
|
||||
cache: npm
|
||||
node-version: 12.x
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
1
.github/workflows/codeql-analysis.yml
vendored
1
.github/workflows/codeql-analysis.yml
vendored
@ -2,7 +2,6 @@ name: "Code scanning - action"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ 'main' ]
|
||||
pull_request:
|
||||
schedule:
|
||||
- cron: '25 3 * * 5'
|
||||
|
26
.github/workflows/e2e-cache.yml
vendored
26
.github/workflows/e2e-cache.yml
vendored
@ -48,7 +48,7 @@ jobs:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
cache: 'pipenv'
|
||||
- name: Install pipenv
|
||||
run: curl https://raw.githubusercontent.com/pypa/pipenv/master/get-pipenv.py | python
|
||||
run: curl https://raw.githubusercontent.com/pypa/pipenv/main/get-pipenv.py | python
|
||||
- name: Install dependencies
|
||||
shell: pwsh
|
||||
run: |
|
||||
@ -60,28 +60,6 @@ jobs:
|
||||
pipenv install --keep-outdated --python ${{ matrix.python-version }}
|
||||
}
|
||||
|
||||
python-poetry-dependencies-caching:
|
||||
name: Test poetry (Python ${{ matrix.python-version}}, ${{ matrix.os }})
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest, macos-latest]
|
||||
python-version: ['3.9', 'pypy-3.8']
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Install poetry
|
||||
run: pipx install poetry
|
||||
- name: Setup Python
|
||||
uses: ./
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
cache: 'poetry'
|
||||
- name: Init pyproject.toml
|
||||
run: poetry init -n
|
||||
- name: Install dependencies
|
||||
run: poetry add flake8
|
||||
|
||||
python-pip-dependencies-caching-path:
|
||||
name: Test pip (Python ${{ matrix.python-version}}, ${{ matrix.os }})
|
||||
runs-on: ${{ matrix.os }}
|
||||
@ -118,7 +96,7 @@ jobs:
|
||||
cache: 'pipenv'
|
||||
cache-dependency-path: '**/pipenv-requirements.txt'
|
||||
- name: Install pipenv
|
||||
run: curl https://raw.githubusercontent.com/pypa/pipenv/master/get-pipenv.py | python
|
||||
run: curl https://raw.githubusercontent.com/pypa/pipenv/main/get-pipenv.py | python
|
||||
- name: Install dependencies
|
||||
shell: pwsh
|
||||
run: |
|
||||
|
9
.github/workflows/licensed.yml
vendored
9
.github/workflows/licensed.yml
vendored
@ -14,16 +14,15 @@ jobs:
|
||||
name: Check licenses
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Set Node.js 16.x
|
||||
uses: actions/setup-node@v3
|
||||
- name: Set Node.js 12.x
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: 16.x
|
||||
cache: npm
|
||||
node-version: 12.x
|
||||
- run: npm ci
|
||||
- name: Install licensed
|
||||
run: |
|
||||
cd $RUNNER_TEMP
|
||||
curl -Lfs -o licensed.tar.gz https://github.com/github/licensed/releases/download/3.4.4/licensed-3.4.4-linux-x64.tar.gz
|
||||
curl -Lfs -o licensed.tar.gz https://github.com/github/licensed/releases/download/3.3.1/licensed-3.3.1-linux-x64.tar.gz
|
||||
sudo tar -xzf licensed.tar.gz
|
||||
sudo mv licensed /usr/local/bin/licensed
|
||||
- run: licensed status
|
||||
|
49
.github/workflows/test-pypy.yml
vendored
49
.github/workflows/test-pypy.yml
vendored
@ -18,11 +18,10 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [macos-latest, windows-latest, ubuntu-18.04, ubuntu-latest]
|
||||
os: [macos-latest, windows-latest, ubuntu-latest]
|
||||
pypy:
|
||||
- 'pypy-2.7'
|
||||
- 'pypy-3.7'
|
||||
- 'pypy3.9'
|
||||
- 'pypy-2.7-v7.3.4'
|
||||
- 'pypy-3.7-v7.3.5'
|
||||
- 'pypy-3.7-v7.3.4'
|
||||
@ -30,64 +29,18 @@ jobs:
|
||||
- 'pypy-3.7-v7.x'
|
||||
- 'pypy-2.7-v7.3.4rc1'
|
||||
- 'pypy-3.7-nightly'
|
||||
- 'pypy3.8-v7.3.7'
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: setup-python ${{ matrix.pypy }}
|
||||
id: setup-python
|
||||
uses: ./
|
||||
with:
|
||||
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
|
||||
run: python --version
|
||||
|
||||
- name: Run simple code
|
||||
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))'
|
||||
|
126
.github/workflows/test-python.yml
vendored
126
.github/workflows/test-python.yml
vendored
@ -10,69 +10,45 @@ on:
|
||||
- '**.md'
|
||||
schedule:
|
||||
- cron: 30 3 * * *
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
default-version:
|
||||
name: Setup default version
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [macos-latest, windows-latest, 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:
|
||||
name: Setup ${{ matrix.python }} ${{ matrix.os }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [macos-latest, windows-latest, ubuntu-18.04, ubuntu-20.04]
|
||||
os: [macos-latest, windows-latest, ubuntu-20.04]
|
||||
python: [3.5.4, 3.6.7, 3.7.5, 3.8.1]
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: setup-python ${{ matrix.python }}
|
||||
id: setup-python
|
||||
uses: ./
|
||||
with:
|
||||
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
|
||||
run: |
|
||||
$pythonVersion = (python --version)
|
||||
@ -92,21 +68,16 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [macos-latest, windows-latest, ubuntu-18.04, ubuntu-20.04]
|
||||
os: [macos-latest, windows-latest, ubuntu-20.04]
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: setup-python 3.9.0-beta.4
|
||||
id: setup-python
|
||||
uses: ./
|
||||
with:
|
||||
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
|
||||
run: |
|
||||
$pythonVersion = (python --version)
|
||||
@ -120,55 +91,18 @@ jobs:
|
||||
- name: Run simple code
|
||||
run: python -c 'import math; print(math.factorial(5))'
|
||||
|
||||
setup-dev-version:
|
||||
name: Setup 3.9-dev ${{ matrix.os }}
|
||||
setup-pypy-legacy:
|
||||
name: Setup PyPy ${{ matrix.os }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [macos-latest, windows-latest, ubuntu-latest]
|
||||
os: [macos-11, windows-2019, ubuntu-20.04]
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: setup-python 3.9-dev
|
||||
id: setup-python
|
||||
- name: setup-python pypy3
|
||||
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))'
|
||||
python-version: 'pypy-3.8'
|
||||
|
23
.github/workflows/workflow.yml
vendored
23
.github/workflows/workflow.yml
vendored
@ -14,19 +14,18 @@ jobs:
|
||||
runs-on: ${{ matrix.operating-system }}
|
||||
strategy:
|
||||
matrix:
|
||||
operating-system: [ubuntu-latest, windows-latest]
|
||||
operating-system: [ubuntu-20.04, windows-latest]
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Set Node.js 16.x
|
||||
uses: actions/setup-node@v3
|
||||
- name: Set Node.js 12.x
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 16.x
|
||||
cache: npm
|
||||
node-version: 12.x
|
||||
|
||||
- name: npm ci
|
||||
run: npm ci
|
||||
- name: npm install
|
||||
run: npm install
|
||||
|
||||
- name: Lint
|
||||
run: npm run format-check
|
||||
@ -89,13 +88,3 @@ jobs:
|
||||
python-version: 3.8.1
|
||||
- name: Verify 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
|
||||
|
2
.licenses/npm/@actions/cache.dep.yml
generated
2
.licenses/npm/@actions/cache.dep.yml
generated
@ -1,6 +1,6 @@
|
||||
---
|
||||
name: "@actions/cache"
|
||||
version: 3.0.0
|
||||
version: 1.0.8
|
||||
type: npm
|
||||
summary: Actions cache lib
|
||||
homepage: https://github.com/actions/toolkit/tree/main/packages/cache
|
||||
|
2
.licenses/npm/@actions/core.dep.yml
generated
2
.licenses/npm/@actions/core.dep.yml
generated
@ -1,6 +1,6 @@
|
||||
---
|
||||
name: "@actions/core"
|
||||
version: 1.7.0
|
||||
version: 1.2.6
|
||||
type: npm
|
||||
summary: Actions core lib
|
||||
homepage: https://github.com/actions/toolkit/tree/main/packages/core
|
||||
|
@ -1,6 +1,6 @@
|
||||
---
|
||||
name: "@actions/http-client"
|
||||
version: 2.0.1
|
||||
version: 1.0.8
|
||||
type: npm
|
||||
summary: Actions Http Client
|
||||
homepage: https://github.com/actions/http-client#readme
|
32
.licenses/npm/@actions/http-client.dep.yml
generated
32
.licenses/npm/@actions/http-client.dep.yml
generated
@ -1,32 +0,0 @@
|
||||
---
|
||||
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: []
|
2
.licenses/npm/@types/node.dep.yml
generated
2
.licenses/npm/@types/node.dep.yml
generated
@ -1,6 +1,6 @@
|
||||
---
|
||||
name: "@types/node"
|
||||
version: 16.11.25
|
||||
version: 12.20.36
|
||||
type: npm
|
||||
summary: TypeScript definitions for Node.js
|
||||
homepage: https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/node
|
||||
|
@ -1,76 +0,0 @@
|
||||
# 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
|
198
README.md
198
README.md
@ -1,4 +1,4 @@
|
||||
# setup-python V4
|
||||
# setup-python V2
|
||||
|
||||
<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>
|
||||
@ -9,7 +9,7 @@ This action sets up a Python environment for use in actions by:
|
||||
- optionally installing and adding to PATH a version of Python that is already installed in the tools cache.
|
||||
- downloading, installing and adding to PATH an available version of Python from GitHub Releases ([actions/python-versions](https://github.com/actions/python-versions/releases)) if a specific version is not available in the tools cache.
|
||||
- failing if a specific version of Python is not preinstalled or available for download.
|
||||
- optionally caching dependencies for pip, pipenv and poetry.
|
||||
- optionally caching dependencies for pip and pipenv.
|
||||
- registering problem matchers for error output.
|
||||
|
||||
# What's new
|
||||
@ -19,8 +19,7 @@ This action sets up a Python environment for use in actions by:
|
||||
- Automatic setup and download of Python packages if using a self-hosted runner.
|
||||
- Support for pre-release versions of Python.
|
||||
- Support for installing any version of PyPy on-flight
|
||||
- Support for built-in caching of pip, pipenv and poetry dependencies
|
||||
- Support for `.python-version` file
|
||||
- Support for built-in caching of pip and pipenv dependencies
|
||||
|
||||
# Usage
|
||||
|
||||
@ -29,24 +28,14 @@ See [action.yml](action.yml)
|
||||
Basic:
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-python@v4
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-python@v2
|
||||
with:
|
||||
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
|
||||
- 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:
|
||||
```yaml
|
||||
jobs:
|
||||
@ -54,12 +43,12 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: [ '2.x', '3.x', 'pypy2.7', 'pypy3.7', 'pypy3.8' ]
|
||||
python-version: [ '2.x', '3.x', 'pypy-2.7', 'pypy-3.7', 'pypy-3.8' ]
|
||||
name: Python ${{ matrix.python-version }} sample
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v2
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v4
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
architecture: x64
|
||||
@ -74,16 +63,16 @@ jobs:
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, macos-latest, windows-latest]
|
||||
python-version: ['2.7', '3.7', '3.8', '3.9', '3.10', 'pypy2.7', 'pypy3.8']
|
||||
python-version: ['2.7', '3.7', '3.8', '3.9', '3.10', 'pypy-2.7', 'pypy-3.8']
|
||||
exclude:
|
||||
- os: macos-latest
|
||||
python-version: '3.8'
|
||||
- os: windows-latest
|
||||
python-version: '3.6'
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v2
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v4
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
- name: Display Python version
|
||||
@ -100,8 +89,8 @@ jobs:
|
||||
# in this example, there is a newer version already installed, 3.7.7, so the older version will be downloaded
|
||||
python-version: ['3.7.4', '3.8', '3.9', '3.10']
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-python@v4
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
- run: python my_script.py
|
||||
@ -110,8 +99,8 @@ jobs:
|
||||
Download and set up an accurate pre-release version of Python:
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-python@v4
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: '3.11.0-alpha.1'
|
||||
- run: python my_script.py
|
||||
@ -120,33 +109,13 @@ steps:
|
||||
Download and set up the latest available version of Python (includes both pre-release and stable versions):
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-python@v4
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: '3.11.0-alpha - 3.11.0' # SemVer's version range syntax
|
||||
- run: python my_script.py
|
||||
```
|
||||
|
||||
Download and set up the latest patch version of Python (for specified major & minor versions):
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: '3.11-dev'
|
||||
- run: python my_script.py
|
||||
```
|
||||
|
||||
Download and set up the latest stable version of Python (for specified major version):
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: '3.x'
|
||||
- run: python my_script.py
|
||||
```
|
||||
|
||||
Download and set up PyPy:
|
||||
|
||||
```yaml
|
||||
@ -156,34 +125,18 @@ jobs:
|
||||
strategy:
|
||||
matrix:
|
||||
python-version:
|
||||
- 'pypy3.7' # the latest available version of PyPy that supports Python 3.7
|
||||
- 'pypy3.7-v7.3.3' # Python 3.7 and PyPy 7.3.3
|
||||
- 'pypy3.8' # the latest available version of PyPy that supports Python 3.8
|
||||
- 'pypy-3.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
|
||||
- 'pypy-3.8' # the latest available version of PyPy that supports Python 3.8
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-python@v4
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
- 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.
|
||||
|
||||
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
|
||||
|
||||
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).
|
||||
@ -197,13 +150,10 @@ 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.
|
||||
- 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.
|
||||
- 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)).
|
||||
- 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
|
||||
|
||||
**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
|
||||
|
||||
`setup-python` is able to configure PyPy from two sources:
|
||||
@ -211,7 +161,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
|
||||
- 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.
|
||||
- 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`.
|
||||
- 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`.
|
||||
|
||||
- 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.
|
||||
@ -229,8 +179,8 @@ GitHub hosted runners have a tools cache that comes with a few versions of Pytho
|
||||
|**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.
|
||||
- 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: [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)
|
||||
- [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 Windows](https://github.com/actions/virtual-environments/blob/main/images/win/scripts/Installers/Download-ToolCache.ps1)
|
||||
|
||||
# Specifying a Python version
|
||||
|
||||
@ -244,30 +194,27 @@ 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.
|
||||
|
||||
# Specifying a 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 version of PyPy should be specified in the format `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.
|
||||
|
||||
```
|
||||
pypy3.7 or pypy-3.7 # the latest available version of PyPy that supports Python 3.7
|
||||
pypy3.8 or pypy-3.8 # the latest available version of PyPy that supports Python 3.8
|
||||
pypy2.7 or pypy-2.7 # the latest available version of PyPy that supports Python 2.7
|
||||
pypy3.7-v7.3.3 or pypy-3.7-v7.3.3 # Python 3.7 and PyPy 7.3.3
|
||||
pypy3.7-v7.x or pypy-3.7-v7.x # Python 3.7 and the latest available PyPy 7.x
|
||||
pypy3.7-v7.3.3rc1 or pypy-3.7-v7.3.3rc1 # Python 3.7 and preview version of PyPy
|
||||
pypy3.7-nightly or pypy-3.7-nightly # Python 3.7 and nightly PyPy
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
|
||||
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` and `pipenv`. The `cache` input is optional, and caching is turned off by default.
|
||||
|
||||
The action defaults to searching for a dependency file (`requirements.txt` for pip, `Pipfile.lock` for pipenv or `poetry.lock` for poetry) in the repository, and uses its hash as a part of the cache key. Use `cache-dependency-path` for cases where multiple dependency files are used, they are located in different subdirectories or different files for the hash want to be used.
|
||||
The action defaults to searching for a dependency file (`requirements.txt` for pip or `Pipfile.lock` for pipenv) in the repository, and uses its hash as a part of the cache key. Use `cache-dependency-path` for cases where multiple dependency files are used, they are located in different subdirectories or different files for the hash want to be used.
|
||||
|
||||
- For pip, the action will cache global cache directory
|
||||
- For pipenv, the action will cache virtualenv directory
|
||||
- For poetry, the action will cache virtualenv directory
|
||||
|
||||
**Please Note:** Restored cache will not be used if the requirements.txt file is not updated for a long time and a newer version of the dependency is available that can lead to an increase in total build time.
|
||||
|
||||
@ -277,8 +224,8 @@ The requirements file format allows to specify dependency versions using logical
|
||||
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-python@v4
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: '3.9'
|
||||
cache: 'pip'
|
||||
@ -288,35 +235,21 @@ steps:
|
||||
**Caching pipenv dependencies:**
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-python@v4
|
||||
- uses: actions/checkout@v2
|
||||
- name: Install pipenv
|
||||
run: pipx install pipenv
|
||||
- uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: '3.9'
|
||||
cache: 'pipenv'
|
||||
- name: Install pipenv
|
||||
run: curl https://raw.githubusercontent.com/pypa/pipenv/master/get-pipenv.py | python
|
||||
- run: pipenv install
|
||||
```
|
||||
|
||||
**Caching poetry dependencies:**
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Install poetry
|
||||
run: pipx install poetry
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: '3.9'
|
||||
cache: 'poetry'
|
||||
- run: poetry install
|
||||
- run: poetry run pytest
|
||||
```
|
||||
|
||||
**Using wildcard patterns to cache dependencies**
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-python@v4
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: '3.9'
|
||||
cache: 'pip'
|
||||
@ -327,54 +260,19 @@ steps:
|
||||
**Using a list of file paths to cache dependencies**
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-python@v4
|
||||
- uses: actions/checkout@v2
|
||||
- name: Install pipenv
|
||||
run: pipx install pipenv
|
||||
- uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: '3.9'
|
||||
cache: 'pipenv'
|
||||
cache-dependency-path: |
|
||||
server/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
|
||||
```
|
||||
|
||||
**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
|
||||
|
||||
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.
|
||||
@ -392,7 +290,7 @@ If you are experiencing problems while configuring Python on your self-hosted ru
|
||||
### Linux
|
||||
|
||||
- The Python packages that are downloaded from `actions/python-versions` are originally compiled from source in `/opt/hostedtoolcache/` with the [--enable-shared](https://github.com/actions/python-versions/blob/94f04ae6806c6633c82db94c6406a16e17decd5c/builders/ubuntu-python-builder.psm1#L35) flag, which makes them non-relocatable.
|
||||
- By default runner downloads and install the tools to `/opt/hostedtoolcache`. The environment variable called `AGENT_TOOLSDIRECTORY` can be set to change this location.
|
||||
- Create an environment variable called `AGENT_TOOLSDIRECTORY` and set it to `/opt/hostedtoolcache`. This controls where the runner downloads and installs tools.
|
||||
- In the same shell that your runner is using, type `export AGENT_TOOLSDIRECTORY=/opt/hostedtoolcache`.
|
||||
- A more permanent way of setting the environment variable is to create a `.env` file in the same directory as your runner and to add `AGENT_TOOLSDIRECTORY=/opt/hostedtoolcache`. This ensures the variable is always set if your runner is configured as a service.
|
||||
- Create a directory called `hostedtoolcache` inside `/opt`.
|
||||
|
@ -10,16 +10,6 @@ describe('restore-cache', () => {
|
||||
'd8110e0006d7fb5ee76365d565eef9d37df1d11598b912d3eb66d398d57a1121';
|
||||
const requirementsLinuxHash =
|
||||
'2d0ff7f46b0e120e3d3294db65768b474934242637b9899b873e6283dfd16d7c';
|
||||
const poetryLockHash =
|
||||
'571bf984f8d210e6a97f854e479fdd4a2b5af67b5fdac109ec337a0ea16e7836';
|
||||
const poetryConfigOutput = `
|
||||
cache-dir = "/Users/patrick/Library/Caches/pypoetry"
|
||||
experimental.new-installer = false
|
||||
installer.parallel = true
|
||||
virtualenvs.create = true
|
||||
virtualenvs.in-project = true
|
||||
virtualenvs.path = "{cache-dir}/virtualenvs" # /Users/patrick/Library/Caches/pypoetry/virtualenvs
|
||||
`;
|
||||
|
||||
// core spy
|
||||
let infoSpy: jest.SpyInstance;
|
||||
@ -27,7 +17,6 @@ virtualenvs.path = "{cache-dir}/virtualenvs" # /Users/patrick/Library/Caches/py
|
||||
let debugSpy: jest.SpyInstance;
|
||||
let saveSatetSpy: jest.SpyInstance;
|
||||
let getStateSpy: jest.SpyInstance;
|
||||
let setOutputSpy: jest.SpyInstance;
|
||||
|
||||
// cache spy
|
||||
let restoreCacheSpy: jest.SpyInstance;
|
||||
@ -58,16 +47,10 @@ virtualenvs.path = "{cache-dir}/virtualenvs" # /Users/patrick/Library/Caches/py
|
||||
if (input.includes('pip')) {
|
||||
return {stdout: 'pip', stderr: '', exitCode: 0};
|
||||
}
|
||||
if (input.includes('poetry')) {
|
||||
return {stdout: poetryConfigOutput, stderr: '', exitCode: 0};
|
||||
}
|
||||
|
||||
return {stdout: '', stderr: 'Error occured', exitCode: 2};
|
||||
});
|
||||
|
||||
setOutputSpy = jest.spyOn(core, 'setOutput');
|
||||
setOutputSpy.mockImplementation(input => undefined);
|
||||
|
||||
restoreCacheSpy = jest.spyOn(cache, 'restoreCache');
|
||||
restoreCacheSpy.mockImplementation(
|
||||
(cachePaths: string[], primaryKey: string, restoreKey?: string) => {
|
||||
@ -99,12 +82,11 @@ virtualenvs.path = "{cache-dir}/virtualenvs" # /Users/patrick/Library/Caches/py
|
||||
],
|
||||
['pip', '3.8.12', '__tests__/data/requirements.txt', requirementsHash],
|
||||
['pipenv', '3.9.1', undefined, pipFileLockHash],
|
||||
['pipenv', '3.9.12', '__tests__/data/requirements.txt', requirementsHash],
|
||||
['poetry', '3.9.1', undefined, poetryLockHash]
|
||||
['pipenv', '3.9.12', '__tests__/data/requirements.txt', requirementsHash]
|
||||
])(
|
||||
'restored dependencies for %s by primaryKey',
|
||||
async (packageManager, pythonVersion, dependencyFile, fileHash) => {
|
||||
const cacheDistributor = getCacheDistributor(
|
||||
const cacheDistributor = await getCacheDistributor(
|
||||
packageManager,
|
||||
pythonVersion,
|
||||
dependencyFile
|
||||
@ -130,7 +112,7 @@ virtualenvs.path = "{cache-dir}/virtualenvs" # /Users/patrick/Library/Caches/py
|
||||
dependencyFile,
|
||||
cacheDependencyPath
|
||||
) => {
|
||||
const cacheDistributor = getCacheDistributor(
|
||||
const cacheDistributor = await getCacheDistributor(
|
||||
packageManager,
|
||||
pythonVersion,
|
||||
dependencyFile
|
||||
@ -156,8 +138,7 @@ virtualenvs.path = "{cache-dir}/virtualenvs" # /Users/patrick/Library/Caches/py
|
||||
],
|
||||
['pip', '3.8.12', '__tests__/data/requirements.txt', pipFileLockHash],
|
||||
['pipenv', '3.9.1', undefined, requirementsHash],
|
||||
['pipenv', '3.9.12', '__tests__/data/requirements.txt', requirementsHash],
|
||||
['poetry', '3.9.1', undefined, requirementsHash]
|
||||
['pipenv', '3.9.12', '__tests__/data/requirements.txt', requirementsHash]
|
||||
])(
|
||||
'restored dependencies for %s by primaryKey',
|
||||
async (packageManager, pythonVersion, dependencyFile, fileHash) => {
|
||||
@ -166,24 +147,17 @@ virtualenvs.path = "{cache-dir}/virtualenvs" # /Users/patrick/Library/Caches/py
|
||||
return primaryKey !== fileHash && restoreKey ? pipFileLockHash : '';
|
||||
}
|
||||
);
|
||||
const cacheDistributor = getCacheDistributor(
|
||||
const cacheDistributor = await getCacheDistributor(
|
||||
packageManager,
|
||||
pythonVersion,
|
||||
dependencyFile
|
||||
);
|
||||
await cacheDistributor.restoreCache();
|
||||
let result = '';
|
||||
|
||||
switch (packageManager) {
|
||||
case 'pip':
|
||||
if (packageManager !== 'pipenv') {
|
||||
result = `Cache restored from key: ${fileHash}`;
|
||||
break;
|
||||
case 'pipenv':
|
||||
} else {
|
||||
result = 'pipenv cache is not found';
|
||||
break;
|
||||
case 'poetry':
|
||||
result = 'poetry cache is not found';
|
||||
break;
|
||||
}
|
||||
|
||||
expect(infoSpy).toHaveBeenCalledWith(result);
|
||||
@ -191,38 +165,6 @@ virtualenvs.path = "{cache-dir}/virtualenvs" # /Users/patrick/Library/Caches/py
|
||||
);
|
||||
});
|
||||
|
||||
describe('Check if handleMatchResult', () => {
|
||||
it.each([
|
||||
['pip', '3.8.12', 'requirements.txt', 'someKey', 'someKey', true],
|
||||
['pipenv', '3.9.1', 'requirements.txt', 'someKey', 'someKey', true],
|
||||
['poetry', '3.8.12', 'requirements.txt', 'someKey', 'someKey', true],
|
||||
['pip', '3.9.2', 'requirements.txt', undefined, 'someKey', false],
|
||||
['pipenv', '3.8.12', 'requirements.txt', undefined, 'someKey', false],
|
||||
['poetry', '3.9.12', 'requirements.txt', undefined, 'someKey', false]
|
||||
])(
|
||||
'sets correct outputs',
|
||||
async (
|
||||
packageManager,
|
||||
pythonVersion,
|
||||
dependencyFile,
|
||||
matchedKey,
|
||||
restoredKey,
|
||||
expectedOutputValue
|
||||
) => {
|
||||
const cacheDistributor = getCacheDistributor(
|
||||
packageManager,
|
||||
pythonVersion,
|
||||
dependencyFile
|
||||
);
|
||||
cacheDistributor.handleMatchResult(matchedKey, restoredKey);
|
||||
expect(setOutputSpy).toHaveBeenCalledWith(
|
||||
'cache-hit',
|
||||
expectedOutputValue
|
||||
);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.resetAllMocks();
|
||||
jest.clearAllMocks();
|
||||
|
@ -6,13 +6,11 @@ import {State} from '../src/cache-distributions/cache-distributor';
|
||||
|
||||
describe('run', () => {
|
||||
const pipFileLockHash =
|
||||
'd1dd6218299d8a6db5fc2001d988b34a8b31f1e9d0bb4534d377dde7c19f64b3';
|
||||
'67d817abcde9c72da0ed5b8f235647cb14638b9ff9d742b42e4406d2eb16fe3c';
|
||||
const requirementsHash =
|
||||
'd8110e0006d7fb5ee76365d565eef9d37df1d11598b912d3eb66d398d57a1121';
|
||||
const requirementsLinuxHash =
|
||||
'2d0ff7f46b0e120e3d3294db65768b474934242637b9899b873e6283dfd16d7c';
|
||||
const poetryLockHash =
|
||||
'571bf984f8d210e6a97f854e479fdd4a2b5af67b5fdac109ec337a0ea16e7836';
|
||||
|
||||
// core spy
|
||||
let infoSpy: jest.SpyInstance;
|
||||
@ -116,22 +114,6 @@ describe('run', () => {
|
||||
);
|
||||
expect(setFailedSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should not save cache for pipenv', async () => {
|
||||
inputs['cache'] = 'pipenv';
|
||||
|
||||
await run();
|
||||
|
||||
expect(getInputSpy).toHaveBeenCalled();
|
||||
expect(debugSpy).toHaveBeenCalledWith(
|
||||
`paths for caching are ${__dirname}`
|
||||
);
|
||||
expect(getStateSpy).toHaveBeenCalledTimes(3);
|
||||
expect(infoSpy).toHaveBeenCalledWith(
|
||||
`Cache hit occurred on the primary key ${requirementsHash}, not saving cache.`
|
||||
);
|
||||
expect(setFailedSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('action saves the cache', () => {
|
||||
@ -186,85 +168,6 @@ describe('run', () => {
|
||||
);
|
||||
expect(setFailedSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('saves cache from poetry', async () => {
|
||||
inputs['cache'] = 'poetry';
|
||||
getStateSpy.mockImplementation((name: string) => {
|
||||
if (name === State.CACHE_MATCHED_KEY) {
|
||||
return poetryLockHash;
|
||||
} else if (name === State.CACHE_PATHS) {
|
||||
return JSON.stringify([__dirname]);
|
||||
} else {
|
||||
return requirementsHash;
|
||||
}
|
||||
});
|
||||
|
||||
await run();
|
||||
|
||||
expect(getInputSpy).toHaveBeenCalled();
|
||||
expect(getStateSpy).toHaveBeenCalledTimes(3);
|
||||
expect(infoSpy).not.toHaveBeenCalledWith(
|
||||
`Cache hit occurred on the primary key ${poetryLockHash}, not saving cache.`
|
||||
);
|
||||
expect(saveCacheSpy).toHaveBeenCalled();
|
||||
expect(infoSpy).toHaveBeenLastCalledWith(
|
||||
`Cache saved with the key: ${requirementsHash}`
|
||||
);
|
||||
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(() => {
|
||||
|
@ -1,14 +0,0 @@
|
||||
#!/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}"
|
413
__tests__/data/poetry.lock
generated
413
__tests__/data/poetry.lock
generated
@ -1,413 +0,0 @@
|
||||
[[package]]
|
||||
name = "altgraph"
|
||||
version = "0.17.2"
|
||||
description = "Python graph (network) package"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
|
||||
[[package]]
|
||||
name = "certifi"
|
||||
version = "2020.6.20"
|
||||
description = "Python package for providing Mozilla's CA Bundle."
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
|
||||
[[package]]
|
||||
name = "chardet"
|
||||
version = "3.0.4"
|
||||
description = "Universal encoding detector for Python 2 and 3"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
|
||||
[[package]]
|
||||
name = "dis3"
|
||||
version = "0.1.3"
|
||||
description = "Python 2.7 backport of the \"dis\" module from Python 3.5+"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
|
||||
[[package]]
|
||||
name = "docutils"
|
||||
version = "0.16"
|
||||
description = "Docutils -- Python Documentation Utilities"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
|
||||
|
||||
[[package]]
|
||||
name = "future"
|
||||
version = "0.18.2"
|
||||
description = "Clean single-source support for Python 3 and 2"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
|
||||
|
||||
[[package]]
|
||||
name = "idna"
|
||||
version = "2.9"
|
||||
description = "Internationalized Domain Names in Applications (IDNA)"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
|
||||
|
||||
[[package]]
|
||||
name = "itsdangerous"
|
||||
version = "1.1.0"
|
||||
description = "Various helpers to pass data to untrusted environments and back."
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
|
||||
|
||||
[[package]]
|
||||
name = "kivy"
|
||||
version = "1.11.1"
|
||||
description = "A software library for rapid development of hardware-accelerated multitouch applications."
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
|
||||
[package.dependencies]
|
||||
docutils = "*"
|
||||
Kivy-Garden = ">=0.1.4"
|
||||
pygments = "*"
|
||||
|
||||
[package.extras]
|
||||
tuio = ["oscpy"]
|
||||
|
||||
[[package]]
|
||||
name = "kivy-deps.angle"
|
||||
version = "0.3.0"
|
||||
description = "Repackaged binary dependency of Kivy."
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
|
||||
[[package]]
|
||||
name = "kivy-deps.glew"
|
||||
version = "0.1.12"
|
||||
description = "Repackaged binary dependency of Kivy."
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
|
||||
[[package]]
|
||||
name = "kivy-deps.gstreamer"
|
||||
version = "0.1.17"
|
||||
description = "Repackaged binary dependency of Kivy."
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
|
||||
[[package]]
|
||||
name = "kivy-deps.sdl2"
|
||||
version = "0.1.22"
|
||||
description = "Repackaged binary dependency of Kivy."
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
|
||||
[[package]]
|
||||
name = "kivy-garden"
|
||||
version = "0.1.4"
|
||||
description = "Garden tool for kivy flowers."
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
|
||||
[package.dependencies]
|
||||
requests = "*"
|
||||
|
||||
[[package]]
|
||||
name = "packaging"
|
||||
version = "21.0"
|
||||
description = "Core utilities for Python packages"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
|
||||
[package.dependencies]
|
||||
pyparsing = ">=2.0.2"
|
||||
|
||||
[[package]]
|
||||
name = "pdf2image"
|
||||
version = "1.12.1"
|
||||
description = "A wrapper around the pdftoppm and pdftocairo command line tools to convert PDF to a PIL Image list."
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
|
||||
[package.dependencies]
|
||||
pillow = "*"
|
||||
|
||||
[[package]]
|
||||
name = "pefile"
|
||||
version = "2021.9.3"
|
||||
description = "Python PE parsing module"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.6.0"
|
||||
|
||||
[package.dependencies]
|
||||
future = "*"
|
||||
|
||||
[[package]]
|
||||
name = "pillow"
|
||||
version = "7.2.0"
|
||||
description = "Python Imaging Library (Fork)"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.5"
|
||||
|
||||
[[package]]
|
||||
name = "pygments"
|
||||
version = "2.6.1"
|
||||
description = "Pygments is a syntax highlighting package written in Python."
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.5"
|
||||
|
||||
[[package]]
|
||||
name = "pyinstaller"
|
||||
version = "3.6"
|
||||
description = "PyInstaller bundles a Python application and all its dependencies into a single package."
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
|
||||
|
||||
[package.dependencies]
|
||||
altgraph = "*"
|
||||
dis3 = "*"
|
||||
|
||||
[[package]]
|
||||
name = "pyparsing"
|
||||
version = "2.4.7"
|
||||
description = "Python parsing module"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
|
||||
|
||||
[[package]]
|
||||
name = "pywin32-ctypes"
|
||||
version = "0.2.0"
|
||||
description = ""
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
|
||||
[[package]]
|
||||
name = "requests"
|
||||
version = "2.24.0"
|
||||
description = "Python HTTP for Humans."
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
|
||||
|
||||
[package.dependencies]
|
||||
certifi = ">=2017.4.17"
|
||||
chardet = ">=3.0.2,<4"
|
||||
idna = ">=2.5,<3"
|
||||
urllib3 = ">=1.21.1,<1.25.0 || >1.25.0,<1.25.1 || >1.25.1,<1.26"
|
||||
|
||||
[package.extras]
|
||||
security = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)"]
|
||||
socks = ["PySocks (>=1.5.6,!=1.5.7)", "win-inet-pton"]
|
||||
|
||||
[[package]]
|
||||
name = "urllib3"
|
||||
version = "1.25.9"
|
||||
description = "HTTP library with thread-safe connection pooling, file post, and more."
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4"
|
||||
|
||||
[package.extras]
|
||||
brotli = ["brotlipy (>=0.6.0)"]
|
||||
secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "pyOpenSSL (>=0.14)", "ipaddress"]
|
||||
socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"]
|
||||
|
||||
[[package]]
|
||||
name = "xlrd"
|
||||
version = "1.2.0"
|
||||
description = "Library for developers to extract data from Microsoft Excel (tm) spreadsheet files"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
|
||||
|
||||
[metadata]
|
||||
lock-version = "1.1"
|
||||
python-versions = "^3.8"
|
||||
content-hash = "b3d607363c6daf2b5448aa5ee676cff28606af6200d8e9b42e89937a190a3d46"
|
||||
|
||||
[metadata.files]
|
||||
altgraph = [
|
||||
{file = "altgraph-0.17.2-py2.py3-none-any.whl", hash = "sha256:743628f2ac6a7c26f5d9223c91ed8ecbba535f506f4b6f558885a8a56a105857"},
|
||||
{file = "altgraph-0.17.2.tar.gz", hash = "sha256:ebf2269361b47d97b3b88e696439f6e4cbc607c17c51feb1754f90fb79839158"},
|
||||
]
|
||||
certifi = [
|
||||
{file = "certifi-2020.6.20-py2.py3-none-any.whl", hash = "sha256:8fc0819f1f30ba15bdb34cceffb9ef04d99f420f68eb75d901e9560b8749fc41"},
|
||||
{file = "certifi-2020.6.20.tar.gz", hash = "sha256:5930595817496dd21bb8dc35dad090f1c2cd0adfaf21204bf6732ca5d8ee34d3"},
|
||||
]
|
||||
chardet = [
|
||||
{file = "chardet-3.0.4-py2.py3-none-any.whl", hash = "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"},
|
||||
{file = "chardet-3.0.4.tar.gz", hash = "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae"},
|
||||
]
|
||||
dis3 = [
|
||||
{file = "dis3-0.1.3-py2-none-any.whl", hash = "sha256:61f7720dd0d8749d23fda3d7227ce74d73da11c2fade993a67ab2f9852451b14"},
|
||||
{file = "dis3-0.1.3-py3-none-any.whl", hash = "sha256:30b6412d33d738663e8ded781b138f4b01116437f0872aa56aa3adba6aeff218"},
|
||||
{file = "dis3-0.1.3.tar.gz", hash = "sha256:9259b881fc1df02ed12ac25f82d4a85b44241854330b1a651e40e0c675cb2d1e"},
|
||||
]
|
||||
docutils = [
|
||||
{file = "docutils-0.16-py2.py3-none-any.whl", hash = "sha256:0c5b78adfbf7762415433f5515cd5c9e762339e23369dbe8000d84a4bf4ab3af"},
|
||||
{file = "docutils-0.16.tar.gz", hash = "sha256:c2de3a60e9e7d07be26b7f2b00ca0309c207e06c100f9cc2a94931fc75a478fc"},
|
||||
]
|
||||
future = [
|
||||
{file = "future-0.18.2.tar.gz", hash = "sha256:b1bead90b70cf6ec3f0710ae53a525360fa360d306a86583adc6bf83a4db537d"},
|
||||
]
|
||||
idna = [
|
||||
{file = "idna-2.9-py2.py3-none-any.whl", hash = "sha256:a068a21ceac8a4d63dbfd964670474107f541babbd2250d61922f029858365fa"},
|
||||
{file = "idna-2.9.tar.gz", hash = "sha256:7588d1c14ae4c77d74036e8c22ff447b26d0fde8f007354fd48a7814db15b7cb"},
|
||||
]
|
||||
itsdangerous = [
|
||||
{file = "itsdangerous-1.1.0-py2.py3-none-any.whl", hash = "sha256:b12271b2047cb23eeb98c8b5622e2e5c5e9abd9784a153e9d8ef9cb4dd09d749"},
|
||||
{file = "itsdangerous-1.1.0.tar.gz", hash = "sha256:321b033d07f2a4136d3ec762eac9f16a10ccd60f53c0c91af90217ace7ba1f19"},
|
||||
]
|
||||
kivy = [
|
||||
{file = "Kivy-1.11.1-cp27-cp27m-macosx_10_6_intel.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:11e85eaf6efbfa2362a3334ffdad179a1b0ca8d255cca79eaa6a2765560d4982"},
|
||||
{file = "Kivy-1.11.1-cp27-cp27m-win32.whl", hash = "sha256:5c3d0f2749522d62e9cce09cd54b2d823bf1b6b644ff1f627be49de6f3e3cba0"},
|
||||
{file = "Kivy-1.11.1-cp27-cp27m-win_amd64.whl", hash = "sha256:f835462dd9aa491272552ef079b948a088598e2e95d68bb1d885d2c3f3d4e2c3"},
|
||||
{file = "Kivy-1.11.1-cp35-cp35m-macosx_10_6_intel.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:090d3ded9835a17477cd93fbdaf0a7c42ff2218981cf198ded5ad8795bc74391"},
|
||||
{file = "Kivy-1.11.1-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:b85ccf165050cbf2ee8447671eebbc222b369b40f0e0038dd9547d49a5e37373"},
|
||||
{file = "Kivy-1.11.1-cp35-cp35m-win32.whl", hash = "sha256:4a5480cbf837d3780c77a4f61b32b56d22ae9f03845e7a89dd3eaef1ae5fd037"},
|
||||
{file = "Kivy-1.11.1-cp35-cp35m-win_amd64.whl", hash = "sha256:a687602d90c4629dd036f577ca39acb76ba581370f9d915f3cab99be818ba8ad"},
|
||||
{file = "Kivy-1.11.1-cp36-cp36m-macosx_10_6_intel.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:c36652caa7f6c327dee834cfc699d5962d346b7a53e54bd81abc17c314226d89"},
|
||||
{file = "Kivy-1.11.1-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:b7ef6aad43a86d8df3fb865db864e354f2155a748019f8517f69f65c1a29cb64"},
|
||||
{file = "Kivy-1.11.1-cp36-cp36m-win32.whl", hash = "sha256:f3bea6e4a21991827885d04127fc6d09a0e974ecfa12da7bf5faae93562ea102"},
|
||||
{file = "Kivy-1.11.1-cp36-cp36m-win_amd64.whl", hash = "sha256:ece170514db3f49844a41e4c910ad9ce9bc46da6f47a49158e11266bdcc6e479"},
|
||||
{file = "Kivy-1.11.1-cp37-cp37m-macosx_10_6_intel.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:8819a27a09871af451760cb69486ced52e830c8a0a37480f22ef5e692f12c05b"},
|
||||
{file = "Kivy-1.11.1-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:1a1ff32f8a95f1e175198cbab81fcd2596783b180d4eafe63e87d171aa7fdb5e"},
|
||||
{file = "Kivy-1.11.1-cp37-cp37m-win32.whl", hash = "sha256:815a5c0b3b72fcd81ca7b2aa0744087163ed03e4cf9ab4e7c9733cea99fc1571"},
|
||||
{file = "Kivy-1.11.1-cp37-cp37m-win_amd64.whl", hash = "sha256:1d28b198a64c30db8d94a0488e85f3037af60d514ab0d7ad5ab45add3ab77090"},
|
||||
{file = "Kivy-1.11.1.tar.gz", hash = "sha256:4d0e596f74271e901b551f77661dde238df4765484fce9f5d1c72e8022984e84"},
|
||||
]
|
||||
"kivy-deps.angle" = [
|
||||
{file = "kivy_deps.angle-0.3.0-cp310-cp310-win32.whl", hash = "sha256:7b56477c726e361592f794d49b2fdd96d579b7efd7225a8aadf7fd01d4e8cb80"},
|
||||
{file = "kivy_deps.angle-0.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:a4b78fd9d47c76e5ff52fcbaa040920a2f97bff038f4c534346dd833dc8f3145"},
|
||||
{file = "kivy_deps.angle-0.3.0-cp36-cp36m-win32.whl", hash = "sha256:a2cea09e8a5e899629466403fbd540459f1cdef8d08c6c479b6607b95309be02"},
|
||||
{file = "kivy_deps.angle-0.3.0-cp36-cp36m-win_amd64.whl", hash = "sha256:b167e19b3eea55a9a8c606a607bb909ec1bedda88deee40347c780b310155a79"},
|
||||
{file = "kivy_deps.angle-0.3.0-cp37-cp37m-win32.whl", hash = "sha256:d0e7b7b9eb9669837a5d70808a7ea45f2b61961b56f9f69a233bad6bd36ce260"},
|
||||
{file = "kivy_deps.angle-0.3.0-cp37-cp37m-win_amd64.whl", hash = "sha256:b9d07976b0bf6bac724a42aa8ed5a8c7caa95609046db30c8f15bb731f8e4d36"},
|
||||
{file = "kivy_deps.angle-0.3.0-cp38-cp38-win32.whl", hash = "sha256:99c40d53582a958748e251dfbd61aa67fb85963e27529ca08a21f2f5eeed04e1"},
|
||||
{file = "kivy_deps.angle-0.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:50605fdd4c9fdbe9f717069734a598a9aba0afe5d3f0412afbe2ecff0326e92d"},
|
||||
{file = "kivy_deps.angle-0.3.0-cp39-cp39-win32.whl", hash = "sha256:64ac7f33c000585dc30194e604aed925972c6b7c3848b5c3b073ae916fb0b55c"},
|
||||
{file = "kivy_deps.angle-0.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:bb4d53f15a093214adbbe205c108ede5cc0f6af6eff104c1b8c468ddaaf6400a"},
|
||||
]
|
||||
"kivy-deps.glew" = [
|
||||
{file = "kivy_deps.glew-0.1.12-cp27-cp27m-win32.whl", hash = "sha256:92e72fa2c425887987d1aa861c99537033dc20d68ae1c54864871f0401682586"},
|
||||
{file = "kivy_deps.glew-0.1.12-cp27-cp27m-win_amd64.whl", hash = "sha256:c843104690c0c8f3a58105c53c57f31506f6f90562c18de00bd19317cc1045a7"},
|
||||
{file = "kivy_deps.glew-0.1.12-cp35-cp35m-win32.whl", hash = "sha256:ee8ab67abb2c98d84feede657cae472e7723e529af07394244bdd33caafb1a38"},
|
||||
{file = "kivy_deps.glew-0.1.12-cp35-cp35m-win_amd64.whl", hash = "sha256:ab81783a82bef88a8d2bcf8a93bc21df6b8b0db6ee551eb802727d18f9074b17"},
|
||||
{file = "kivy_deps.glew-0.1.12-cp36-cp36m-win32.whl", hash = "sha256:45aa7f0e8d9bcf5fc1810c9c38bc20edf7dee61df81ecf62102e0f84153f924a"},
|
||||
{file = "kivy_deps.glew-0.1.12-cp36-cp36m-win_amd64.whl", hash = "sha256:ef1116d99bd9cc737cb8c0e13e676955c17d6e4d6d1af5cfccef089a430071bb"},
|
||||
{file = "kivy_deps.glew-0.1.12-cp37-cp37m-win32.whl", hash = "sha256:1e28e40017af9d081fc0fc95b4fadaf31d15e9f63478dcee1c4257d67079894e"},
|
||||
{file = "kivy_deps.glew-0.1.12-cp37-cp37m-win_amd64.whl", hash = "sha256:6bb435620c3187d2c61054adb9ec277ed487256b457a0a7b1491bc0cb7247e18"},
|
||||
{file = "kivy_deps.glew-0.1.12-cp38-cp38-win32.whl", hash = "sha256:09f72ee5ef33ff273332e2a229dc97d650d29818a0189339421949e4e0f63d93"},
|
||||
{file = "kivy_deps.glew-0.1.12-cp38-cp38-win_amd64.whl", hash = "sha256:cf351aad171796f8051af8e49ec430a9aa128d8557d8643e73f2bb1e5f9c2dab"},
|
||||
]
|
||||
"kivy-deps.gstreamer" = [
|
||||
{file = "kivy_deps.gstreamer-0.1.17-cp27-cp27m-win32.whl", hash = "sha256:309eca64dee5939f16f8465e5cbb08bdde7c90ded1af6a00690c7e928326af79"},
|
||||
{file = "kivy_deps.gstreamer-0.1.17-cp27-cp27m-win_amd64.whl", hash = "sha256:0d9598d2d31c0e780adf4b767fa3a691123621fd0ffef94b83cf82c2da84341b"},
|
||||
{file = "kivy_deps.gstreamer-0.1.17-cp35-cp35m-win32.whl", hash = "sha256:4f2ddd61d185310258d338ae80a646df7822efdd7d67e57f49dc7b87555c5d7e"},
|
||||
{file = "kivy_deps.gstreamer-0.1.17-cp35-cp35m-win_amd64.whl", hash = "sha256:6fa9f76afe600baa221abee31ce7dc63e653d0affe0f6c558bfc4f35af96396f"},
|
||||
{file = "kivy_deps.gstreamer-0.1.17-cp36-cp36m-win32.whl", hash = "sha256:c4709765e2b17c6c96b46a92207b0457def147544d825654077603eaf0d424de"},
|
||||
{file = "kivy_deps.gstreamer-0.1.17-cp36-cp36m-win_amd64.whl", hash = "sha256:c29cfc63fe70a58dad889e631f1ba4711c9ea80103f2b2b8d670a97f093076c8"},
|
||||
{file = "kivy_deps.gstreamer-0.1.17-cp37-cp37m-win32.whl", hash = "sha256:4d996377111e854b3dea90846f9b2f98766a44529fd8b72125e18c552381d928"},
|
||||
{file = "kivy_deps.gstreamer-0.1.17-cp37-cp37m-win_amd64.whl", hash = "sha256:739cd331b9f33a822d700273674a79a3157054e9358a01a0d553f094a5f4a8c9"},
|
||||
{file = "kivy_deps.gstreamer-0.1.17-cp38-cp38-win_amd64.whl", hash = "sha256:3d53d2c84c0a997c4cac6c239b1e0a6486e533836321003dc365ec42b97a664b"},
|
||||
]
|
||||
"kivy-deps.sdl2" = [
|
||||
{file = "kivy_deps.sdl2-0.1.22-cp27-cp27m-win32.whl", hash = "sha256:1b987bdd4fbbcb31baf0d7fc9584ad99912179b8968311bb7e30fbeb14e98e0d"},
|
||||
{file = "kivy_deps.sdl2-0.1.22-cp27-cp27m-win_amd64.whl", hash = "sha256:228128cdd8112dc7505ac43027a770476e9ef282e0b84ca68037133cd025960b"},
|
||||
{file = "kivy_deps.sdl2-0.1.22-cp35-cp35m-win32.whl", hash = "sha256:053f26e8c05d5545bdbc7eeb8c450b8e4410ee355792e9345af536110fe247e2"},
|
||||
{file = "kivy_deps.sdl2-0.1.22-cp35-cp35m-win_amd64.whl", hash = "sha256:5ce23f1a3286d6288751a12b0eaefd02f947ea101bb807e9781b964e496fc3f3"},
|
||||
{file = "kivy_deps.sdl2-0.1.22-cp36-cp36m-win32.whl", hash = "sha256:96e1fa89fd8b5351f2d3c26bbffd50df8d554b03fba4025ecc941d773d241698"},
|
||||
{file = "kivy_deps.sdl2-0.1.22-cp36-cp36m-win_amd64.whl", hash = "sha256:c3ace0ddde0e59cdcaf260eda1daa0c05ca9bf8cd0c4ea404539de25a5dcaec7"},
|
||||
{file = "kivy_deps.sdl2-0.1.22-cp37-cp37m-win32.whl", hash = "sha256:7928746eaed51944c10d1bb36fcefebe3d1aff1b97ba32359c2c97ba74707e1b"},
|
||||
{file = "kivy_deps.sdl2-0.1.22-cp37-cp37m-win_amd64.whl", hash = "sha256:2c2fd5a12a7a9afe3bb962b273561099a180edae91bb9c8f8386b72253fcae4a"},
|
||||
{file = "kivy_deps.sdl2-0.1.22-cp38-cp38-win32.whl", hash = "sha256:9270fa8ed5130074b167a7a3a9c85efc3cfe3c04584ab084cb6ae9e4edfa8168"},
|
||||
{file = "kivy_deps.sdl2-0.1.22-cp38-cp38-win_amd64.whl", hash = "sha256:92ed97d3247bc8ce98f336cbc940bb889310199326e9ccf251c49ae7e4b80de8"},
|
||||
]
|
||||
kivy-garden = [
|
||||
{file = "Kivy Garden-0.1.4.tar.gz", hash = "sha256:9b7d9de5efacbcd0c4b3dd873b30622a86093c9965aa47b523c7a32f3eb34610"},
|
||||
{file = "kivy-garden-0.1.4.tar.gz", hash = "sha256:c256f42788421273a08fbb0a228f0fb0e80dd86b629fb8c0920507f645be6c72"},
|
||||
]
|
||||
packaging = [
|
||||
{file = "packaging-21.0-py3-none-any.whl", hash = "sha256:c86254f9220d55e31cc94d69bade760f0847da8000def4dfe1c6b872fd14ff14"},
|
||||
{file = "packaging-21.0.tar.gz", hash = "sha256:7dc96269f53a4ccec5c0670940a4281106dd0bb343f47b7471f779df49c2fbe7"},
|
||||
]
|
||||
pdf2image = [
|
||||
{file = "pdf2image-1.12.1.tar.gz", hash = "sha256:a0d9906f5507192210a8d5d7ead63145e9dec4bccc4564b1fb644e923913c31c"},
|
||||
]
|
||||
pefile = [
|
||||
{file = "pefile-2021.9.3.tar.gz", hash = "sha256:344a49e40a94e10849f0fe34dddc80f773a12b40675bf2f7be4b8be578bdd94a"},
|
||||
]
|
||||
pillow = [
|
||||
{file = "Pillow-7.2.0-cp35-cp35m-macosx_10_10_intel.whl", hash = "sha256:1ca594126d3c4def54babee699c055a913efb01e106c309fa6b04405d474d5ae"},
|
||||
{file = "Pillow-7.2.0-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:c92302a33138409e8f1ad16731568c55c9053eee71bb05b6b744067e1b62380f"},
|
||||
{file = "Pillow-7.2.0-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:8dad18b69f710bf3a001d2bf3afab7c432785d94fcf819c16b5207b1cfd17d38"},
|
||||
{file = "Pillow-7.2.0-cp35-cp35m-manylinux2014_aarch64.whl", hash = "sha256:431b15cffbf949e89df2f7b48528be18b78bfa5177cb3036284a5508159492b5"},
|
||||
{file = "Pillow-7.2.0-cp35-cp35m-win32.whl", hash = "sha256:09d7f9e64289cb40c2c8d7ad674b2ed6105f55dc3b09aa8e4918e20a0311e7ad"},
|
||||
{file = "Pillow-7.2.0-cp35-cp35m-win_amd64.whl", hash = "sha256:0295442429645fa16d05bd567ef5cff178482439c9aad0411d3f0ce9b88b3a6f"},
|
||||
{file = "Pillow-7.2.0-cp36-cp36m-macosx_10_10_x86_64.whl", hash = "sha256:ec29604081f10f16a7aea809ad42e27764188fc258b02259a03a8ff7ded3808d"},
|
||||
{file = "Pillow-7.2.0-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:612cfda94e9c8346f239bf1a4b082fdd5c8143cf82d685ba2dba76e7adeeb233"},
|
||||
{file = "Pillow-7.2.0-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:0a80dd307a5d8440b0a08bd7b81617e04d870e40a3e46a32d9c246e54705e86f"},
|
||||
{file = "Pillow-7.2.0-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:06aba4169e78c439d528fdeb34762c3b61a70813527a2c57f0540541e9f433a8"},
|
||||
{file = "Pillow-7.2.0-cp36-cp36m-win32.whl", hash = "sha256:f7e30c27477dffc3e85c2463b3e649f751789e0f6c8456099eea7ddd53be4a8a"},
|
||||
{file = "Pillow-7.2.0-cp36-cp36m-win_amd64.whl", hash = "sha256:ffe538682dc19cc542ae7c3e504fdf54ca7f86fb8a135e59dd6bc8627eae6cce"},
|
||||
{file = "Pillow-7.2.0-cp37-cp37m-macosx_10_10_x86_64.whl", hash = "sha256:94cf49723928eb6070a892cb39d6c156f7b5a2db4e8971cb958f7b6b104fb4c4"},
|
||||
{file = "Pillow-7.2.0-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:6edb5446f44d901e8683ffb25ebdfc26988ee813da3bf91e12252b57ac163727"},
|
||||
{file = "Pillow-7.2.0-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:52125833b070791fcb5710fabc640fc1df07d087fc0c0f02d3661f76c23c5b8b"},
|
||||
{file = "Pillow-7.2.0-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:9ad7f865eebde135d526bb3163d0b23ffff365cf87e767c649550964ad72785d"},
|
||||
{file = "Pillow-7.2.0-cp37-cp37m-win32.whl", hash = "sha256:c79f9c5fb846285f943aafeafda3358992d64f0ef58566e23484132ecd8d7d63"},
|
||||
{file = "Pillow-7.2.0-cp37-cp37m-win_amd64.whl", hash = "sha256:d350f0f2c2421e65fbc62690f26b59b0bcda1b614beb318c81e38647e0f673a1"},
|
||||
{file = "Pillow-7.2.0-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:6d7741e65835716ceea0fd13a7d0192961212fd59e741a46bbed7a473c634ed6"},
|
||||
{file = "Pillow-7.2.0-cp38-cp38-manylinux1_i686.whl", hash = "sha256:edf31f1150778abd4322444c393ab9c7bd2af271dd4dafb4208fb613b1f3cdc9"},
|
||||
{file = "Pillow-7.2.0-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:d08b23fdb388c0715990cbc06866db554e1822c4bdcf6d4166cf30ac82df8c41"},
|
||||
{file = "Pillow-7.2.0-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:5e51ee2b8114def244384eda1c82b10e307ad9778dac5c83fb0943775a653cd8"},
|
||||
{file = "Pillow-7.2.0-cp38-cp38-win32.whl", hash = "sha256:725aa6cfc66ce2857d585f06e9519a1cc0ef6d13f186ff3447ab6dff0a09bc7f"},
|
||||
{file = "Pillow-7.2.0-cp38-cp38-win_amd64.whl", hash = "sha256:a060cf8aa332052df2158e5a119303965be92c3da6f2d93b6878f0ebca80b2f6"},
|
||||
{file = "Pillow-7.2.0-pp36-pypy36_pp73-macosx_10_10_x86_64.whl", hash = "sha256:9c87ef410a58dd54b92424ffd7e28fd2ec65d2f7fc02b76f5e9b2067e355ebf6"},
|
||||
{file = "Pillow-7.2.0-pp36-pypy36_pp73-manylinux2010_x86_64.whl", hash = "sha256:e901964262a56d9ea3c2693df68bc9860b8bdda2b04768821e4c44ae797de117"},
|
||||
{file = "Pillow-7.2.0-pp36-pypy36_pp73-win32.whl", hash = "sha256:25930fadde8019f374400f7986e8404c8b781ce519da27792cbe46eabec00c4d"},
|
||||
{file = "Pillow-7.2.0.tar.gz", hash = "sha256:97f9e7953a77d5a70f49b9a48da7776dc51e9b738151b22dacf101641594a626"},
|
||||
]
|
||||
pygments = [
|
||||
{file = "Pygments-2.6.1-py3-none-any.whl", hash = "sha256:ff7a40b4860b727ab48fad6360eb351cc1b33cbf9b15a0f689ca5353e9463324"},
|
||||
{file = "Pygments-2.6.1.tar.gz", hash = "sha256:647344a061c249a3b74e230c739f434d7ea4d8b1d5f3721bc0f3558049b38f44"},
|
||||
]
|
||||
pyinstaller = [
|
||||
{file = "PyInstaller-3.6.tar.gz", hash = "sha256:3730fa80d088f8bb7084d32480eb87cbb4ddb64123363763cf8f2a1378c1c4b7"},
|
||||
]
|
||||
pyparsing = [
|
||||
{file = "pyparsing-2.4.7-py2.py3-none-any.whl", hash = "sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b"},
|
||||
{file = "pyparsing-2.4.7.tar.gz", hash = "sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1"},
|
||||
]
|
||||
pywin32-ctypes = [
|
||||
{file = "pywin32-ctypes-0.2.0.tar.gz", hash = "sha256:24ffc3b341d457d48e8922352130cf2644024a4ff09762a2261fd34c36ee5942"},
|
||||
{file = "pywin32_ctypes-0.2.0-py2.py3-none-any.whl", hash = "sha256:9dc2d991b3479cc2df15930958b674a48a227d5361d413827a4cfd0b5876fc98"},
|
||||
]
|
||||
requests = [
|
||||
{file = "requests-2.24.0-py2.py3-none-any.whl", hash = "sha256:fe75cc94a9443b9246fc7049224f75604b113c36acb93f87b80ed42c44cbb898"},
|
||||
{file = "requests-2.24.0.tar.gz", hash = "sha256:b3559a131db72c33ee969480840fff4bb6dd111de7dd27c8ee1f820f4f00231b"},
|
||||
]
|
||||
urllib3 = [
|
||||
{file = "urllib3-1.25.9-py2.py3-none-any.whl", hash = "sha256:88206b0eb87e6d677d424843ac5209e3fb9d0190d0ee169599165ec25e9d9115"},
|
||||
{file = "urllib3-1.25.9.tar.gz", hash = "sha256:3018294ebefce6572a474f0604c2021e33b3fd8006ecd11d62107a5d2a963527"},
|
||||
]
|
||||
xlrd = [
|
||||
{file = "xlrd-1.2.0-py2.py3-none-any.whl", hash = "sha256:e551fb498759fa3a5384a94ccd4c3c02eb7c00ea424426e212ac0c57be9dfbde"},
|
||||
{file = "xlrd-1.2.0.tar.gz", hash = "sha256:546eb36cee8db40c3eaa46c351e67ffee6eeb5fa2650b71bc4c758a29a1b29b2"},
|
||||
]
|
@ -5,7 +5,6 @@ import {HttpClient} from '@actions/http-client';
|
||||
import * as ifm from '@actions/http-client/interfaces';
|
||||
import * as tc from '@actions/tool-cache';
|
||||
import * as exec from '@actions/exec';
|
||||
import * as core from '@actions/core';
|
||||
|
||||
import * as path from 'path';
|
||||
import * as semver from 'semver';
|
||||
@ -38,34 +37,16 @@ describe('parsePyPyVersion', () => {
|
||||
['pypy-3.6-v7.x', {pythonVersion: '3.6', pypyVersion: 'v7.x'}],
|
||||
['pypy-3.6', {pythonVersion: '3.6', pypyVersion: 'x'}],
|
||||
['pypy-3.6-nightly', {pythonVersion: '3.6', pypyVersion: 'nightly'}],
|
||||
['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'}]
|
||||
['pypy-3.6-v7.3.3rc1', {pythonVersion: '3.6', pypyVersion: 'v7.3.3-rc.1'}]
|
||||
])('%s -> %s', (input, expected) => {
|
||||
expect(finder.parsePyPyVersion(input)).toEqual(expected);
|
||||
});
|
||||
|
||||
it.each(['', 'pypy-', 'pypy', 'p', 'notpypy-'])(
|
||||
'throw on invalid input "%s"',
|
||||
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."
|
||||
);
|
||||
}
|
||||
it('throw on invalid input', () => {
|
||||
expect(() => finder.parsePyPyVersion('pypy-')).toThrowError(
|
||||
"Invalid 'version' property for PyPy. PyPy version should be specified as 'pypy-<python-version>'. See README for examples and documentation."
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getPyPyVersionFromPath', () => {
|
||||
@ -149,13 +130,8 @@ describe('findPyPyVersion', () => {
|
||||
let spyWriteExactPyPyVersionFile: jest.SpyInstance;
|
||||
let spyCacheDir: jest.SpyInstance;
|
||||
let spyChmodSync: jest.SpyInstance;
|
||||
let spyCoreAddPath: jest.SpyInstance;
|
||||
let spyCoreExportVariable: jest.SpyInstance;
|
||||
const env = process.env;
|
||||
|
||||
beforeEach(() => {
|
||||
jest.resetModules();
|
||||
process.env = {...env};
|
||||
tcFind = jest.spyOn(tc, 'find');
|
||||
tcFind.mockImplementation((tool: string, version: string) => {
|
||||
const semverRange = new semver.Range(version);
|
||||
@ -207,46 +183,32 @@ describe('findPyPyVersion', () => {
|
||||
|
||||
spyExistsSync = jest.spyOn(fs, 'existsSync');
|
||||
spyExistsSync.mockReturnValue(true);
|
||||
|
||||
spyCoreAddPath = jest.spyOn(core, 'addPath');
|
||||
|
||||
spyCoreExportVariable = jest.spyOn(core, 'exportVariable');
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.resetAllMocks();
|
||||
jest.clearAllMocks();
|
||||
jest.restoreAllMocks();
|
||||
process.env = env;
|
||||
});
|
||||
|
||||
it('found PyPy in toolcache', async () => {
|
||||
await expect(
|
||||
finder.findPyPyVersion('pypy-3.6-v7.3.x', architecture, true)
|
||||
finder.findPyPyVersion('pypy-3.6-v7.3.x', architecture)
|
||||
).resolves.toEqual({
|
||||
resolvedPythonVersion: '3.6.12',
|
||||
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 () => {
|
||||
await expect(
|
||||
finder.findPyPyVersion('pypy3.7-v7.3.x', architecture, true)
|
||||
finder.findPyPyVersion('pypy3.7-v7.3.x', architecture)
|
||||
).rejects.toThrow();
|
||||
});
|
||||
|
||||
it('throw on invalid input format pypy3.7-7.3.x', async () => {
|
||||
await expect(
|
||||
finder.findPyPyVersion('pypy3.7-v7.3.x', architecture, true)
|
||||
finder.findPyPyVersion('pypy3.7-v7.3.x', architecture)
|
||||
).rejects.toThrow();
|
||||
});
|
||||
|
||||
@ -258,42 +220,16 @@ describe('findPyPyVersion', () => {
|
||||
spyChmodSync = jest.spyOn(fs, 'chmodSync');
|
||||
spyChmodSync.mockImplementation(() => undefined);
|
||||
await expect(
|
||||
finder.findPyPyVersion('pypy-3.7-v7.3.x', architecture, true)
|
||||
finder.findPyPyVersion('pypy-3.7-v7.3.x', architecture)
|
||||
).resolves.toEqual({
|
||||
resolvedPythonVersion: '3.7.9',
|
||||
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 () => {
|
||||
await expect(
|
||||
finder.findPyPyVersion('pypy-3.7-v7.5.x', architecture, true)
|
||||
finder.findPyPyVersion('pypy-3.7-v7.5.x', architecture)
|
||||
).rejects.toThrowError(
|
||||
`PyPy version 3.7 (v7.5.x) with arch ${architecture} not found`
|
||||
);
|
||||
|
@ -19,29 +19,15 @@ process.env['RUNNER_TOOL_CACHE'] = toolDir;
|
||||
process.env['RUNNER_TEMP'] = tempDir;
|
||||
|
||||
import * as tc from '@actions/tool-cache';
|
||||
import * as core from '@actions/core';
|
||||
import * as finder from '../src/find-python';
|
||||
import * as installer from '../src/install-python';
|
||||
|
||||
const manifestData = require('./data/versions-manifest.json');
|
||||
|
||||
describe('Finder tests', () => {
|
||||
let spyCoreAddPath: jest.SpyInstance;
|
||||
let spyCoreExportVariable: jest.SpyInstance;
|
||||
const env = process.env;
|
||||
|
||||
beforeEach(() => {
|
||||
jest.resetModules();
|
||||
process.env = {...env};
|
||||
spyCoreAddPath = jest.spyOn(core, 'addPath');
|
||||
spyCoreExportVariable = jest.spyOn(core, 'exportVariable');
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.resetAllMocks();
|
||||
jest.clearAllMocks();
|
||||
jest.restoreAllMocks();
|
||||
process.env = env;
|
||||
});
|
||||
|
||||
it('Finds Python if it is installed', async () => {
|
||||
@ -49,26 +35,7 @@ describe('Finder tests', () => {
|
||||
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', 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();
|
||||
await finder.findPythonVersion('3.x', 'x64');
|
||||
});
|
||||
|
||||
it('Finds stable Python version if it is not installed, but exists in the manifest', async () => {
|
||||
@ -85,16 +52,7 @@ describe('Finder tests', () => {
|
||||
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('1.2.3', 'x64', true);
|
||||
expect(spyCoreAddPath).toHaveBeenCalled();
|
||||
expect(spyCoreExportVariable).toHaveBeenCalledWith(
|
||||
'pythonLocation',
|
||||
expect.anything()
|
||||
);
|
||||
expect(spyCoreExportVariable).toHaveBeenCalledWith(
|
||||
'PKG_CONFIG_PATH',
|
||||
expect.anything()
|
||||
);
|
||||
await finder.findPythonVersion('1.2.3', 'x64');
|
||||
});
|
||||
|
||||
it('Finds pre-release Python version in the manifest', async () => {
|
||||
@ -116,28 +74,25 @@ describe('Finder tests', () => {
|
||||
fs.writeFileSync(`${pythonDir}.complete`, 'hello');
|
||||
});
|
||||
// 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', true);
|
||||
expect(spyCoreAddPath).toHaveBeenCalled();
|
||||
expect(spyCoreExportVariable).toHaveBeenCalledWith(
|
||||
'pythonLocation',
|
||||
expect.anything()
|
||||
);
|
||||
expect(spyCoreExportVariable).toHaveBeenCalledWith(
|
||||
'PKG_CONFIG_PATH',
|
||||
expect.anything()
|
||||
);
|
||||
await finder.findPythonVersion('1.2.3-beta.2', 'x64');
|
||||
});
|
||||
|
||||
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)
|
||||
let thrown = false;
|
||||
try {
|
||||
await finder.useCpythonVersion('3.300000', 'x64', true);
|
||||
await finder.findPythonVersion('3.300000', 'x64');
|
||||
} catch {
|
||||
thrown = true;
|
||||
}
|
||||
expect(thrown).toBeTruthy();
|
||||
expect(spyCoreAddPath).not.toHaveBeenCalled();
|
||||
expect(spyCoreExportVariable).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('Finds PyPy if it is installed', async () => {
|
||||
const pythonDir: string = path.join(toolDir, 'PyPy', '2.0.0', 'x64');
|
||||
await io.mkdirP(pythonDir);
|
||||
fs.writeFileSync(`${pythonDir}.complete`, 'hello');
|
||||
// This will throw if it doesn't find it in the cache (because no such version exists)
|
||||
await finder.findPythonVersion('pypy2', 'x64');
|
||||
});
|
||||
});
|
||||
|
@ -1,14 +1,8 @@
|
||||
import * as cache from '@actions/cache';
|
||||
import * as core from '@actions/core';
|
||||
import {
|
||||
validateVersion,
|
||||
validatePythonVersionFormatForPyPy,
|
||||
isCacheFeatureAvailable
|
||||
validatePythonVersionFormatForPyPy
|
||||
} from '../src/utils';
|
||||
|
||||
jest.mock('@actions/cache');
|
||||
jest.mock('@actions/core');
|
||||
|
||||
describe('validatePythonVersionFormatForPyPy', () => {
|
||||
it.each([
|
||||
['3.6', true],
|
||||
@ -38,39 +32,3 @@ describe('validateVersion', () => {
|
||||
expect(validateVersion(input)).toEqual(expected);
|
||||
});
|
||||
});
|
||||
|
||||
describe('isCacheFeatureAvailable', () => {
|
||||
it('isCacheFeatureAvailable disabled on GHES', () => {
|
||||
jest.spyOn(cache, 'isFeatureAvailable').mockImplementation(() => false);
|
||||
try {
|
||||
process.env['GITHUB_SERVER_URL'] = 'http://example.com';
|
||||
isCacheFeatureAvailable();
|
||||
} catch (error) {
|
||||
expect(error).toHaveProperty(
|
||||
'message',
|
||||
'Caching is only supported on GHES version >= 3.5. If you are on a version >= 3.5, please check with your GHES admin if the Actions cache service is enabled or not.'
|
||||
);
|
||||
} finally {
|
||||
delete process.env['GITHUB_SERVER_URL'];
|
||||
}
|
||||
});
|
||||
|
||||
it('isCacheFeatureAvailable disabled on dotcom', () => {
|
||||
jest.spyOn(cache, 'isFeatureAvailable').mockImplementation(() => false);
|
||||
const infoMock = jest.spyOn(core, 'warning');
|
||||
const message =
|
||||
'The runner was not able to contact the cache service. Caching will be skipped';
|
||||
try {
|
||||
process.env['GITHUB_SERVER_URL'] = 'http://github.com';
|
||||
expect(isCacheFeatureAvailable()).toBe(false);
|
||||
expect(infoMock).toHaveBeenCalledWith(message);
|
||||
} finally {
|
||||
delete process.env['GITHUB_SERVER_URL'];
|
||||
}
|
||||
});
|
||||
|
||||
it('isCacheFeatureAvailable is enabled', () => {
|
||||
jest.spyOn(cache, 'isFeatureAvailable').mockImplementation(() => true);
|
||||
expect(isCacheFeatureAvailable()).toBe(true);
|
||||
});
|
||||
});
|
||||
|
16
action.yml
16
action.yml
@ -4,11 +4,10 @@ description: 'Set up a specific version of Python and add the command-line tools
|
||||
author: 'GitHub'
|
||||
inputs:
|
||||
python-version:
|
||||
description: "Version range or exact version of Python to use, using SemVer's version range syntax. Reads from .python-version if unset."
|
||||
python-version-file:
|
||||
description: "File containing the Python version to use. Example: .python-version"
|
||||
description: "Version range or exact version of a Python version to use, using SemVer's version range syntax."
|
||||
default: '3.x'
|
||||
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.'
|
||||
required: false
|
||||
architecture:
|
||||
description: 'The target architecture (x86, x64) of the Python interpreter.'
|
||||
@ -17,18 +16,11 @@ inputs:
|
||||
default: ${{ github.token }}
|
||||
cache-dependency-path:
|
||||
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:
|
||||
python-version:
|
||||
description: "The installed python version. Useful when given a version range as input."
|
||||
cache-hit:
|
||||
description: 'A boolean value to indicate a cache entry was found'
|
||||
python-path:
|
||||
description: "The absolute path to the Python executable."
|
||||
runs:
|
||||
using: 'node16'
|
||||
using: 'node12'
|
||||
main: 'dist/setup/index.js'
|
||||
post: 'dist/cache-save/index.js'
|
||||
post-if: success()
|
||||
|
54448
dist/cache-save/index.js
vendored
54448
dist/cache-save/index.js
vendored
File diff suppressed because one or more lines are too long
66614
dist/setup/index.js
vendored
66614
dist/setup/index.js
vendored
File diff suppressed because one or more lines are too long
@ -45,8 +45,8 @@ We won't pursue the goal to provide wide customization of caching in the scope o
|
||||
|
||||
```
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-python@v4
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: 3.9
|
||||
cache: pip
|
||||
@ -56,8 +56,8 @@ steps:
|
||||
|
||||
```
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-python@v4
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: 3.9
|
||||
cache: pipenv
|
||||
@ -66,8 +66,8 @@ steps:
|
||||
|
||||
```
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-python@v4
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: 3.9
|
||||
cache: pip
|
||||
@ -80,8 +80,8 @@ steps:
|
||||
|
||||
```
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-python@v4
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: 3.9
|
||||
cache: pip
|
||||
|
11442
package-lock.json
generated
11442
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
14
package.json
14
package.json
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "setup-python",
|
||||
"version": "4.0.0",
|
||||
"version": "2.3.3",
|
||||
"private": true,
|
||||
"description": "Setup python action",
|
||||
"main": "dist/index.js",
|
||||
@ -9,7 +9,7 @@
|
||||
"format": "prettier --write \"{,!(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/",
|
||||
"test": "jest --coverage"
|
||||
"test": "jest"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@ -23,8 +23,8 @@
|
||||
"author": "GitHub",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@actions/cache": "^3.0.0",
|
||||
"@actions/core": "^1.7.0",
|
||||
"@actions/cache": "^1.0.8",
|
||||
"@actions/core": "^1.10.0",
|
||||
"@actions/exec": "^1.1.0",
|
||||
"@actions/glob": "^0.2.0",
|
||||
"@actions/io": "^1.0.2",
|
||||
@ -33,15 +33,15 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jest": "^27.0.2",
|
||||
"@types/node": "^16.11.25",
|
||||
"@types/node": "^12.20.36",
|
||||
"@types/semver": "^7.1.0",
|
||||
"@vercel/ncc": "^0.33.4",
|
||||
"@zeit/ncc": "^0.22.0",
|
||||
"husky": "^7.0.2",
|
||||
"jest": "^27.2.5",
|
||||
"jest-circus": "^27.2.5",
|
||||
"prettier": "^2.0.2",
|
||||
"ts-jest": "^27.0.5",
|
||||
"typescript": "^4.2.3"
|
||||
"typescript": "^3.8.3"
|
||||
},
|
||||
"husky": {
|
||||
"skipCI": true,
|
||||
|
@ -41,17 +41,12 @@ abstract class CacheDistributor {
|
||||
restoreKey
|
||||
);
|
||||
|
||||
this.handleMatchResult(matchedKey, primaryKey);
|
||||
}
|
||||
|
||||
public handleMatchResult(matchedKey: string | undefined, primaryKey: string) {
|
||||
if (matchedKey) {
|
||||
core.saveState(State.CACHE_MATCHED_KEY, matchedKey);
|
||||
core.info(`Cache restored from key: ${matchedKey}`);
|
||||
} else {
|
||||
core.info(`${this.packageManager} cache is not found`);
|
||||
}
|
||||
core.setOutput('cache-hit', matchedKey === primaryKey);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,11 +1,9 @@
|
||||
import PipCache from './pip-cache';
|
||||
import PipenvCache from './pipenv-cache';
|
||||
import PoetryCache from './poetry-cache';
|
||||
|
||||
export enum PackageManagers {
|
||||
Pip = 'pip',
|
||||
Pipenv = 'pipenv',
|
||||
Poetry = 'poetry'
|
||||
Pipenv = 'pipenv'
|
||||
}
|
||||
|
||||
export function getCacheDistributor(
|
||||
@ -18,8 +16,6 @@ export function getCacheDistributor(
|
||||
return new PipCache(pythonVersion, cacheDependencyPath);
|
||||
case PackageManagers.Pipenv:
|
||||
return new PipenvCache(pythonVersion, cacheDependencyPath);
|
||||
case PackageManagers.Poetry:
|
||||
return new PoetryCache(pythonVersion, cacheDependencyPath);
|
||||
default:
|
||||
throw new Error(`Caching for '${packageManager}' is not supported`);
|
||||
}
|
||||
|
@ -1,76 +0,0 @@
|
||||
import * as glob from '@actions/glob';
|
||||
import * as os from 'os';
|
||||
import * as path from 'path';
|
||||
import * as exec from '@actions/exec';
|
||||
|
||||
import CacheDistributor from './cache-distributor';
|
||||
|
||||
class PoetryCache extends CacheDistributor {
|
||||
constructor(
|
||||
private pythonVersion: string,
|
||||
protected patterns: string = '**/poetry.lock'
|
||||
) {
|
||||
super('poetry', patterns);
|
||||
}
|
||||
|
||||
protected async getCacheGlobalDirectories() {
|
||||
const poetryConfig = await this.getPoetryConfiguration();
|
||||
|
||||
const cacheDir = poetryConfig['cache-dir'];
|
||||
const virtualenvsPath = poetryConfig['virtualenvs.path'].replace(
|
||||
'{cache-dir}',
|
||||
cacheDir
|
||||
);
|
||||
|
||||
const paths = [virtualenvsPath];
|
||||
|
||||
if (poetryConfig['virtualenvs.in-project'] === true) {
|
||||
paths.push(path.join(process.cwd(), '.venv'));
|
||||
}
|
||||
|
||||
return paths;
|
||||
}
|
||||
|
||||
protected async computeKeys() {
|
||||
const hash = await glob.hashFiles(this.patterns);
|
||||
const primaryKey = `${this.CACHE_KEY_PREFIX}-${process.env['RUNNER_OS']}-python-${this.pythonVersion}-${this.packageManager}-${hash}`;
|
||||
const restoreKey = undefined;
|
||||
return {
|
||||
primaryKey,
|
||||
restoreKey
|
||||
};
|
||||
}
|
||||
|
||||
private async getPoetryConfiguration() {
|
||||
const {stdout, stderr, exitCode} = await exec.getExecOutput('poetry', [
|
||||
'config',
|
||||
'--list'
|
||||
]);
|
||||
|
||||
if (exitCode && stderr) {
|
||||
throw new Error(
|
||||
'Could not get cache folder path for poetry package manager'
|
||||
);
|
||||
}
|
||||
|
||||
const lines = stdout.trim().split('\n');
|
||||
|
||||
const config: any = {};
|
||||
|
||||
for (let line of lines) {
|
||||
line = line.replace(/#.*$/gm, '');
|
||||
|
||||
const [key, value] = line.split('=').map(part => part.trim());
|
||||
|
||||
config[key] = JSON.parse(value);
|
||||
}
|
||||
|
||||
return config as {
|
||||
'cache-dir': string;
|
||||
'virtualenvs.in-project': boolean;
|
||||
'virtualenvs.path': string;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export default PoetryCache;
|
@ -43,11 +43,17 @@ async function saveCache(packageManager: string) {
|
||||
return;
|
||||
}
|
||||
|
||||
const cacheId = await cache.saveCache(cachePaths, primaryKey);
|
||||
if (cacheId == -1) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
await cache.saveCache(cachePaths, primaryKey);
|
||||
core.info(`Cache saved with the key: ${primaryKey}`);
|
||||
} catch (error) {
|
||||
const err = error as Error;
|
||||
if (err.name === cache.ReserveCacheError.name) {
|
||||
core.info(err.message);
|
||||
} else {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function isCacheDirectoryExists(cacheDirectory: string[]) {
|
||||
|
@ -20,8 +20,7 @@ interface IPyPyVersionSpec {
|
||||
|
||||
export async function findPyPyVersion(
|
||||
versionSpec: string,
|
||||
architecture: string,
|
||||
updateEnvironment: boolean
|
||||
architecture: string
|
||||
): Promise<{resolvedPyPyVersion: string; resolvedPythonVersion: string}> {
|
||||
let resolvedPyPyVersion = '';
|
||||
let resolvedPythonVersion = '';
|
||||
@ -49,26 +48,10 @@ export async function findPyPyVersion(
|
||||
|
||||
const pipDir = IS_WINDOWS ? 'Scripts' : 'bin';
|
||||
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);
|
||||
if (updateEnvironment) {
|
||||
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', pythonLocation + '/lib/pkgconfig');
|
||||
core.exportVariable('pythonLocation', pythonLocation);
|
||||
core.addPath(pythonLocation);
|
||||
core.addPath(_binDir);
|
||||
}
|
||||
core.setOutput('python-version', 'pypy' + resolvedPyPyVersion.trim());
|
||||
core.setOutput('python-path', pythonPath);
|
||||
|
||||
return {resolvedPyPyVersion, resolvedPythonVersion};
|
||||
}
|
||||
@ -113,14 +96,9 @@ export function findPyPyToolCache(
|
||||
export function parsePyPyVersion(versionSpec: string): IPyPyVersionSpec {
|
||||
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') {
|
||||
throw new Error(
|
||||
"Invalid 'version' property for PyPy. PyPy version should be specified as 'pypy<python-version>' or 'pypy-<python-version>'. See README for examples and documentation."
|
||||
"Invalid 'version' property for PyPy. PyPy version should be specified as 'pypy-<python-version>'. See README for examples and documentation."
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -30,10 +30,54 @@ function binDir(installDir: string): string {
|
||||
}
|
||||
}
|
||||
|
||||
export async function useCpythonVersion(
|
||||
// Note on the tool cache layout for PyPy:
|
||||
// PyPy has its own versioning scheme that doesn't follow the Python versioning scheme.
|
||||
// A particular version of PyPy may contain one or more versions of the Python interpreter.
|
||||
// For example, PyPy 7.0 contains Python 2.7, 3.5, and 3.6-alpha.
|
||||
// We only care about the Python version, so we don't use the PyPy version for the tool cache.
|
||||
function usePyPy(
|
||||
majorVersion: '2' | '3.6',
|
||||
architecture: string
|
||||
): InstalledVersion {
|
||||
const findPyPy = tc.find.bind(undefined, 'PyPy', majorVersion);
|
||||
let installDir: string | null = findPyPy(architecture);
|
||||
|
||||
if (!installDir && IS_WINDOWS) {
|
||||
// PyPy only precompiles binaries for x86, but the architecture parameter defaults to x64.
|
||||
// On our Windows virtual environments, we only install an x86 version.
|
||||
// Fall back to x86.
|
||||
installDir = findPyPy('x86');
|
||||
}
|
||||
|
||||
if (!installDir) {
|
||||
// PyPy not installed in $(Agent.ToolsDirectory)
|
||||
throw new Error(`PyPy ${majorVersion} not found`);
|
||||
}
|
||||
|
||||
// For PyPy, Windows uses 'bin', not 'Scripts'.
|
||||
const _binDir = path.join(installDir, 'bin');
|
||||
|
||||
// On Linux and macOS, the Python interpreter is in 'bin'.
|
||||
// On Windows, it is in the installation root.
|
||||
const pythonLocation = IS_WINDOWS ? installDir : _binDir;
|
||||
core.exportVariable('pythonLocation', pythonLocation);
|
||||
|
||||
core.addPath(installDir);
|
||||
core.addPath(_binDir);
|
||||
// Starting from PyPy 7.3.1, the folder that is used for pip and anything that pip installs should be "Scripts" on Windows.
|
||||
if (IS_WINDOWS) {
|
||||
core.addPath(path.join(installDir, 'Scripts'));
|
||||
}
|
||||
|
||||
const impl = 'pypy' + majorVersion.toString();
|
||||
core.setOutput('python-version', impl);
|
||||
|
||||
return {impl: impl, version: versionFromPath(installDir)};
|
||||
}
|
||||
|
||||
async function useCpythonVersion(
|
||||
version: string,
|
||||
architecture: string,
|
||||
updateEnvironment: boolean
|
||||
architecture: string
|
||||
): Promise<InstalledVersion> {
|
||||
const desugaredVersionSpec = desugarDevVersion(version);
|
||||
const semanticVersionSpec = pythonVersionToSemantic(desugaredVersionSpec);
|
||||
@ -70,23 +114,7 @@ export async function useCpythonVersion(
|
||||
);
|
||||
}
|
||||
|
||||
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) {
|
||||
const libPath = process.env.LD_LIBRARY_PATH
|
||||
@ -98,8 +126,9 @@ export async function useCpythonVersion(
|
||||
core.exportVariable('LD_LIBRARY_PATH', pyLibPath + libPath);
|
||||
}
|
||||
}
|
||||
|
||||
core.addPath(installDir);
|
||||
core.addPath(_binDir);
|
||||
core.addPath(binDir(installDir));
|
||||
|
||||
if (IS_WINDOWS) {
|
||||
// Add --user directory
|
||||
@ -118,19 +147,21 @@ export async function useCpythonVersion(
|
||||
core.addPath(userScriptsDir);
|
||||
}
|
||||
// On Linux and macOS, pip will create the --user directory and add it to PATH as needed.
|
||||
}
|
||||
|
||||
const installed = versionFromPath(installDir);
|
||||
core.setOutput('python-version', installed);
|
||||
core.setOutput('python-path', pythonPath);
|
||||
|
||||
return {impl: 'CPython', version: installed};
|
||||
}
|
||||
|
||||
/** Convert versions like `3.8-dev` to a version like `~3.8.0-0`. */
|
||||
/** Convert versions like `3.8-dev` to a version like `>= 3.8.0-a0`. */
|
||||
function desugarDevVersion(versionSpec: string) {
|
||||
const devVersion = /^(\d+)\.(\d+)-dev$/;
|
||||
return versionSpec.replace(devVersion, '~$1.$2.0-0');
|
||||
if (versionSpec.endsWith('-dev')) {
|
||||
const versionRoot = versionSpec.slice(0, -'-dev'.length);
|
||||
return `>= ${versionRoot}.0-a0`;
|
||||
} else {
|
||||
return versionSpec;
|
||||
}
|
||||
}
|
||||
|
||||
/** Extracts python version from install path from hosted tool cache as described in README.md */
|
||||
@ -155,3 +186,18 @@ export function pythonVersionToSemantic(versionSpec: string) {
|
||||
const prereleaseVersion = /(\d+\.\d+\.\d+)((?:a|b|rc)\d*)/g;
|
||||
return versionSpec.replace(prereleaseVersion, '$1-$2');
|
||||
}
|
||||
|
||||
export async function findPythonVersion(
|
||||
version: string,
|
||||
architecture: string
|
||||
): Promise<InstalledVersion> {
|
||||
switch (version.toUpperCase()) {
|
||||
case 'PYPY2':
|
||||
return usePyPy('2', architecture);
|
||||
case 'PYPY3':
|
||||
// keep pypy3 pointing to 3.6 for backward compatibility
|
||||
return usePyPy('3.6', architecture);
|
||||
default:
|
||||
return await useCpythonVersion(version, architecture);
|
||||
}
|
||||
}
|
||||
|
@ -98,9 +98,7 @@ async function createPyPySymlink(
|
||||
) {
|
||||
const version = semver.coerce(pythonVersion)!;
|
||||
const pythonBinaryPostfix = semver.major(version);
|
||||
const pythonMinor = semver.minor(version);
|
||||
const pypyBinaryPostfix = pythonBinaryPostfix === 2 ? '' : '3';
|
||||
const pypyMajorMinorBinaryPostfix = `${pythonBinaryPostfix}.${pythonMinor}`;
|
||||
let binaryExtension = IS_WINDOWS ? '.exe' : '';
|
||||
|
||||
core.info('Creating symlinks...');
|
||||
@ -117,13 +115,6 @@ async function createPyPySymlink(
|
||||
`python${binaryExtension}`,
|
||||
true
|
||||
);
|
||||
|
||||
createSymlinkInFolder(
|
||||
pypyBinaryPath,
|
||||
`pypy${pypyBinaryPostfix}${binaryExtension}`,
|
||||
`pypy${pypyMajorMinorBinaryPostfix}${binaryExtension}`,
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
async function installPip(pythonLocation: string) {
|
||||
|
@ -3,15 +3,17 @@ import * as finder from './find-python';
|
||||
import * as finderPyPy from './find-pypy';
|
||||
import * as path from 'path';
|
||||
import * as os from 'os';
|
||||
import fs from 'fs';
|
||||
import {getCacheDistributor} from './cache-distributions/cache-factory';
|
||||
import {isCacheFeatureAvailable, IS_LINUX, IS_WINDOWS} from './utils';
|
||||
import {isGhes} from './utils';
|
||||
|
||||
function isPyPyVersion(versionSpec: string) {
|
||||
return versionSpec.startsWith('pypy');
|
||||
return versionSpec.startsWith('pypy-');
|
||||
}
|
||||
|
||||
async function cacheDependencies(cache: string, pythonVersion: string) {
|
||||
if (isGhes()) {
|
||||
throw new Error('Caching is not supported on GHES');
|
||||
}
|
||||
const cacheDependencyPath =
|
||||
core.getInput('cache-dependency-path') || undefined;
|
||||
const cacheDistributor = getCacheDistributor(
|
||||
@ -22,89 +24,33 @@ async function cacheDependencies(cache: string, pythonVersion: string) {
|
||||
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() {
|
||||
// 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 {
|
||||
const version = resolveVersionInput();
|
||||
const version = core.getInput('python-version');
|
||||
if (version) {
|
||||
if (version.trim().startsWith('2')) {
|
||||
core.warning(
|
||||
'The support for python 2.7 will be removed on June 19. Related issue: https://github.com/actions/setup-python/issues/672'
|
||||
);
|
||||
}
|
||||
let pythonVersion: string;
|
||||
const arch: string = core.getInput('architecture') || os.arch();
|
||||
const updateEnvironment = core.getBooleanInput('update-environment');
|
||||
if (isPyPyVersion(version)) {
|
||||
const installed = await finderPyPy.findPyPyVersion(
|
||||
version,
|
||||
arch,
|
||||
updateEnvironment
|
||||
);
|
||||
const installed = await finderPyPy.findPyPyVersion(version, arch);
|
||||
pythonVersion = `${installed.resolvedPyPyVersion}-${installed.resolvedPythonVersion}`;
|
||||
core.info(
|
||||
`Successfully set up PyPy ${installed.resolvedPyPyVersion} with Python (${installed.resolvedPythonVersion})`
|
||||
`Successfully setup PyPy ${installed.resolvedPyPyVersion} with Python (${installed.resolvedPythonVersion})`
|
||||
);
|
||||
} else {
|
||||
const installed = await finder.useCpythonVersion(
|
||||
version,
|
||||
arch,
|
||||
updateEnvironment
|
||||
);
|
||||
const installed = await finder.findPythonVersion(version, arch);
|
||||
pythonVersion = installed.version;
|
||||
core.info(`Successfully set up ${installed.impl} (${pythonVersion})`);
|
||||
core.info(`Successfully setup ${installed.impl} (${pythonVersion})`);
|
||||
}
|
||||
|
||||
const cache = core.getInput('cache');
|
||||
if (cache && isCacheFeatureAvailable()) {
|
||||
if (cache) {
|
||||
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');
|
||||
core.info(`##[add-matcher]${path.join(matchersPath, 'python.json')}`);
|
||||
@ -113,9 +59,4 @@ async function run() {
|
||||
}
|
||||
}
|
||||
|
||||
export function logWarning(message: string): void {
|
||||
const warningPrefix = '[warning]';
|
||||
core.info(`${warningPrefix}${message}`);
|
||||
}
|
||||
|
||||
run();
|
||||
|
20
src/utils.ts
20
src/utils.ts
@ -1,5 +1,3 @@
|
||||
import * as cache from '@actions/cache';
|
||||
import * as core from '@actions/core';
|
||||
import fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import * as semver from 'semver';
|
||||
@ -101,21 +99,3 @@ export function isGhes(): boolean {
|
||||
);
|
||||
return ghUrl.hostname.toUpperCase() !== 'GITHUB.COM';
|
||||
}
|
||||
|
||||
export function isCacheFeatureAvailable(): boolean {
|
||||
if (!cache.isFeatureAvailable()) {
|
||||
if (isGhes()) {
|
||||
throw new Error(
|
||||
'Caching is only supported on GHES version >= 3.5. If you are on a version >= 3.5, please check with your GHES admin if the Actions cache service is enabled or not.'
|
||||
);
|
||||
} else {
|
||||
core.warning(
|
||||
'The runner was not able to contact the cache service. Caching will be skipped'
|
||||
);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
Reference in New Issue
Block a user