这个问题与在 Jenkins 管道中使用 Python + Poetry 项目以及如何保留.venv/
设想:
我有一个触发 Python 项目的 Jenkins Pipeline 作业。该项目使用诗歌在工作空间内的 .venv 中创建虚拟环境。每次后续作业运行,它将按预期重新使用 .venv ,因此每个 pip 包不需要在每次运行时重新下载(除非poetry.lock 文件中有差异)。一切都按预期工作。
我想使用 Jenkins Workspace Cleanup Plugin 对管道进行更改,我想破坏工作区文件但保留一些文件,包括 pip/poetry/venv 环境文件。这是为了允许它重新使用上一次运行中仍然存储在 .venv 中的 pip 包——就像它在今天的工作管道上一样。
完整的管道文件示例在这篇文章的底部,但这是我添加到现有管道中的 cleanWs() 部分的片段:
post {
always {
cleanWs(
deleteDirs: true,
notFailBuild: true,
patterns: [
[pattern: '.venv', type: 'EXCLUDE'],
[pattern: '.venv/**', type: 'EXCLUDE']
]
)
}
}
这是问题:
作业第一次运行时,它工作得非常好,工作区清理工作按预期工作。该
.venv/
目录按预期保留。(问题)在作业的后续运行中,诗歌将重新安装所有包并且不会重新使用 .venv 目录:
Creating virtualenv test in /data/jenkins_home/workspace/test-cleanup/.venv
-- 这会强制重新下载每个包,即使.venv
已经存在。在作业运行之前已确认/data/jenkins_home/workspace/test-cleanup/.venv
已存在。这是奇怪的部分:如果我在 Jenkins 服务器上手动转到工作区目录并运行与预期完全相同的命令 ,它会被重用并且不会重新安装所有包。因此,它在作业中运行的处理方式有一些特定的内容,这使得它想要重新创建 .venv 目录。
poetry install
.venv
注意in-project = true
已经为诗歌设置。所以它总是会尝试在当前工作目录中使用 .venv 。
例子:
这是一个按预期工作的简单示例管道。当poetry install
step 运行时,它不会在每次作业运行时重新下载所有包,只有第一次,或者如果有差异:
pipeline {
agent any
stages {
stage("Prep Build Environment") {
steps {
script {
scmVars = git branch: "main", poll: false, url: "[email protected]:my-org/private-repo.git"
}
sh "poetry install"
}
}
}
}
这是添加的新Jenkinsfile 管道文件cleanWs()
。添加后,项目将不再在每次运行时重新使用 .venv,即使它仍然存在:
pipeline {
agent any
stages {
stage("Prep Build Environment") {
steps {
script {
scmVars = git branch: "main", poll: false, url: "[email protected]:my-org/private-repo.git"
}
sh "poetry install"
}
}
}
post {
always {
cleanWs(
deleteDirs: true,
notFailBuild: true,
patterns: [
[pattern: '.venv', type: 'EXCLUDE'],
[pattern: '.venv/**', type: 'EXCLUDE']
]
)
}
}
}
通常,Jenkins Pipeline 会在构建开始时清理工作区,这就是为什么 .venv 文件夹在构建运行后存在但在下一次构建期间运行 virtualenv 步骤时不存在的原因。
如果您想在构建之间缓存或保留一些文件,最可靠的方法是将这些文件存储在工作区之外。但是,您需要非常小心,因为同时运行构建访问相同的文件可能会导致资源争用和竞争条件以及损坏的文件。
快速回答:
添加
[pattern: '.git/**', type: 'EXCLUDE']
到您的cleanWs()
模式列表中。工作区文件,包括
.venv/
将在作业运行之间持续存在。长答案:
所以问题似乎是 git 插件在
.git/
目录丢失时破坏了工作区(当它需要进行完整克隆时)。从我所看到的任何地方,我都没有看到这种行为记录在案。由于
cleanWs()
动作 removes.git
,它将触发 git 插件的这个“功能”。将
.git/
目录添加到排除列表似乎已经解决了原始问题并允许其他文件在构建之间保留。可以证明这种行为:
将文件写入工作区并签出 repo 的流水线步骤。
作业运行一次后,
foo.txt
将持续存在于工作区中:.git
克隆后删除数据:作业运行一次后,
foo.txt
现在将在每次作业运行开始时丢失:最后的帖子/总是阻止片段。诗歌安装和虚拟环境现在按预期工作: