9.5 KiB
| title | description |
|---|---|
| Using uv in GitHub Actions | A guide to using uv in GitHub Actions, including installation, setting up Python, installing dependencies, and more. |
Using uv in GitHub Actions
Installation
For use with GitHub Actions, we recommend the official
astral-sh/setup-uv action, which installs uv, adds it to
PATH, (optionally) persists the cache, and more, with support for all uv-supported platforms.
To install the latest version of uv:
name: Example
jobs:
uv-example:
name: python
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- name: Install uv
uses: astral-sh/setup-uv@v7
It is considered best practice to pin to a specific uv version, e.g., with:
name: Example
jobs:
uv-example:
name: python
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- name: Install uv
uses: astral-sh/setup-uv@v7
with:
# Install a specific version of uv.
version: "0.9.18"
Setting up Python
Python can be installed with the python install command:
name: Example
jobs:
uv-example:
name: python
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- name: Install uv
uses: astral-sh/setup-uv@v7
- name: Set up Python
run: uv python install
This will respect the Python version pinned in the project.
Alternatively, the official GitHub setup-python action can be used. This can be faster, because
GitHub caches the Python versions alongside the runner.
Set the
python-version-file
option to use the pinned version for the project:
name: Example
jobs:
uv-example:
name: python
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- name: "Set up Python"
uses: actions/setup-python@v6
with:
python-version-file: ".python-version"
- name: Install uv
uses: astral-sh/setup-uv@v7
Or, specify the pyproject.toml file to ignore the pin and use the latest version compatible with
the project's requires-python constraint:
name: Example
jobs:
uv-example:
name: python
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- name: "Set up Python"
uses: actions/setup-python@v6
with:
python-version-file: "pyproject.toml"
- name: Install uv
uses: astral-sh/setup-uv@v7
Multiple Python versions
When using a matrix to test multiple Python versions, set the Python version using
astral-sh/setup-uv, which will override the Python version specification in the pyproject.toml
or .python-version files:
jobs:
build:
name: continuous-integration
runs-on: ubuntu-latest
strategy:
matrix:
python-version:
- "3.10"
- "3.11"
- "3.12"
steps:
- uses: actions/checkout@v5
- name: Install uv and set the Python version
uses: astral-sh/setup-uv@v7
with:
python-version: ${{ matrix.python-version }}
If not using the setup-uv action, you can set the UV_PYTHON environment variable:
jobs:
build:
name: continuous-integration
runs-on: ubuntu-latest
strategy:
matrix:
python-version:
- "3.10"
- "3.11"
- "3.12"
env:
UV_PYTHON: ${{ matrix.python-version }}
steps:
- uses: actions/checkout@v5
Syncing and running
Once uv and Python are installed, the project can be installed with uv sync and commands can be
run in the environment with uv run:
name: Example
jobs:
uv-example:
name: python
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- name: Install uv
uses: astral-sh/setup-uv@v7
- name: Install the project
run: uv sync --locked --all-extras --dev
- name: Run tests
# For example, using `pytest`
run: uv run pytest tests
!!! tip
The
[`UV_PROJECT_ENVIRONMENT` setting](../../concepts/projects/config.md#project-environment-path) can
be used to install to the system Python environment instead of creating a virtual environment.
Caching
It may improve CI times to store uv's cache across workflow runs.
The astral-sh/setup-uv has built-in support for
persisting the cache:
- name: Enable caching
uses: astral-sh/setup-uv@v7
with:
enable-cache: true
The documentation also explains how you can control the caching e.g. what to cache and when to cache.
Using uv pip
If using the uv pip interface instead of the uv project interface, uv requires a virtual
environment by default. To allow installing packages into the system environment, use the --system
flag on all uv invocations or set the UV_SYSTEM_PYTHON variable.
The UV_SYSTEM_PYTHON variable can be defined in at different scopes.
Opt-in for the entire workflow by defining it at the top level:
env:
UV_SYSTEM_PYTHON: 1
jobs: ...
Or, opt-in for a specific job in the workflow:
jobs:
install_job:
env:
UV_SYSTEM_PYTHON: 1
...
Or, opt-in for a specific step in a job:
steps:
- name: Install requirements
run: uv pip install -r requirements.txt
env:
UV_SYSTEM_PYTHON: 1
To opt-out again, the --no-system flag can be used in any uv invocation.
Private repos
If your project has dependencies on private GitHub repositories, you will need to configure a personal access token (PAT) to allow uv to fetch them.
After creating a PAT that has read access to the private repositories, add it as a repository secret.
Then, you can use the gh CLI (which is installed in GitHub Actions
runners by default) to configure a
credential helper for Git to use the
PAT for queries to repositories hosted on github.com.
For example, if you called your repository secret MY_PAT:
steps:
- name: Register the personal access token
run: echo "${{ secrets.MY_PAT }}" | gh auth login --with-token
- name: Configure the Git credential helper
run: gh auth setup-git
Publishing to PyPI
uv can be used to build and publish your package to PyPI from GitHub Actions. We provide a standalone example alongside this guide in astral-sh/trusted-publishing-examples. The workflow uses trusted publishing, so no credentials need to be configured.
In the example workflow, we use a script to test that the source distribution and the wheel are both functional and we didn't miss any files. This step is recommended, but optional.
First, add a release workflow to your project:
name: "Publish"
on:
push:
tags:
# Publish on any tag starting with a `v`, e.g., v0.1.0
- v*
jobs:
run:
runs-on: ubuntu-latest
environment:
name: pypi
permissions:
id-token: write
contents: read
steps:
- name: Checkout
uses: actions/checkout@v5
- name: Install uv
uses: astral-sh/setup-uv@v7
- name: Install Python 3.13
run: uv python install 3.13
- name: Build
run: uv build
# Check that basic features work and we didn't miss to include crucial files
- name: Smoke test (wheel)
run: uv run --isolated --no-project --with dist/*.whl tests/smoke_test.py
- name: Smoke test (source distribution)
run: uv run --isolated --no-project --with dist/*.tar.gz tests/smoke_test.py
- name: Publish
run: uv publish
Then, create the environment defined in the workflow in the GitHub repository under "Settings" -> "Environments".
Add a trusted publisher to your PyPI project in the project settings under "Publishing". Ensure that all fields match with your GitHub configuration.
After saving:
Finally, tag a release and push it. Make sure it starts with v to match the pattern in the
workflow.
$ git tag -a v0.1.0 -m v0.1.0
$ git push --tags


