跳转至

在 GitHub Actions 中使用 uv

安装

若要在 GitHub Actions 中使用,我们推荐官方的 astral-sh/setup-uv 操作,它可以安装 uv,将其添加到 PATH 中,(可选)持久化缓存等,支持所有 uv 支持的平台。

要安装最新版本的 uv:

example.yml
name: Example

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

    steps:
      - uses: actions/checkout@v4

      - name: 安装 uv
        uses: astral-sh/setup-uv@v5

将版本固定到特定的 uv 版本被视为最佳实践,例如:

example.yml
name: Example

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

    steps:
      - uses: actions/checkout@v4

      - name: 安装 uv
        uses: astral-sh/setup-uv@v5
        with:
          # 安装特定版本的 uv。
          version: "0.7.4"

安装 Python

可以使用 python install 命令安装 Python:

example.yml
name: Example

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

    steps:
      - uses: actions/checkout@v4

      - name: 安装 uv
        uses: astral-sh/setup-uv@v5

      - name: 安装 Python
        run: uv python install

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

或者,也可以使用官方的 GitHub setup-python 操作。这可能会更快,因为 GitHub 会将 Python 版本与运行器一起缓存。

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

example.yml
name: Example

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

    steps:
      - uses: actions/checkout@v4

      - name: 安装 uv
        uses: astral-sh/setup-uv@v5

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

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

example.yml
name: Example

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

    steps:
      - uses: actions/checkout@v4

      - name: 安装 uv
        uses: astral-sh/setup-uv@v5

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

多个 Python 版本

使用矩阵测试多个 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: 安装 uv 并设置 Python 版本
        uses: astral-sh/setup-uv@v5
        with:
          python-version: ${{ matrix.python-version }}

如果不使用 setup-uv 操作,可以设置 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: 安装 uv
        uses: astral-sh/setup-uv@v5

      - name: 安装项目
        run: uv sync --locked --all-extras --dev

      - name: 运行测试
        # 例如,使用 `pytest`
        run: uv run pytest tests

Tip

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

缓存

跨工作流程运行存储 uv 的缓存可能会缩短持续集成(CI)的时间。

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

example.yml
- 名称: 启用缓存
  使用: astral-sh/setup-uv@v5
  配置:
    enable-cache: true

你可以配置该操作,以便在运行器上使用自定义缓存目录:

example.yml
- 名称: 定义自定义 uv 缓存路径
  使用: astral-sh/setup-uv@v5
  配置:
    enable-cache: true
    cache-local-path: "/path/to/cache"

或者在锁定文件发生变化时使缓存失效:

example.yml
- 名称: 定义缓存依赖通配符
  使用: astral-sh/setup-uv@v5
  配置:
    enable-cache: true
    cache-dependency-glob: "uv.lock"

或者在任何需求文件发生变化时:

example.yml
- 名称: 定义缓存依赖通配符
  使用: astral-sh/setup-uv@v5
  配置:
    enable-cache: true
    cache-dependency-glob: "requirements**.txt"

请注意,astral-sh/setup-uv 将自动为每个主机架构和平台使用单独的缓存键。

或者,你可以使用 actions/cache 操作手动管理缓存:

example.yml
jobs:
  install_job:
    env:
      # 为 uv 缓存配置一个固定位置
      UV_CACHE_DIR: /tmp/.uv-cache

    steps:
      # ... 安装 Python 和 uv ...

      - 名称: 恢复 uv 缓存
        使用: actions/cache@v4
        配置:
          path: /tmp/.uv-cache
          key: uv-${{ runner.os }}-${{ hashFiles('uv.lock') }}
          restore-keys: |
            uv-${{ runner.os }}-${{ hashFiles('uv.lock') }}
            uv-${{ runner.os }}

      # ... 安装软件包、运行测试等 ...

      - 名称: 最小化 uv 缓存
        运行: uv cache prune --ci

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

Tip

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

Note

当使用非临时的自托管运行器时,默认缓存目录可能会无限制增长。在这种情况下,在作业之间共享缓存可能不是最佳选择。相反,将缓存移动到 GitHub 工作区中,并在作业完成后使用 [作业后钩子][post-job-hook] 将其删除。

install_job:
  env:
    # 为 uv 缓存配置一个相对位置
    UV_CACHE_DIR: ${{ github.workspace }}/.cache/uv

使用作业后钩子需要在自托管运行器上将 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 变量可在不同作用域中定义。

通过在顶级定义,为整个工作流程启用该设置:

example.yml
env:
  UV_SYSTEM_PYTHON: 1

jobs: ...

或者,为工作流程中的特定作业启用该设置:

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

或者,为作业中的特定步骤启用该设置:

example.yml
steps:
  - name: 安装依赖项
    run: uv pip install -r requirements.txt
    env:
      UV_SYSTEM_PYTHON: 1

若要再次禁用该设置,可在任何 uv 调用中使用 --no-system 标志。

[post-job-hook]: https://docs.github.com/en/actions/hosting-your-own-runners/managing-self-hosted-runners/running-scripts-before-or-after-a-job