我正在尝试使用virtualenv
编程方式管理 Jenkins 服务器上每个作业的 Python 环境,通过以下方式实现共享库扩展以根据每个作业激活环境。例如:
/vars/activateEnvironment.groovy
:
def call(String env = "/usr/local/etc/environments/jenkins-$JOB_NAME") {
sh """
mkdir ${env}
virtualenv ${env}
source ${env}/bin/activate
"""
}
管道脚本,其中virtualenv-scripts
存储库包含上述文件:
@Library('virtualenv-scripts') _
pipeline {
agent any
stages {
stage("Test") {
steps {
activateEnvironment()
sh 'which pip'
sh 'echo \$PATH'
}
}
}
}
运行此管道脚本,我得到以下输出:
[Pipeline] sh
[example-pipeline] Running shell script
+ echo /sbin:/usr/sbin:/bin:/usr/bin
/sbin:/usr/sbin:/bin:/usr/bin
[Pipeline] sh
[example-pipeline] Running shell script
+ which pip
/bin/pip
我试过使用这个答案让 Jenkins 使用登录 shell,但每次sh
调用时仍会重新加载环境。
我也看到了这个答案这就需要sh
在管道中每次使用某个步骤时粘贴额外的文本——这并不理想。
有没有一种好的方法可以让环境在sh
命令之间保持不变?或者,有没有更好的方法来实现每个作业的环境virtualenv
?感谢所有的帮助/建议!
答案1
我遇到了同样的问题。在与一些资深的 Jenkins 管理员交谈后,我找到了以下解决方案:
def runCommandInMyEnvironment(cmd) {
sh "setup_environment_command; source ./some/file; ${cmd}"
}
pipeline {
agent any
stages {
stage("My Stage") {
steps {
runCommandInMyEnvironment('first_command')
runCommandInMyEnvironment('second_command')
// and so on
}
}
}
}
它并不漂亮并且可能会使控制台输出变得混乱,但这也是最可靠的方法。
另一种方法是解析某些命令的输出并将其分成一系列环境变量,然后将它们传递给一个withEnv
块,但这可能非常棘手且不可靠。
无论如何,正如您所提到的,Jenkins 不支持没有的持久环境withEnv
,所以最终没有真正好的或干净的方法来做到这一点。
可能有更好的方法将虚拟环境与 Jenkins 结合使用,但我从未编写过在虚拟环境中运行任务的 Jenkins 作业,所以我不能说。这个插件, 但另一个 stackoverflow 答案表明我在这个答案中给出的方法是使用 Jenkins 中的虚拟环境的首选方法。