Jenkins 中使用 virtualenv 的每个作业环境

cwh*_*cwh 3 python bash virtualenv jenkins

我正在尝试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
    """
}
Run Code Online (Sandbox Code Playgroud)

管道脚本,其中virtualenv-scripts存储库包含上述文件:

@Library('virtualenv-scripts') _

pipeline {
    agent any
    stages {
        stage("Test") {
            steps {
                activateEnvironment()
                sh 'which pip'
                sh 'echo \$PATH'
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

运行此管道脚本,我得到以下输出:

[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
Run Code Online (Sandbox Code Playgroud)

我尝试使用此答案使 Jenkins 使用登录 shell,但这仍然会在每次sh调用时重新加载环境。

我还看到了这个答案sh,每次在管道中使用步骤时都需要粘贴额外的文本——这并不理想。

有没有办法让环境在sh命令之间持续存在?或者,是否有更好的方法来实现按作业环境virtualenv?感谢您的所有帮助/建议!

jay*_*ren 6

我遇到过同样的问题。在与一些经验丰富的 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
      }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

它并不漂亮,而且会使控制台输出变得相当混乱,但这也是最可靠的方法。

另一种方法是解析某些命令的输出并将其分成一堆环境变量,然后将它们传递给一个withEnv块,但这可能是一种非常棘手且不可靠的方法。

无论如何,正如您所提到的,Jenkins 不支持没有 的持久环境withEnv,因此最终没有真正好的或干净的方法来做到这一点。

可能有更好的方法将 virtualenvs 与 Jenkins 结合使用,但我从未编写过在 virtualenv 中运行任务的 Jenkins 作业,所以我不能说。有这个插件,但另一个 stackoverflow 答案表明我在这个答案中给出的方法是在 Jenkins 中使用 virtualenvs 的首选方法。