> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/astral-sh/uv/llms.txt
> Use this file to discover all available pages before exploring further.

# GitHub Actions Integration

> Use uv in GitHub Actions workflows with caching, matrix builds, and CI/CD automation

Integrate uv into your GitHub Actions workflows for fast, reliable Python dependency management and CI/CD automation.

## Installation

<Steps>
  <Step title="Install latest version">
    Use the official `astral-sh/setup-uv` action:

    ```yaml theme={null}
    name: CI

    jobs:
      test:
        runs-on: ubuntu-latest
        steps:
          - uses: actions/checkout@v6

          - name: Install uv
            uses: astral-sh/setup-uv@v7
    ```
  </Step>

  <Step title="Pin to specific version (recommended)">
    ```yaml theme={null}
    - name: Install uv
      uses: astral-sh/setup-uv@v7
      with:
        version: "0.10.8"
    ```
  </Step>
</Steps>

## Setting Up Python

### Using uv python install

Install Python using uv (respects project's pinned version):

```yaml theme={null}
steps:
  - uses: actions/checkout@v6

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

  - name: Set up Python
    run: uv python install
```

### Using actions/setup-python

Alternatively, use GitHub's cached Python versions:

```yaml theme={null}
steps:
  - uses: actions/checkout@v6

  - 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 use `pyproject.toml` for the latest compatible version:

```yaml theme={null}
- name: Set up Python
  uses: actions/setup-python@v6
  with:
    python-version-file: "pyproject.toml"
```

## Matrix Builds

Test across multiple Python versions:

```yaml theme={null}
jobs:
  test:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        python-version:
          - "3.10"
          - "3.11"
          - "3.12"

    steps:
      - uses: actions/checkout@v6

      - name: Install uv and set Python version
        uses: astral-sh/setup-uv@v7
        with:
          python-version: ${{ matrix.python-version }}

      - name: Install dependencies
        run: uv sync --locked

      - name: Run tests
        run: uv run pytest
```

### Using UV\_PYTHON Environment Variable

```yaml theme={null}
jobs:
  test:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        python-version:
          - "3.10"
          - "3.11"
          - "3.12"
    env:
      UV_PYTHON: ${{ matrix.python-version }}

    steps:
      - uses: actions/checkout@v6
      - name: Install uv
        uses: astral-sh/setup-uv@v7
```

## Installing Dependencies

<Steps>
  <Step title="Sync project dependencies">
    ```yaml theme={null}
    - name: Install the project
      run: uv sync --locked --all-extras
    ```
  </Step>

  <Step title="Install without dev dependencies">
    ```yaml theme={null}
    - name: Install the project
      run: uv sync --locked --no-dev
    ```
  </Step>

  <Step title="Run tests">
    ```yaml theme={null}
    - name: Run tests
      run: uv run pytest tests
    ```
  </Step>
</Steps>

## Caching

### Built-in Caching with setup-uv

The easiest approach uses the action's built-in caching:

```yaml theme={null}
- name: Install uv with caching
  uses: astral-sh/setup-uv@v7
  with:
    enable-cache: true
```

### Manual Caching with actions/cache

For more control, use the `actions/cache` action:

```yaml theme={null}
jobs:
  test:
    runs-on: ubuntu-latest
    env:
      UV_CACHE_DIR: /tmp/.uv-cache

    steps:
      - uses: actions/checkout@v6

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

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

      - name: Install dependencies
        run: uv sync --locked

      - name: Run tests
        run: uv run pytest

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

<Note>
  Use `uv cache prune --ci` to optimize cache size. If using `uv pip`, replace `uv.lock` with `requirements.txt` in the cache key.
</Note>

## Complete CI Workflow

Here's a complete example combining best practices:

```yaml theme={null}
name: CI

on:
  push:
    branches: [main]
  pull_request:

jobs:
  test:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        python-version: ["3.10", "3.11", "3.12"]

    steps:
      - uses: actions/checkout@v6

      - name: Install uv
        uses: astral-sh/setup-uv@v7
        with:
          version: "0.10.8"
          enable-cache: true
          python-version: ${{ matrix.python-version }}

      - name: Install dependencies
        run: uv sync --locked --all-extras

      - name: Run linter
        run: uv run ruff check .

      - name: Run type checker
        run: uv run mypy .

      - name: Run tests
        run: uv run pytest tests --cov
```

## Using uv pip

If using the `uv pip` interface, enable system Python:

```yaml theme={null}
# Workflow-level
env:
  UV_SYSTEM_PYTHON: 1

jobs:
  test:
    steps:
      - name: Install dependencies
        run: uv pip install -r requirements.txt
```

Or at the job level:

```yaml theme={null}
jobs:
  test:
    env:
      UV_SYSTEM_PYTHON: 1
    steps:
      - name: Install dependencies
        run: uv pip install -r requirements.txt
```

Or at the step level:

```yaml theme={null}
steps:
  - name: Install requirements
    run: uv pip install -r requirements.txt
    env:
      UV_SYSTEM_PYTHON: 1
```

## Private Repositories

Access private GitHub repositories using a Personal Access Token (PAT):

<Steps>
  <Step title="Create and store PAT">
    Create a PAT with repository read access and add it as a repository secret (e.g., `MY_PAT`).
  </Step>

  <Step title="Configure Git credential helper">
    ```yaml theme={null}
    steps:
      - name: Register personal access token
        run: echo "${{ secrets.MY_PAT }}" | gh auth login --with-token

      - name: Configure Git credential helper
        run: gh auth setup-git

      - name: Install dependencies
        run: uv sync --locked
    ```
  </Step>
</Steps>

## Publishing to PyPI

Publish packages using trusted publishing (no credentials needed):

<Steps>
  <Step title="Create publish workflow">
    ```yaml theme={null}
    name: Publish

    on:
      push:
        tags:
          - v*

    jobs:
      publish:
        runs-on: ubuntu-latest
        environment:
          name: pypi
        permissions:
          id-token: write
          contents: read

        steps:
          - uses: actions/checkout@v6

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

          - name: Install Python
            run: uv python install 3.13

          - name: Build
            run: uv build

          - name: Test wheel
            run: uv run --isolated --no-project --with dist/*.whl tests/smoke_test.py

          - name: Test source distribution
            run: uv run --isolated --no-project --with dist/*.tar.gz tests/smoke_test.py

          - name: Publish
            run: uv publish
    ```
  </Step>

  <Step title="Configure PyPI environment">
    Create a `pypi` environment in your repository settings under Settings → Environments.
  </Step>

  <Step title="Add trusted publisher">
    Configure trusted publishing in your PyPI project settings, matching the workflow name, environment, and repository details.
  </Step>

  <Step title="Trigger release">
    ```bash theme={null}
    git tag -a v0.1.0 -m v0.1.0
    git push --tags
    ```
  </Step>
</Steps>

See [astral-sh/trusted-publishing-examples](https://github.com/astral-sh/trusted-publishing-examples) for a complete working example.
