mirror of
https://gitea.com/actions/setup-python.git
synced 2026-09-09 21:30:31 +08:00
feat: Add mirror and mirror-token inputs for custom Python distribution sources (#1302)
* feat: Add `mirror` and `mirror-token` inputs for custom Python distribution sources Users who need custom CPython builds (internal mirrors, GHES-hosted forks, special build configurations, compliance builds, air-gapped runners) could not previously point setup-python at anything other than actions/python-versions. Adds two new inputs: - `mirror`: base URL hosting versions-manifest.json and the Python distributions it references. Defaults to the existing https://raw.githubusercontent.com/actions/python-versions/main. - `mirror-token`: optional token used to authenticate requests to the mirror. If `mirror` is a raw.githubusercontent.com/{owner}/{repo}/{branch} URL, the manifest is fetched via the GitHub REST API (authenticated rate limit applies); otherwise the action falls back to a direct GET of {mirror}/versions-manifest.json. Token interaction ----------------- `token` is never forwarded to arbitrary hosts. Auth resolution is per-URL: 1. if mirror-token is set, use mirror-token 2. else if token is set AND the target host is github.com, *.github.com, or *.githubusercontent.com, use token 3. else send no auth Cases: Default (no inputs set) mirror = default raw.githubusercontent.com URL, mirror-token empty, token = github.token. → manifest API call and tarball downloads use `token`. Identical to prior behavior. Custom raw.githubusercontent.com mirror (e.g. personal fork) mirror-token empty, token = github.token. → manifest API call and tarball downloads use `token` (target hosts are GitHub-owned). Custom non-GitHub mirror, no mirror-token mirror-token empty, token = github.token. → manifest fetched via direct URL (no auth attached), tarball downloads use no auth. `token` is NOT forwarded to the custom host — this is the leak-prevention case. Custom non-GitHub mirror with mirror-token mirror-token set, token may be set. → manifest fetch and tarball downloads use `mirror-token`. Custom GitHub mirror with both tokens set mirror-token wins. Used for both the manifest API call and tarball downloads. * fix: address mirror review feedback - scope mirror-token to the mirror host and send it verbatim - route non-repo mirrors straight to the URL fetch instead of throwing - authenticate the manifest fetch - warn on slash branches, and on mirror with PyPy/GraalPy - memoize mirror validation - exercise the direct-URL path in the E2E job Addresses https://github.com/actions/setup-python/pull/1302#issuecomment-5202618946 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix: correct mirror warnings, auth scoping, and integration coverage - only warn about PyPy/GraalPy mirror when a custom mirror is set; the action.yml default made the warning fire on every run - accept the refs/heads/{branch} raw URL form so it routes via the REST API instead of tripping the slash-branch warning - scope mirror-token to the full mirror origin (scheme+host+port) so it can't leak to a same-host http download_url - make an invalid mirror fatal on the auth path, matching getManifestUrl - fix warning/docs that wrongly claimed the raw fallback is anonymous - force a manifest fetch in the mirror integration job (check-latest) so it actually contacts the mirror instead of using the preinstalled cache --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -524,6 +524,46 @@ Such a requirement on side-effect could be because you don't want your composite
|
||||
|
||||
>**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.
|
||||
|
||||
#### Using a custom mirror
|
||||
|
||||
The `mirror` input lets you point `setup-python` at a different location for CPython distributions — a personal fork of `actions/python-versions`, an internal mirror, or any server that hosts a `versions-manifest.json` at its root plus the tarballs referenced by that manifest. Default: `https://raw.githubusercontent.com/actions/python-versions/main`.
|
||||
|
||||
The manifest is resolved as follows:
|
||||
|
||||
- If `mirror` matches `https://raw.githubusercontent.com/{owner}/{repo}/{branch}`, the manifest is fetched via the GitHub REST API (giving you the 5000/hr authenticated rate limit when a token is present).
|
||||
- Otherwise, the action fetches `{mirror}/versions-manifest.json` via a direct HTTP GET.
|
||||
|
||||
Authentication is decided by the host of each request, so neither credential reaches a server you did not nominate:
|
||||
|
||||
- Requests to the host named in `mirror` use `mirror-token`, sent **verbatim** as the `Authorization` header. Include a scheme if your mirror expects one — `Bearer <token>`, `Basic <base64>`, or `token <token>` for a GitHub host. This covers both the manifest fetch and the tarball downloads.
|
||||
- Requests to `github.com`, `*.github.com`, or `*.githubusercontent.com` use `token`, sent as `token <token>`. A manifest that points its `download_url` at a GitHub host therefore keeps working without `mirror-token` being leaked to it.
|
||||
- Any other host is requested anonymously.
|
||||
- One exception: when `mirror` is a GitHub repo URL, the manifest is fetched from `api.github.com`, and `mirror-token` is preferred there (with the `token ` prefix the API requires) because naming a repo mirror is an explicit instruction to read that repo.
|
||||
|
||||
Point at a personal fork of `actions/python-versions` (uses the default `token`, fetched via the GitHub API):
|
||||
|
||||
```yaml
|
||||
- uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: '3.12'
|
||||
mirror: https://raw.githubusercontent.com/my-org/python-versions/main
|
||||
```
|
||||
|
||||
Point at an internal mirror with its own credential:
|
||||
|
||||
```yaml
|
||||
- uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: '3.12'
|
||||
mirror: https://python-mirror.internal.example
|
||||
mirror-token: ${{ secrets.PYTHON_MIRROR_TOKEN }}
|
||||
```
|
||||
|
||||
Caveats:
|
||||
|
||||
- `mirror` and `mirror-token` apply to **CPython only**. PyPy resolves from `downloads.python.org` and GraalPy from the GitHub releases API; both ignore these inputs, and the action warns if you set `mirror` alongside a `pypy-*` or `graalpy-*` version.
|
||||
- Branch names containing `/` cannot be used with a `raw.githubusercontent.com` mirror, because `.../{owner}/{repo}/feature/riscv` is indistinguishable from a repo path. Such a mirror still works and is still authenticated with your `token` (raw.githubusercontent.com is a GitHub host), but the manifest is fetched directly from the raw URL rather than through the GitHub REST API; the action warns when this happens. Use a branch without a slash to get the REST API path. The `refs/heads/{branch}` form (for example `.../actions/python-versions/refs/heads/main`) is recognized and routes through the REST API.
|
||||
|
||||
### PyPy
|
||||
|
||||
`setup-python` is able to configure **PyPy** from two sources:
|
||||
|
||||
Reference in New Issue
Block a user