使用 python uv 编写 ci/cd 流水线,核心在于利用其极速的依赖解析与安装能力替代传统的 pip 流程,并通过缓存机制显著缩短构建时间。具体做法是在 ci 配置文件中引入 uv 的安装步骤,使用 uv sync 命令在隔离环境中同步项目依赖,并配合 uv run 执行测试或构建任务。由于 uv 支持基于锁文件的确定性安装且速度极快,这种方案能有效解决传统 python 环境搭建耗时过长的问题。

如何在 GitHub Actions 中集成 uv 进行依赖安装
在 GitHub Actions 中集成 uv 进行依赖安装,主要步骤是设置环境变量、安装 uv 二进制文件以及执行同步操作。通过配置 actions/setup-python 或直接下载 uv 二进制包,可以在运行器中快速获得工具链。随后使用 uv sync --frozen 确保依赖版本与 uv.lock 文件严格一致,避免非确定性构建。这一过程通常比使用 pip 和 venv 的组合快数倍,特别是在大型项目中优势明显。

name: CI
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install uv
uses: astral-sh/setup-uv@v3
with:
version: "0.5.0"
- name: Sync dependencies
run: uv sync --frozen
- name: Run tests
run: uv run pytest
上述配置展示了标准的 GitHub Actions 工作流。首先检出代码,然后使用官方推荐的 setup-uv 动作安装 uv。接着执行 uv sync --frozen,这会读取 pyproject.toml 和 uv.lock,并在虚拟环境中安装所有精确版本的依赖。最后使用 uv run 调用 pytest 运行测试。整个过程无需手动创建虚拟环境,uv 会自动管理。--frozen 标志确保了构建的可重复性,如果锁文件与需求不匹配则直接报错。
立即学习“Python免费学习笔记(深入)”;
如何利用 uv 缓存加速 CI 构建过程
利用 uv 缓存加速 CI 构建过程,关键在于复用已下载的包和解析后的元数据。uv 默认将缓存存储在系统特定的目录中,如 Linux 下的 $XDG_CACHE_HOME/uv。在 CI 环境中,可以通过 actions/cache 动作将这些目录挂载到持久化存储中。这样,后续的运行可以直接从缓存中恢复依赖,跳过耗时的网络下载和解析阶段。结合 uv sync 的快速特性,整体构建时间可以进一步压缩。

name: CI with Cache
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install uv
uses: astral-sh/setup-uv@v3
- name: Cache uv
uses: actions/cache@v4
with:
path: ~/.cache/uv
key: ${{ runner.os }}-uv-${{ hashFiles('uv.lock') }}
- name: Sync dependencies
run: uv sync --frozen
- name: Run tests
run: uv run pytest
该配置在上一节的基础上增加了缓存步骤。使用 actions/cache 将 ~/.cache/uv 目录作为缓存路径。键值基于 uv.lock 文件的哈希值生成,这意味着只有当依赖列表发生变化时,缓存才会失效并重新下载。这极大地提高了构建效率,尤其是在依赖稳定不变的频繁提交场景中。注意,不同操作系统可能需要不同的缓存路径,因此使用 ${{ runner.os }} 前缀有助于区分平台特定的缓存。
uv sync 在 lock 文件缺失时会发生什么
当项目中存在 pyproject.toml 但缺少 uv.lock 文件时,执行 uv sync 会触发依赖解析并自动生成锁文件。uv 会根据 pyproject.toml 中定义的依赖约束,计算满足条件的最兼容版本集,并将结果写入 uv.lock。这一过程类似于 pip freeze 或 poetry lock,但速度更快。生成的锁文件随后会被用于后续的 uv sync --frozen 命令,确保环境的一致性。
# 假设 pyproject.toml 包含以下依赖
[project]
dependencies = [
"requests>=2.28.0",
"fastapi>=0.100.0"
]
# 执行 uv sync
$ uv sync
Resolved 15 packages in 0.5s
Installed 15 packages in 0.2s
# 此时 uv.lock 已生成
$ cat uv.lock | head -n 20
version = 1
requires-python = ">=3.9"
在这个示例中,项目仅指定了最低版本要求。首次运行 uv sync 时,uv 会解析这些约束,选择最新的兼容版本(例如 requests 2.31.0),并生成 uv.lock。之后的构建将直接使用锁文件中的精确版本。开发者应将 uv.lock 提交到版本控制系统中,以便团队成员和其他 CI 环境获得一致的依赖状态。如果希望强制锁定当前版本而不允许更新,可以在 CI 中使用 --frozen 标志,若锁文件不存在则会报错,提示先运行一次不带 --frozen 的同步。


















