You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在GitLab CI/CD中正确缓存Poetry虚拟环境?

问题描述

我需要在GitLab CI/CD的Python应用构建之间缓存Poetry虚拟环境,已配置流水线仅在lego/pyproject.toml变更时重建虚拟环境(未提交poetry.lock),当前缓存配置如下:

default:
  cache:
    - key:
        files:
        - lego/pyproject.toml
      paths:
        - lego/.venv
        - artifacts/build/layer/build/.venv
    - paths:
        - artifacts/pypoetry

创建虚拟环境的命令为:

poetry config virtualenvs.in-project true
poetry install

本地测试正常,但第二次CI流水线运行时出现错误:

$ LOG_LEVEL=ERROR poetry run pytest tests -n auto -v --cov=./src --junitxml=lego-report.xml

ImportError while loading conftest '/builds/5565557/lddpro-bff/lego/tests/conftest.py'.
tests/conftest.py:22: in <module>
   from lego.common.aws import S3, EventBridge, SSM, Secrets
E ModuleNotFoundError: No module named 'lego'

排查发现,虚拟环境.venv中存在根包的lego.pth文件,但文件内的路径为上一次Job的绝对路径:

$ cat .venv/lib/python*/site-packages/lego.pth
/builds/5565557/lddpro-bff/lego/src

由于GitLab CI每次Job的工作目录路径可能因Job ID不同而变化,缓存的虚拟环境中.pth文件的绝对路径与当前Job路径不匹配,导致pytest无法找到根包。

解决方案

方案1:提交poetry.lock并优化缓存键

提交poetry.lock到仓库,不仅能确保依赖版本一致性,还能让缓存键更精准(只有依赖配置变更时才重建缓存),同时Poetry在恢复缓存后的安装步骤中会自动处理路径问题。

修改缓存配置:

default:
  cache:
    - key:
        files:
        - lego/pyproject.toml
        - lego/poetry.lock
      paths:
        - lego/.venv
        - artifacts/build/layer/build/.venv
    - paths:
        - artifacts/pypoetry

方案2:缓存恢复后更新根包路径

无论缓存是否存在,在poetry install前添加路径更新逻辑。由于Poetry的可编辑安装依赖绝对路径,缓存恢复后只需重新触发根包的链接即可,无需重新安装所有依赖。

修改Job的script部分:

script:
  - cd lego
  - poetry config virtualenvs.in-project true
  # 缓存存在时仅更新根包路径,不存在则完整安装
  - if [ -d .venv ]; then poetry install --no-root; else poetry install; fi
  - poetry env info
  - env LOG_LEVEL=ERROR poetry run pytest tests -n auto -v --cov=./src --junitxml=${REPORT_NAME}
  - mv -f ${REPORT_NAME} ${CI_PROJECT_DIR}/ || echo ""
  - cd ${CI_PROJECT_DIR}
  - mkdir -p artifacts
  - cd tools
  - . ./build_deploy.sh --command=build --debug

注:poetry install --no-root会跳过根包的安装,但会更新可编辑安装的路径配置,比完整安装更快。如果不确定依赖是否有变更,直接执行poetry install也可,Poetry会自动校验依赖并仅更新必要部分。

方案3:手动修正.pth文件路径(临时hack)

如果无法提交poetry.lock,可在缓存恢复后手动替换.pth文件中的绝对路径为当前Job的路径:

修改script部分:

script:
  - cd lego
  - poetry config virtualenvs.in-project true
  # 若缓存存在,修正.pth文件中的路径
  - if [ -d .venv ]; then
      CURRENT_SRC=$(realpath src)
      find .venv/lib/python*/site-packages -name "*.pth" -exec sed -i "s|^/builds/.*lego/src|$CURRENT_SRC|" {} \;
    fi
  - poetry install
  - poetry env info
  - env LOG_LEVEL=ERROR poetry run pytest tests -n auto -v --cov=./src --junitxml=${REPORT_NAME}
  # 后续命令不变

内容的提问来源于stack exchange,提问作者Shuzheng

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 08:17:48