Jenkins 中使用 virtualenv 的每個作業環境

Jenkins 中使用 virtualenv 的每個作業環境

我正在嘗試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,因此最終沒有真正好的或乾淨的方法來做到這一點。

可能有更好的方法將 virtualenvs 與 Jenkins 結合使用,但我從未編寫過在 virtualenv 中運行任務的 Jenkins 作業,所以我不能說。有這個插件, 但另一個 stackoverflow 答案表明我在這個答案中給出的方法是在 Jenkins 中使用 virtualenvs 的首選方法。

相關內容