uv/docs/guides/integration/github.md
2024-09-07 02:18:15 +00:00

6.9 KiB

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@v4

      - name: Install uv
        uses: astral-sh/setup-uv@v2

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@v4

      - name: Install uv
        uses: astral-sh/setup-uv@v2
        with:
          # Install a specific version of uv.
          version: "0.4.7"

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@v4

      - name: Install uv
        uses: astral-sh/setup-uv@v2

      - name: Set up Python
        run: uv python install

This will respect the Python version pinned in the project.

Or, when using a matrix, as in:

strategy:
  matrix:
    python-version:
      - "3.10"
      - "3.11"
      - "3.12"

Provide the version to the python install invocation:

name: Example

jobs:
  uv-example:
    name: python
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4

      - name: Install uv
        uses: astral-sh/setup-uv@v2

      - name: Set up Python ${{ matrix.python-version }}
        run: uv python install ${{ matrix.python-version }}

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@v4

      - name: Install uv
        uses: astral-sh/setup-uv@v2

      - name: "Set up Python"
        uses: actions/setup-python@v5
        with:
          python-version-file: ".python-version"

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@v4

      - name: Install uv
        uses: astral-sh/setup-uv@v2

      - name: "Set up Python"
        uses: actions/setup-python@v5
        with:
          python-version-file: "pyproject.toml"

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@v4

      - name: Install uv
        uses: astral-sh/setup-uv@v2

      - name: Set up Python
        run: uv python install

      - name: Install the project
        run: uv sync --all-extras --dev

      - name: Run tests
        # For example, using `pytest`
        run: uv run pytest tests

!!! tip

The
[`UV_PROJECT_ENVIRONMENT` setting](../../concepts/projects.md#configuring-the-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@v2
  with:
    enable-cache: true

You can configure the action to use a custom cache directory on the runner:

- name: Define a custom uv cache path
  uses: astral-sh/setup-uv@v2
  with:
    enable-cache: true
    cache-local-path: "/path/to/cache"

Or invalidate it when the lockfile changes:

- name: Define a cache dependency glob
  uses: astral-sh/setup-uv@v2
  with:
    enable-cache: true
    cache-dependency-glob: "uv.lock"

Or when any requirements file changes:

- name: Define a cache dependency glob
  uses: astral-sh/setup-uv@v2
  with:
    enable-cache: true
    cache-dependency-glob: "requirements**.txt"

Note that astral-sh/setup-uv will automatically use a separate cache key for each host architecture and platform.

Alternatively, you can manage the cache manually with the actions/cache action:

jobs:
  install_job:
    env:
      # Configure a constant location for the uv cache
      UV_CACHE_DIR: /tmp/.uv-cache

    steps:
      # ... setup up Python and uv ...

      - name: Restore uv cache
        uses: actions/cache@v4
        with:
          path: /tmp/.uv-cache
          key: uv-${{ runner.os }}-${{ hashFiles('uv.lock') }}
          restore-keys: |
            uv-${{ runner.os }}-${{ hashFiles('uv.lock') }}
            uv-${{ runner.os }}

      # ... install packages, run tests, etc ...

      - name: Minimize uv cache
        run: uv cache prune --ci

The uv cache prune --ci command is used to reduce the size of the cache and is optimized for CI. Its effect on performance is dependent on the packages being installed.

!!! tip

If using `uv pip`, use `requirements.txt` instead of `uv.lock` in the cache key.

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.