GitLab CI中uv Python项目无法缓存环境及依赖,如何解决?
在GitLab CI(Shell执行器)中复用uv缓存与虚拟环境的解决方案
问题描述
在Linux机器上部署了Shell执行器的GitLab Runner,用于测试采用uv管理虚拟环境与依赖的Python项目。按照uv官方文档配置.gitlab-ci.yml后缓存完全未生效,每次流水线运行时,.uv-cache缓存目录和.venv虚拟环境都会被删除后重建,依赖下载耗时极长。
当前使用的.gitlab-ci.yml配置:
# GitLab CI for custom runner instance with shell executor # Requires uv installed for gitlab-runner user stages: - check - test variables: UV_CACHE_DIR: .uv-cache cache: - key: files: - uv.lock paths: - $UV_CACHE_DIR checks: stage: check script: - uv sync - uv run ruff check . - uv run ruff format --check . - uv cache prune --ci tests: stage: test script: - uv sync - uv run pytest - uv cache prune --ci
流水线日志片段:
以git深度20拉取变更... 重新初始化现有Git仓库于/home/cloud/builds/t2_jESXhP/0/ai4ops/risk-analysis/.git/ 检出94d41e64作为分离HEAD(引用为fix-checks)... 正在删除.uv-cache/ 正在删除.venv/ 跳过Git子模块设置 恢复缓存 00:00 检查缓存0_uv-8be8d005e56e2d62177fb81b4081e3dc73657342-non_protected... 运行平台 arch=amd64 os=linux pid=184162 revision=4d7093e1 version=18.0.2 未提供URL,将不会从共享缓存服务器下载缓存,而是提取本地版本的缓存 警告:缓存文件不存在 提取缓存失败 执行作业脚本的"step_script"阶段 00:42 $ uv sync 使用CPython 3.12.10 在.venv创建虚拟环境 1ms内解析215个包 Downloading pygments (1.2MiB) Downloading setuptools (1.1MiB) Downloading numpy (15.8MiB) ...
解决方案
1. 阻止Runner清理缓存与虚拟环境目录
Shell执行器默认会清理项目目录中的未追踪文件,.uv-cache和.venv属于未追踪文件,因此会被删除。需添加GIT_CLEAN_FLAGS变量排除这两个目录:
variables: UV_CACHE_DIR: .uv-cache # 禁止清理目标目录 GIT_CLEAN_FLAGS: -ffdx -e .uv-cache -e .venv
2. 扩展缓存路径至虚拟环境
虚拟环境.venv也需要纳入缓存范围,避免每次重建。可添加Python版本作为缓存key前缀,防止跨版本缓存冲突:
cache: key: files: - uv.lock prefix: "py3.12" # 与项目使用的Python版本匹配 paths: - $UV_CACHE_DIR - .venv policy: pull-push # 确保作业既拉取又推送缓存
3. 优化uv sync命令避免重复重建环境
缓存恢复.venv后,使用--frozen参数仅同步依赖,不强制重建虚拟环境:
checks: stage: check script: - if [ ! -d .venv ]; then uv sync; else uv sync --frozen; fi - uv run ruff check . - uv run ruff format --check . tests: stage: test script: - if [ ! -d .venv ]; then uv sync; else uv sync --frozen; fi - uv run pytest
4. 验证Runner本地缓存配置
确保GitLab Runner配置文件(/etc/gitlab-runner/config.toml)开启本地缓存,且缓存目录权限正确:
[[runners]] name = "Shell Runner" executor = "shell" [runners.cache] Type = "local" Path = "/var/gitlab-runner/cache" # 自定义缓存目录 Shared = true
注意:需保证gitlab-runner用户对该目录有读写权限。
5. 集中执行缓存清理
uv cache prune --ci会清理未使用的缓存,建议只在流水线最后阶段执行一次,避免提前清理有效缓存:
cleanup: stage: cleanup script: - uv cache prune --ci when: always
最终完整配置示例
# GitLab CI for custom runner instance with shell executor # Requires uv installed for gitlab-runner user stages: - check - test - cleanup variables: UV_CACHE_DIR: .uv-cache GIT_CLEAN_FLAGS: -ffdx -e .uv-cache -e .venv cache: key: files: - uv.lock prefix: "py3.12" paths: - $UV_CACHE_DIR - .venv policy: pull-push checks: stage: check script: - if [ ! -d .venv ]; then uv sync; else uv sync --frozen; fi - uv run ruff check . - uv run ruff format --check . tests: stage: test script: - if [ ! -d .venv ]; then uv sync; else uv sync --frozen; fi - uv run pytest cleanup: stage: cleanup script: - uv cache prune --ci when: always
内容的提问来源于stack exchange,提问作者wigging
相关产品推荐
相关产品推荐

