跳到内容

在 GitHub Actions 中使用 uv

安装

对于 GitHub Actions 的使用,我们推荐官方的 astral-sh/setup-uv action,它会安装 uv,将其添加到 PATH,(可选)持久化缓存,并支持所有 uv 支持的平台。

安装 uv 的最新版本

example.yml
name: Example

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

    steps:
      - uses: actions/checkout@v4

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

最佳实践是固定到特定的 uv 版本,例如:

example.yml
name: Example

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

    steps:
      - uses: actions/checkout@v4

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

设置 Python

可以使用 python install 命令安装 Python

example.yml
name: Example

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

    steps:
      - uses: actions/checkout@v4

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

      - name: Set up Python
        run: uv python install

这将遵循项目中固定的 Python 版本。

或者,可以使用官方 GitHub setup-python action。这可能会更快,因为 GitHub 会将 Python 版本与 runner 一起缓存。

设置 python-version-file 选项,以使用项目的固定版本

example.yml
name: Example

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

    steps:
      - uses: actions/checkout@v4

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

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

或者,指定 pyproject.toml 文件以忽略 pin 并使用与项目的 requires-python 约束兼容的最新版本

example.yml
name: Example

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

    steps:
      - uses: actions/checkout@v4

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

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

多个 Python 版本

当使用 matrix 测试多个 Python 版本时,使用 astral-sh/setup-uv 设置 Python 版本,这将覆盖 pyproject.toml.python-version 文件中的 Python 版本规范

example.yml
jobs:
  build:
    name: continuous-integration
    runs-on: ubuntu-latest
    strategy:
      matrix:
        python-version:
          - "3.10"
          - "3.11"
          - "3.12"

    steps:
      - uses: actions/checkout@v4

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

如果不使用 setup-uv action,您可以设置 UV_PYTHON 环境变量

example.yml
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@v4

同步和运行

安装 uv 和 Python 后,可以使用 uv sync 安装项目,并使用 uv run 在环境中运行命令

example.yml
name: Example

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

    steps:
      - uses: actions/checkout@v4

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

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

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

提示

UV_PROJECT_ENVIRONMENT 设置 可用于安装到系统 Python 环境,而不是创建虚拟环境。

缓存

跨 workflow 运行存储 uv 的缓存可以提高 CI 时间。

astral-sh/setup-uv 内置了对持久化缓存的支持

example.yml
- name: Enable caching
  uses: astral-sh/setup-uv@v6
  with:
    enable-cache: true

或者,您可以使用 actions/cache action 手动管理缓存

example.yml
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

uv cache prune --ci 命令用于减小缓存大小,并针对 CI 进行了优化。它对性能的影响取决于正在安装的软件包。

提示

如果使用 uv pip,请在缓存 key 中使用 requirements.txt 而不是 uv.lock

注意

当使用非临时性的自托管 runners 时,默认缓存目录可能会无限增长。在这种情况下,在作业之间共享缓存可能不是最佳选择。相反,将缓存移动到 GitHub Workspace 中,并在作业完成后使用 Post Job Hook 将其删除。

install_job:
  env:
    # Configure a relative location for the uv cache
    UV_CACHE_DIR: ${{ github.workspace }}/.cache/uv

使用 post job hook 需要在自托管 runner 上将 ACTIONS_RUNNER_HOOK_JOB_STARTED 环境变量设置为清理脚本的路径,如下所示。

clean-uv-cache.sh
#!/usr/bin/env sh
uv cache clean

使用 uv pip

如果使用 uv pip 接口而不是 uv 项目接口,则默认情况下 uv 需要虚拟环境。要允许将软件包安装到系统环境中,请在所有 uv 调用上使用 --system 标志或设置 UV_SYSTEM_PYTHON 变量。

UV_SYSTEM_PYTHON 变量可以在不同的范围内定义。

通过在顶层定义它来选择整个 workflow

example.yml
env:
  UV_SYSTEM_PYTHON: 1

jobs: ...

或者,选择 workflow 中的特定作业

example.yml
jobs:
  install_job:
    env:
      UV_SYSTEM_PYTHON: 1
    ...

或者,选择作业中的特定步骤

example.yml
steps:
  - name: Install requirements
    run: uv pip install -r requirements.txt
    env:
      UV_SYSTEM_PYTHON: 1

要再次选择退出,可以在任何 uv 调用中使用 --no-system 标志。

私有仓库

如果您的项目对私有 GitHub 仓库有 依赖,您需要配置一个 个人访问令牌 (PAT) 以允许 uv 获取它们。

创建具有对私有仓库的读取权限的 PAT 后,将其添加为 仓库密钥

然后,您可以使用 gh CLI(默认安装在 GitHub Actions runners 中)配置一个 Git 凭证助手,以使用 PAT 查询托管在 github.com 上的仓库。

例如,如果您将仓库密钥称为 MY_PAT

example.yml
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