Skip to content

ci: install Python via astral-sh/setup-uv to skip slow downloads#1351

Closed
bdraco wants to merge 4 commits into
aio-libs:masterfrom
bdraco:ci/setup-uv-action
Closed

ci: install Python via astral-sh/setup-uv to skip slow downloads#1351
bdraco wants to merge 4 commits into
aio-libs:masterfrom
bdraco:ci/setup-uv-action

Conversation

@bdraco
Copy link
Copy Markdown
Member

@bdraco bdraco commented May 18, 2026

What do these changes do?

Port aio-libs/yarl#1704 to multidict. Three logical steps, mirrored
1:1 in the commit history:

  1. Swap actions/setup-python@v6 for astral-sh/setup-uv@v8 in
    the two CI jobs that install a Python interpreter
    (build-pure-python-dists and the matrix test).
    activate-environment: true keeps python/pip on PATH so
    the rest of the pipeline is unchanged. The allow-prereleases
    input has no equivalent on setup-uv because uv treats prereleases
    as first-class.
  2. Pin to the immutable v8.1.0 tag. The floating v8 major tag
    does not exist; setup-uv switched to immutable releases at v8.0.0
    and only publishes per-version tags from then on.
  3. Drop the pip-cache wrapper and py-actions/py-dependency-install
    and install via uv pip instead. setup-uv does not seed
    pip into the venv, so the existing pip cache dir probe would
    crash the job; rather than seed pip back in just to keep the
    wrapper working, switch to enable-cache: true (which persists
    uv's own wheel cache across runs) and uv pip install -r requirements/pytest.txt. The pip --dry-run --report=- | jq
    wheel-discovery trick collapses into a single uv pip install --find-links=./dist call; uv picks the right wheel for the
    active interpreter directly.

Net: 58 fewer lines in the workflow and one tool (uv) doing both
the interpreter install and the dependency install with one cache.

Are there changes in behavior for the user?

No. This only affects CI runner provisioning. End-user-visible
behavior of multidict is unaffected.

Unlike yarl, multidict computes its runtime Python version in a
separate Compute runtime Python version step rather than
reading steps.python-install.outputs.python-version off the
setup action, so no Codecov flag shape changes here.

Is it a substantial burden for the maintainers to support this?

No. astral-sh/setup-uv is widely used across aio-libs and the
broader Python ecosystem; activate-environment: true plus
uv pip install reproduce the behavior the existing pipeline
already relies on.

Related issue number

N/A; ports aio-libs/yarl#1704 across to
multidict, whose matrix has the same 3.14t entry on macOS and
Windows.

Checklist

  • I think the code is well written
  • Unit tests for the changes exist -- N/A (CI configuration)
  • Documentation reflects the changes -- N/A (no user-visible change)
  • If you provide code modification, please add yourself to CONTRIBUTORS.txt
  • Add a new news fragment into the CHANGES/ folder (1351.contrib.rst)
Agent run details (optional, for reviewers)

Drafted with Claude Code (Opus 4.7); reviewed by @bdraco.

Direct port of aio-libs/yarl#1704 (merged). Commits mirror the
yarl PR's structure so the diff is easy to compare side-by-side:

multidict commit yarl commit
ci: install Python via astral-sh/setup-uv to skip slow downloads d10eecb
ci: pin astral-sh/setup-uv to the exact v8.1.0 tag 07327e0
ci: drop pip cache wrapper, install via uv pip d4ab3be

(yarl's intermediate Symlink CHANGES/1704.contrib.rst -> 1703.contrib.rst
commit does not apply here -- multidict has no separate tracking issue,
so the news fragment is named after the PR directly.)

This is a CI-only change; it cannot be exercised against the local
test suite. The full proof is the post-merge CI run on this PR
showing the matrix completing on all three OSes, which the
operator will check before flipping the PR out of draft.

Local verification:

  • make doc-spelling passes for the new fragment (the five
    misspellings reported are pre-existing entries in CHANGES.rst;
    the new 1351.contrib.rst is scanned by
    sphinxcontrib-towncrier and clean).
  • pre-commit ran on each commit: YAML lint, workflow
    validation, and the changelog/news-fragment role check all pass.

The macOS and Windows hosted runners do not keep pre-release or
free-threaded CPython variants in the tool-cache, so
`actions/setup-python` falls back to downloading them from the
`python-versions` repo on each run. For `3.14t` that adds tens of
seconds to jobs whose pytest run is shorter than the install step.

`astral-sh/setup-uv` fetches python-build-standalone from a CDN and
creates a seeded venv, which completes in a few seconds for the same
matrix entries. `activate-environment: true` keeps `python`/`pip`
on PATH so the rest of the pipeline (`py-actions/py-dependency-install`,
inline `pip install` calls, and the standalone `Compute runtime
Python version` step) is unchanged.

The `allow-prereleases` input has no equivalent on setup-uv because
uv treats prereleases as first-class.
@psf-chronographer psf-chronographer Bot added the bot:chronographer:provided There is a change note present in this PR label May 18, 2026
The floating `v8` major tag does not exist; setup-uv switched to
immutable releases at v8.0.0 and only publishes per-version tags
from then on. Use the exact `v8.1.0` tag (same style as the
existing `sigstore/gh-action-sigstore-python@v3.3.0` pin).
@codspeed-hq
Copy link
Copy Markdown

codspeed-hq Bot commented May 18, 2026

Merging this PR will not alter performance

✅ 242 untouched benchmarks


Comparing bdraco:ci/setup-uv-action (e858dca) with master (1ad8b48)

Open in CodSpeed

bdraco added 2 commits May 18, 2026 11:28
When `actions/setup-python` was the interpreter source, the
`Get pip cache dir` + `Cache PyPI` pair sped up the pip HTTP cache
across runs. With `astral-sh/setup-uv` and `activate-environment:
true` the venv is created without `--seed`, so pip is missing and
the wrapper's `pip cache dir` probe crashes the job.

Rather than seed pip back in just to keep the wrapper working,
go uv-native:

* Drop the `Get pip cache dir` + `Cache PyPI` pair (and the
  `actions/cache@v5` invocation) from the test-matrix job.
* Set `enable-cache: true` on both `setup-uv` invocations so uv's
  own wheel cache is persisted across runs.
* Replace `py-actions/py-dependency-install@v4` with a one-line
  `uv pip install -r requirements/pytest.txt`.
* Collapse the `pip --dry-run --report=-` + `jq` wheel-discovery
  trick and the follow-up `pip install <url>` into a single
  `uv pip install --find-links=./dist --no-index --no-deps
  --force-reinstall --only-binary=:all: multidict`. uv resolves
  the matching wheel for the active interpreter directly, so
  the intermediate JSON parse is unnecessary.
* Split the conditional `Self-install` step into two clearer
  steps gated on `build_type`; the source-build branch keeps
  the `MULTIDICT_NO_EXTENSIONS` / `MULTIDICT_DEBUG_BUILD` env
  pair, the wheel branch does not need either.
* Swap the inline `python -Im pip install build` in the
  build-pure-python-dists job for `uv pip install build` so
  the whole pipeline uses one cache.

Net: -65 lines, no more pip dependency in the venv, and every
install benefits from uv's resolver and cache.
`actions/setup-python@v6` accepts the `3.x` shorthand to mean
"latest 3.x release", but `astral-sh/setup-uv` passes the value
straight through to `uv venv --python <ver>`, and uv has no such
shorthand. The build-pure-python-dists job is the only consumer
of `${{ env.PYTHON_LATEST }}` in this workflow and was failing
with:

    error: No interpreter found for executable name `3.x` in
    managed installations or search path

Pin `PYTHON_LATEST` to `3.13`, matching the concrete-pin style
already in use by `reusable-linters.yml` (`PYTHON_LATEST: 3.12`)
and yarl's analogous job (`PYTHON_LATEST: 3.12`). Bump to 3.13
specifically because the test matrix already exercises 3.13 as
a stable target.
@bdraco
Copy link
Copy Markdown
Member Author

bdraco commented May 18, 2026

Closing in favor of a fresh PR with a clean single-commit history; the iterative back-and-forth on this branch (initial swap, v8.1.0 pin, pip-cache drop, PYTHON_LATEST fix) is noise. Reopening as a single coherent commit.

@bdraco bdraco closed this May 18, 2026
@bdraco bdraco deleted the ci/setup-uv-action branch May 18, 2026 18:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bot:chronographer:provided There is a change note present in this PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant