我正在嘗試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 的首選方法。