mirror of
https://github.com/actions/setup-python.git
synced 2026-09-17 10:01:28 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
82c7e631bb | ||
|
|
10aa35afd7 | ||
|
|
9a7ac94420 | ||
|
|
871daa956c | ||
|
|
2f078955e4 | ||
|
|
e9d6f99097 | ||
|
|
0a5c615913 | ||
|
|
0ae58361cd |
@@ -13,3 +13,5 @@ jobs:
|
||||
call-basic-validation:
|
||||
name: Basic validation
|
||||
uses: actions/reusable-workflows/.github/workflows/basic-validation.yml@main
|
||||
with:
|
||||
node-version: '20.x'
|
||||
|
||||
@@ -15,3 +15,5 @@ jobs:
|
||||
call-check-dist:
|
||||
name: Check dist/
|
||||
uses: actions/reusable-workflows/.github/workflows/check-dist.yml@main
|
||||
with:
|
||||
node-version: '20.x'
|
||||
|
||||
@@ -93,3 +93,7 @@ jobs:
|
||||
python-version: '<3.11'
|
||||
- name: Verify <3.11
|
||||
run: python __tests__/verify-python.py 3.10
|
||||
- name: Test Raw Endpoint Access
|
||||
run: |
|
||||
curl -L https://raw.githubusercontent.com/actions/python-versions/main/versions-manifest.json | jq empty
|
||||
shell: bash
|
||||
|
||||
@@ -30,7 +30,7 @@ jobs:
|
||||
- 'pypy-3.7-v7.3.x'
|
||||
- 'pypy-3.7-v7.x'
|
||||
- 'pypy-2.7-v7.3.4rc1'
|
||||
- 'pypy-3.7-nightly'
|
||||
- 'pypy-3.8-nightly'
|
||||
- 'pypy3.8-v7.3.7'
|
||||
|
||||
steps:
|
||||
|
||||
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Binary file not shown.
Generated
BIN
Binary file not shown.
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
@@ -19,7 +19,7 @@ See [action.yml](action.yml)
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v4
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.10'
|
||||
- run: python my_script.py
|
||||
@@ -29,11 +29,22 @@ steps:
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v4
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: 'pypy3.9'
|
||||
- run: python my_script.py
|
||||
```
|
||||
|
||||
**GraalPy**
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: 'graalpy-22.3'
|
||||
- run: python my_script.py
|
||||
```
|
||||
|
||||
The `python-version` input is optional. If not supplied, the action will try to resolve the version from the default `.python-version` file. If the `.python-version` file doesn't exist Python or PyPy version from the PATH will be used. The default version of Python or PyPy in PATH varies between runners and can be changed unexpectedly so we recommend always setting Python version explicitly using the `python-version` or `python-version-file` inputs.
|
||||
|
||||
The action will first check the local [tool cache](docs/advanced-usage.md#hosted-tool-cache) for a [semver](https://github.com/npm/node-semver#versions) match. If unable to find a specific version in the tool cache, the action will attempt to download a version of Python from [GitHub Releases](https://github.com/actions/python-versions/releases) and for PyPy from the official [PyPy's dist](https://downloads.python.org/pypy/).
|
||||
@@ -63,7 +74,7 @@ The action defaults to searching for a dependency file (`requirements.txt` or `p
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v4
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.9'
|
||||
cache: 'pip' # caching pip dependencies
|
||||
@@ -82,7 +93,7 @@ See examples of using `cache` and `cache-dependency-path` for `pipenv` and `poet
|
||||
- [Check latest version](docs/advanced-usage.md#check-latest-version)
|
||||
- [Caching packages](docs/advanced-usage.md#caching-packages)
|
||||
- [Outputs and environment variables](docs/advanced-usage.md#outputs-and-environment-variables)
|
||||
- [Available versions of Python and PyPy](docs/advanced-usage.md#available-versions-of-python-and-pypy)
|
||||
- [Available versions of Python, PyPy and GraalPy](docs/advanced-usage.md#available-versions-of-python-pypy-and-graalpy)
|
||||
- [Hosted tool cache](docs/advanced-usage.md#hosted-tool-cache)
|
||||
- [Using `setup-python` with a self-hosted runner](docs/advanced-usage.md#using-setup-python-with-a-self-hosted-runner)
|
||||
- [Using `setup-python` on GHES](docs/advanced-usage.md#using-setup-python-on-ghes)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import fs from 'fs';
|
||||
|
||||
import {HttpClient} from '@actions/http-client';
|
||||
import * as ifm from '@actions/http-client/interfaces';
|
||||
import * as ifm from '@actions/http-client/lib/interfaces';
|
||||
import * as tc from '@actions/tool-cache';
|
||||
import * as exec from '@actions/exec';
|
||||
import * as core from '@actions/core';
|
||||
@@ -179,7 +179,7 @@ describeSkipOnWindows('findGraalPyVersion', () => {
|
||||
|
||||
spyHttpClient = jest.spyOn(HttpClient.prototype, 'getJson');
|
||||
spyHttpClient.mockImplementation(
|
||||
async (): Promise<ifm.ITypedResponse<IGraalPyManifestRelease[]>> => {
|
||||
async (): Promise<ifm.TypedResponse<IGraalPyManifestRelease[]>> => {
|
||||
const result = JSON.stringify(manifestData);
|
||||
return {
|
||||
statusCode: 200,
|
||||
|
||||
@@ -2,7 +2,7 @@ import fs from 'fs';
|
||||
|
||||
import * as utils from '../src/utils';
|
||||
import {HttpClient} from '@actions/http-client';
|
||||
import * as ifm from '@actions/http-client/interfaces';
|
||||
import * as ifm from '@actions/http-client/lib/interfaces';
|
||||
import * as tc from '@actions/tool-cache';
|
||||
import * as exec from '@actions/exec';
|
||||
import * as core from '@actions/core';
|
||||
@@ -240,7 +240,7 @@ describe('findPyPyVersion', () => {
|
||||
|
||||
spyHttpClient = jest.spyOn(HttpClient.prototype, 'getJson');
|
||||
spyHttpClient.mockImplementation(
|
||||
async (): Promise<ifm.ITypedResponse<IPyPyManifestRelease[]>> => {
|
||||
async (): Promise<ifm.TypedResponse<IPyPyManifestRelease[]>> => {
|
||||
const result = JSON.stringify(manifestData);
|
||||
return {
|
||||
statusCode: 200,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import fs from 'fs';
|
||||
|
||||
import {HttpClient} from '@actions/http-client';
|
||||
import * as ifm from '@actions/http-client/interfaces';
|
||||
import * as ifm from '@actions/http-client/lib/interfaces';
|
||||
import * as tc from '@actions/tool-cache';
|
||||
import * as exec from '@actions/exec';
|
||||
import * as core from '@actions/core';
|
||||
@@ -169,7 +169,7 @@ describeSkipOnWindows('installGraalPy', () => {
|
||||
|
||||
spyHttpClient = jest.spyOn(HttpClient.prototype, 'getJson');
|
||||
spyHttpClient.mockImplementation(
|
||||
async (): Promise<ifm.ITypedResponse<IGraalPyManifestRelease[]>> => {
|
||||
async (): Promise<ifm.TypedResponse<IGraalPyManifestRelease[]>> => {
|
||||
const result = JSON.stringify(manifestData);
|
||||
return {
|
||||
statusCode: 200,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import fs from 'fs';
|
||||
|
||||
import {HttpClient} from '@actions/http-client';
|
||||
import * as ifm from '@actions/http-client/interfaces';
|
||||
import * as ifm from '@actions/http-client/lib/interfaces';
|
||||
import * as tc from '@actions/tool-cache';
|
||||
import * as exec from '@actions/exec';
|
||||
import * as core from '@actions/core';
|
||||
@@ -265,7 +265,7 @@ describe('installPyPy', () => {
|
||||
|
||||
spyHttpClient = jest.spyOn(HttpClient.prototype, 'getJson');
|
||||
spyHttpClient.mockImplementation(
|
||||
async (): Promise<ifm.ITypedResponse<IPyPyManifestRelease[]>> => {
|
||||
async (): Promise<ifm.TypedResponse<IPyPyManifestRelease[]>> => {
|
||||
const result = JSON.stringify(manifestData);
|
||||
return {
|
||||
statusCode: 200,
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
import {
|
||||
getManifest,
|
||||
getManifestFromRepo,
|
||||
getManifestFromURL
|
||||
} from '../src/install-python';
|
||||
import * as httpm from '@actions/http-client';
|
||||
import * as tc from '@actions/tool-cache';
|
||||
|
||||
jest.mock('@actions/http-client');
|
||||
jest.mock('@actions/tool-cache');
|
||||
|
||||
const mockManifest = [{version: '1.0.0'}];
|
||||
|
||||
describe('getManifest', () => {
|
||||
it('should return manifest from repo', async () => {
|
||||
(tc.getManifestFromRepo as jest.Mock).mockResolvedValue(mockManifest);
|
||||
const manifest = await getManifest();
|
||||
expect(manifest).toEqual(mockManifest);
|
||||
});
|
||||
|
||||
it('should return manifest from URL if repo fetch fails', async () => {
|
||||
(tc.getManifestFromRepo as jest.Mock).mockRejectedValue(
|
||||
new Error('Fetch failed')
|
||||
);
|
||||
(httpm.HttpClient.prototype.getJson as jest.Mock).mockResolvedValue({
|
||||
result: mockManifest
|
||||
});
|
||||
const manifest = await getManifest();
|
||||
expect(manifest).toEqual(mockManifest);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getManifestFromRepo', () => {
|
||||
it('should return manifest from repo', async () => {
|
||||
(tc.getManifestFromRepo as jest.Mock).mockResolvedValue(mockManifest);
|
||||
const manifest = await getManifestFromRepo();
|
||||
expect(manifest).toEqual(mockManifest);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getManifestFromURL', () => {
|
||||
it('should return manifest from URL', async () => {
|
||||
(httpm.HttpClient.prototype.getJson as jest.Mock).mockResolvedValue({
|
||||
result: mockManifest
|
||||
});
|
||||
const manifest = await getManifestFromURL();
|
||||
expect(manifest).toEqual(mockManifest);
|
||||
});
|
||||
|
||||
it('should throw error if unable to get manifest from URL', async () => {
|
||||
(httpm.HttpClient.prototype.getJson as jest.Mock).mockResolvedValue({
|
||||
result: null
|
||||
});
|
||||
await expect(getManifestFromURL()).rejects.toThrow(
|
||||
'Unable to get manifest from'
|
||||
);
|
||||
});
|
||||
});
|
||||
+1
-1
@@ -34,7 +34,7 @@ outputs:
|
||||
python-path:
|
||||
description: "The absolute path to the Python or PyPy executable."
|
||||
runs:
|
||||
using: 'node16'
|
||||
using: 'node20'
|
||||
main: 'dist/setup/index.js'
|
||||
post: 'dist/cache-save/index.js'
|
||||
post-if: success()
|
||||
|
||||
Vendored
+29666
-6267
File diff suppressed because one or more lines are too long
Vendored
+30393
-7410
File diff suppressed because one or more lines are too long
+39
-52
@@ -2,7 +2,7 @@
|
||||
- [Using the python-version input](advanced-usage.md#using-the-python-version-input)
|
||||
- [Specifying a Python version](advanced-usage.md#specifying-a-python-version)
|
||||
- [Specifying a PyPy version](advanced-usage.md#specifying-a-pypy-version)
|
||||
- [Specifying multiple Python and PyPy versions](advanced-usage.md#specifying-multiple-python/pypy-version)
|
||||
- [Specifying multiple Python/PyPy versions](advanced-usage.md#specifying-multiple-pythonpypy-versions)
|
||||
- [Matrix Testing](advanced-usage.md#matrix-testing)
|
||||
- [Using the python-version-file input](advanced-usage.md#using-the-python-version-file-input)
|
||||
- [Check latest version](advanced-usage.md#check-latest-version)
|
||||
@@ -11,9 +11,10 @@
|
||||
- [Outputs](advanced-usage.md#outputs)
|
||||
- [Environment variables](advanced-usage.md#environment-variables)
|
||||
- [Using update-environment flag](advanced-usage.md#using-update-environment-flag)
|
||||
- [Available versions of Python and PyPy](advanced-usage.md#available-versions-of-python-and-pypy)
|
||||
- [Available versions of Python and PyPy](advanced-usage.md#available-versions-of-python-pypy-and-graalpy)
|
||||
- [Python](advanced-usage.md#python)
|
||||
- [PyPy](advanced-usage.md#pypy)
|
||||
- [GraalPy](advanced-usage.md#graalpy)
|
||||
- [Hosted tool cache](advanced-usage.md#hosted-tool-cache)
|
||||
- [Using `setup-python` with a self-hosted runner](advanced-usage.md#using-setup-python-with-a-self-hosted-runner)
|
||||
- [Windows](advanced-usage.md#windows)
|
||||
@@ -31,7 +32,7 @@ If there is a specific version of Python that you need and you don't want to wor
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v4
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.7.5'
|
||||
- run: python my_script.py
|
||||
@@ -45,7 +46,7 @@ You can specify **only a major and minor version** if you are okay with the most
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v4
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.7'
|
||||
- run: python my_script.py
|
||||
@@ -59,7 +60,7 @@ You can specify the version with **prerelease tag** to download and set up an ac
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v4
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.12.0-alpha.1'
|
||||
- run: python my_script.py
|
||||
@@ -70,7 +71,7 @@ It's also possible to use **x.y-dev syntax** to download and set up the latest p
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v4
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.12-dev'
|
||||
- run: python my_script.py
|
||||
@@ -83,7 +84,7 @@ You can also use several types of ranges that are specified in [semver](https://
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v4
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '>=3.9 <3.10'
|
||||
- run: python my_script.py
|
||||
@@ -94,7 +95,7 @@ steps:
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v4
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.12.0-alpha - 3.12.0'
|
||||
- run: python my_script.py
|
||||
@@ -105,7 +106,7 @@ steps:
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v4
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.x'
|
||||
- run: python my_script.py
|
||||
@@ -138,14 +139,14 @@ jobs:
|
||||
- 'pypy3.7-v7.3.3' # Python 3.7 and PyPy 7.3.3
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v4
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
- run: python my_script.py
|
||||
```
|
||||
More details on PyPy syntax can be found in the [Available versions of PyPy](#pypy) section.
|
||||
|
||||
### Specifying multiple Python/PyPy version
|
||||
### Specifying multiple Python/PyPy versions
|
||||
The python-version input can get multiple python/pypy versions. The last specified version will be used as a default one.
|
||||
|
||||
Download and set up multiple Python versions:
|
||||
@@ -156,7 +157,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v4
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: |
|
||||
3.8
|
||||
@@ -173,7 +174,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v4
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: |
|
||||
pypy-3.7-v7.3.x
|
||||
@@ -190,7 +191,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v4
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: |
|
||||
3.8
|
||||
@@ -216,7 +217,7 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v4
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
architecture: x64
|
||||
@@ -241,7 +242,7 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v4
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
- name: Display Python version
|
||||
@@ -257,7 +258,7 @@ jobs:
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v4
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version-file: '.python-version' # Read python version from a file .python-version
|
||||
- run: python my_script.py
|
||||
@@ -266,7 +267,7 @@ steps:
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v4
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version-file: 'pyproject.toml' # Read python version from a file pyproject.toml
|
||||
- run: python my_script.py
|
||||
@@ -281,7 +282,7 @@ If `check-latest` is set to `true`, the action first checks if the cached versio
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v4
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.7'
|
||||
check-latest: true
|
||||
@@ -296,7 +297,7 @@ steps:
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v4
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.9'
|
||||
cache: 'pipenv'
|
||||
@@ -311,7 +312,7 @@ steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install poetry
|
||||
run: pipx install poetry
|
||||
- uses: actions/setup-python@v4
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.9'
|
||||
cache: 'poetry'
|
||||
@@ -323,7 +324,7 @@ steps:
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v4
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.9'
|
||||
cache: 'pipenv'
|
||||
@@ -338,7 +339,7 @@ steps:
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v4
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.9'
|
||||
cache: 'pip'
|
||||
@@ -350,7 +351,7 @@ steps:
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v4
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.10'
|
||||
cache: 'pip'
|
||||
@@ -365,7 +366,7 @@ steps:
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v4
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.11'
|
||||
cache: 'pip'
|
||||
@@ -388,7 +389,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v4
|
||||
- uses: actions/setup-python@v5
|
||||
id: cp310
|
||||
with:
|
||||
python-version: "3.8.0 - 3.10.0"
|
||||
@@ -405,7 +406,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v4
|
||||
- uses: actions/setup-python@v5
|
||||
id: cp310
|
||||
with:
|
||||
python-version: "3.10"
|
||||
@@ -421,7 +422,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v4
|
||||
- uses: actions/setup-python@v5
|
||||
id: cp310
|
||||
with:
|
||||
python-version: "3.8.0"
|
||||
@@ -452,14 +453,14 @@ Such a requirement on side-effect could be because you don't want your composite
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v4
|
||||
- uses: actions/setup-python@v5
|
||||
id: cp310
|
||||
with:
|
||||
python-version: '3.10'
|
||||
update-environment: false
|
||||
- run: ${{ steps.cp310.outputs.python-path }} my_script.py
|
||||
```
|
||||
## Available versions of Python and PyPy
|
||||
## Available versions of Python, PyPy and GraalPy
|
||||
### Python
|
||||
|
||||
`setup-python` is able to configure **Python** from two sources:
|
||||
@@ -490,6 +491,11 @@ Such a requirement on side-effect could be because you don't want your composite
|
||||
- PyPy < 7.3.3 are not available to install on-flight.
|
||||
- If some versions are not available, you can open an issue in https://foss.heptapod.net/pypy/pypy/
|
||||
|
||||
### GraalPy
|
||||
|
||||
`setup-python` is able to download GraalPy versions from the [official GraalPy repository](https://github.com/oracle/graalpython).
|
||||
- All available versions that we can download are listed in [releases](https://github.com/oracle/graalpython/releases).
|
||||
|
||||
## Hosted tool cache
|
||||
|
||||
GitHub hosted runners have a tool cache that comes with a few versions of Python + PyPy already installed. This tool cache helps speed up runs and tool setup by not requiring any new downloads. There is an environment variable called `RUNNER_TOOL_CACHE` on each runner that describes the location of the tool cache with Python and PyPy installed. `setup-python` works by taking a specific version of Python or PyPy from this tool cache and adding it to PATH.
|
||||
@@ -566,29 +572,10 @@ One quick way to grant access is to change the user and group of `/Users/runner/
|
||||
|
||||
### Avoiding rate limit issues
|
||||
|
||||
`setup-python` comes pre-installed on the appliance with GHES if Actions is enabled. When dynamically downloading Python distributions, `setup-python` downloads distributions from [`actions/python-versions`](https://github.com/actions/python-versions) on github.com (outside of the appliance). These calls to `actions/python-versions` are by default made via unauthenticated requests, which are limited to [60 requests per hour per IP](https://docs.github.com/en/rest/overview/resources-in-the-rest-api#rate-limiting). If more requests are made within the time frame, then you will start to see rate-limit errors during downloading that look like this:
|
||||
|
||||
##[error]API rate limit exceeded for YOUR_IP. (But here's the good news: Authenticated requests get a higher rate limit. Check out the documentation for more details.)
|
||||
|
||||
To get a higher rate limit, you can [generate a personal access token (PAT) on github.com](https://github.com/settings/tokens/new) and pass it as the `token` input for the action. It is important to understand that this needs to be a token from github.com and _not_ from your GHES instance. If you or your colleagues do not yet have a github.com account, you might need to create one.
|
||||
|
||||
Here are the steps you need to follow to avoid the rate limit:
|
||||
|
||||
1. Create a PAT on any github.com account by using [this link](https://github.com/settings/tokens/new) after logging into github.com (not your Enterprise instance). This PAT does _not_ need any rights, so make sure all the boxes are unchecked.
|
||||
2. Store this PAT in the repository / organization where you run your workflow, e.g. as `GH_GITHUB_COM_TOKEN`. You can do this by navigating to your repository -> **Settings** -> **Secrets** -> **Actions** -> **New repository secret**.
|
||||
3. To use this functionality, you need to use any version newer than `v4.3`. Also, change _python-version_ as needed.
|
||||
|
||||
```yml
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: 3.8
|
||||
token: ${{ secrets.GH_GITHUB_COM_TOKEN }}
|
||||
```
|
||||
|
||||
Requests should now be authenticated. To verify that you are getting the higher rate limit, you can call GitHub's [rate limit API](https://docs.github.com/en/rest/rate-limit) from within your workflow ([example](https://github.com/actions/setup-python/pull/443#issuecomment-1206776401)).
|
||||
`setup-python` comes pre-installed on the appliance with GHES if Actions is enabled. When dynamically downloading Python distributions, `setup-python` downloads distributions from [`actions/python-versions`](https://github.com/actions/python-versions) on github.com (outside of the appliance). These calls to `actions/python-versions` are by default made via unauthenticated requests, which are limited to [60 requests per hour per IP](https://docs.github.com/en/rest/overview/resources-in-the-rest-api#rate-limiting). If more requests are made within the time frame, then the action leverages the `raw API` to retrieve the version-manifest. This approach does not impose a rate limit and hence facilitates unrestricted consumption. This is particularly beneficial for GHES runners, which often share the same IP due to Network Address Translation (NAT), to avoid the quick exhaustion of the unauthenticated rate limit.
|
||||
|
||||
### No access to github.com
|
||||
|
||||
If the runner is not able to access github.com, any Python versions requested during a workflow run must come from the runner's tool cache. See "[Setting up the tool cache on self-hosted runners without internet access](https://docs.github.com/en/enterprise-server/admin/github-actions/managing-access-to-actions-from-githubcom/setting-up-the-tool-cache-on-self-hosted-runners-without-internet-access)" for more information.
|
||||
|
||||
|
||||
@@ -612,7 +599,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v4
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "${{ matrix.python_version }}"
|
||||
allow-prereleases: true
|
||||
|
||||
Generated
+862
-5041
File diff suppressed because it is too large
Load Diff
+14
-21
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "setup-python",
|
||||
"version": "4.0.0",
|
||||
"version": "5.0.0",
|
||||
"private": true,
|
||||
"description": "Setup python action",
|
||||
"main": "dist/index.js",
|
||||
@@ -11,7 +11,7 @@
|
||||
"lint": "eslint --config ./.eslintrc.js \"**/*.ts\"",
|
||||
"lint:fix": "eslint --config ./.eslintrc.js \"**/*.ts\" --fix",
|
||||
"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 --runInBand --coverage"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -25,38 +25,31 @@
|
||||
"author": "GitHub",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@actions/cache": "^3.0.4",
|
||||
"@actions/cache": "^3.2.4",
|
||||
"@actions/core": "^1.10.0",
|
||||
"@actions/exec": "^1.1.0",
|
||||
"@actions/glob": "^0.2.0",
|
||||
"@actions/http-client": "^1.0.11",
|
||||
"@actions/glob": "^0.4.0",
|
||||
"@actions/http-client": "^2.2.1",
|
||||
"@actions/io": "^1.0.2",
|
||||
"@actions/tool-cache": "^1.5.5",
|
||||
"@actions/tool-cache": "^2.0.1",
|
||||
"@iarna/toml": "^2.2.5",
|
||||
"semver": "^7.5.2"
|
||||
"semver": "^7.6.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jest": "^29.5.6",
|
||||
"@types/node": "^16.11.25",
|
||||
"@types/semver": "^7.1.0",
|
||||
"@types/jest": "^29.5.12",
|
||||
"@types/node": "^20.11.25",
|
||||
"@types/semver": "^7.5.8",
|
||||
"@typescript-eslint/eslint-plugin": "^5.54.0",
|
||||
"@typescript-eslint/parser": "^5.54.0",
|
||||
"@vercel/ncc": "^0.38.0",
|
||||
"eslint": "^8.35.0",
|
||||
"eslint": "^8.57.0",
|
||||
"eslint-config-prettier": "^8.6.0",
|
||||
"eslint-plugin-jest": "^27.2.1",
|
||||
"eslint-plugin-jest": "^27.9.0",
|
||||
"eslint-plugin-node": "^11.1.0",
|
||||
"husky": "^7.0.2",
|
||||
"jest": "^29.7.0",
|
||||
"jest-circus": "^29.7.0",
|
||||
"prettier": "^2.8.4",
|
||||
"ts-jest": "^29.1.1",
|
||||
"typescript": "^4.2.3"
|
||||
},
|
||||
"husky": {
|
||||
"skipCI": true,
|
||||
"hooks": {
|
||||
"pre-commit": "npm run build && npm run format-check"
|
||||
}
|
||||
"ts-jest": "^29.1.2",
|
||||
"typescript": "^5.4.2"
|
||||
}
|
||||
}
|
||||
|
||||
+9
-2
@@ -4,11 +4,18 @@ import * as cache from '@actions/cache';
|
||||
import fs from 'fs';
|
||||
import {State} from './cache-distributions/cache-distributor';
|
||||
|
||||
export async function run() {
|
||||
// Added early exit to resolve issue with slow post action step:
|
||||
// - https://github.com/actions/setup-node/issues/878
|
||||
// https://github.com/actions/cache/pull/1217
|
||||
export async function run(earlyExit?: boolean) {
|
||||
try {
|
||||
const cache = core.getInput('cache');
|
||||
if (cache) {
|
||||
await saveCache(cache);
|
||||
|
||||
if (earlyExit) {
|
||||
process.exit(0);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
const err = error as Error;
|
||||
@@ -76,4 +83,4 @@ function isCacheDirectoryExists(cacheDirectory: string[]) {
|
||||
return result;
|
||||
}
|
||||
|
||||
run();
|
||||
run(true);
|
||||
|
||||
@@ -4,9 +4,11 @@ import * as core from '@actions/core';
|
||||
import * as tc from '@actions/tool-cache';
|
||||
import * as semver from 'semver';
|
||||
import * as httpm from '@actions/http-client';
|
||||
import * as ifm from '@actions/http-client/interfaces';
|
||||
import * as ifm from '@actions/http-client/lib/interfaces';
|
||||
import * as exec from '@actions/exec';
|
||||
|
||||
import fs from 'fs';
|
||||
import * as http from 'http';
|
||||
|
||||
import {
|
||||
IS_WINDOWS,
|
||||
@@ -108,7 +110,7 @@ export async function installGraalPy(
|
||||
export async function getAvailableGraalPyVersions() {
|
||||
const http: httpm.HttpClient = new httpm.HttpClient('tool-cache');
|
||||
|
||||
const headers: ifm.IHeaders = {};
|
||||
const headers: http.OutgoingHttpHeaders = {};
|
||||
if (AUTH) {
|
||||
headers.authorization = AUTH;
|
||||
}
|
||||
@@ -117,7 +119,7 @@ export async function getAvailableGraalPyVersions() {
|
||||
'https://api.github.com/repos/oracle/graalpython/releases';
|
||||
const result: IGraalPyManifestRelease[] = [];
|
||||
do {
|
||||
const response: ifm.ITypedResponse<IGraalPyManifestRelease[]> =
|
||||
const response: ifm.TypedResponse<IGraalPyManifestRelease[]> =
|
||||
await http.getJson(url, headers);
|
||||
if (!response.result) {
|
||||
throw new Error(
|
||||
|
||||
+25
-1
@@ -2,6 +2,7 @@ import * as path from 'path';
|
||||
import * as core from '@actions/core';
|
||||
import * as tc from '@actions/tool-cache';
|
||||
import * as exec from '@actions/exec';
|
||||
import * as httpm from '@actions/http-client';
|
||||
import {ExecOptions} from '@actions/exec/lib/interfaces';
|
||||
import {IS_WINDOWS, IS_LINUX} from './utils';
|
||||
|
||||
@@ -31,7 +32,19 @@ export async function findReleaseFromManifest(
|
||||
return foundRelease;
|
||||
}
|
||||
|
||||
export function getManifest(): Promise<tc.IToolRelease[]> {
|
||||
export async function getManifest(): Promise<tc.IToolRelease[]> {
|
||||
try {
|
||||
return await getManifestFromRepo();
|
||||
} catch (err) {
|
||||
core.debug('Fetching the manifest via the API failed.');
|
||||
if (err instanceof Error) {
|
||||
core.debug(err.message);
|
||||
}
|
||||
}
|
||||
return await getManifestFromURL();
|
||||
}
|
||||
|
||||
export function getManifestFromRepo(): Promise<tc.IToolRelease[]> {
|
||||
core.debug(
|
||||
`Getting manifest from ${MANIFEST_REPO_OWNER}/${MANIFEST_REPO_NAME}@${MANIFEST_REPO_BRANCH}`
|
||||
);
|
||||
@@ -43,6 +56,17 @@ export function getManifest(): Promise<tc.IToolRelease[]> {
|
||||
);
|
||||
}
|
||||
|
||||
export async function getManifestFromURL(): Promise<tc.IToolRelease[]> {
|
||||
core.debug('Falling back to fetching the manifest using raw URL.');
|
||||
|
||||
const http: httpm.HttpClient = new httpm.HttpClient('tool-cache');
|
||||
const response = await http.getJson<tc.IToolRelease[]>(MANIFEST_URL);
|
||||
if (!response.result) {
|
||||
throw new Error(`Unable to get manifest from ${MANIFEST_URL}`);
|
||||
}
|
||||
return response.result;
|
||||
}
|
||||
|
||||
async function installPython(workingDirectory: string) {
|
||||
const options: ExecOptions = {
|
||||
cwd: workingDirectory,
|
||||
|
||||
+5
-3
@@ -6,7 +6,9 @@ import * as path from 'path';
|
||||
import * as semver from 'semver';
|
||||
import * as toml from '@iarna/toml';
|
||||
import * as exec from '@actions/exec';
|
||||
import * as ifm from '@actions/http-client/interfaces';
|
||||
import * as ifm from '@actions/http-client/lib/interfaces';
|
||||
|
||||
import * as http from 'http';
|
||||
|
||||
export const IS_WINDOWS = process.platform === 'win32';
|
||||
export const IS_LINUX = process.platform === 'linux';
|
||||
@@ -290,8 +292,8 @@ export function getBinaryDirectory(installDir: string) {
|
||||
/**
|
||||
* Extract next page URL from a HTTP response "link" header. Such headers are used in GitHub APIs.
|
||||
*/
|
||||
export function getNextPageUrl<T>(response: ifm.ITypedResponse<T>) {
|
||||
const responseHeaders = <ifm.IHeaders>response.headers;
|
||||
export function getNextPageUrl<T>(response: ifm.TypedResponse<T>) {
|
||||
const responseHeaders = <http.OutgoingHttpHeaders>response.headers;
|
||||
const linkHeader = responseHeaders.link;
|
||||
if (typeof linkHeader === 'string') {
|
||||
for (const link of linkHeader.split(/\s*,\s*/)) {
|
||||
|
||||
Reference in New Issue
Block a user