Jenkinsfile 和 Python virtualenv

Jenkinsfile and Python virtualenv

我正在尝试设置一个使用闪亮的新 Jenkins 管道的项目,更具体地说是一个多分支项目。

我在测试分支中创建了一个 Jenkinsfile,如下所示:

node {
    stage 'Preparing VirtualEnv'
    if (!fileExists('.env')){
        echo 'Creating virtualenv ...'
        sh 'virtualenv --no-site-packages .env'
    }
    sh '. .env/bin/activate'
    sh 'ls -all'
    if (fileExists('requirements/preinstall.txt')){
        sh 'pip install -r requirements/preinstall.txt'
    }
    sh 'pip install -r requirements/test.txt'
    stage 'Unittests'
    sh './manage.py test --noinput'
}

值得注意的是preinstall.txt会更新pip

我收到如下错误:

OSError: [Errno 13] Permission denied: '/usr/local/lib/python2.7/dist-packages/pip'

看起来它正在尝试在全局环境中而不是在 virtualenv 中更新 pip,而且每个 sh 步骤都在其自己的上下文中,如何让它们在相同的上下文中执行?

你正在尝试做的事情是行不通的。每次调用 sh 命令时,jenkins 都会创建一个新的 shell。

这意味着如果您在 sh 中使用 .env/bin/activate,它将仅在 shell 会话中使用。结果是,在新的 sh 命令中,您必须再次获取文件的来源(如果您仔细查看控制台输出,您会发现 Jenkins 实际上会在每次您 运行命令。

所以你应该在每个 shell 命令的开头获取 .env/bin/activate 文件(你可以对多行​​字符串使用三引号),就像这样

if (fileExists('requirements/preinstall.txt')) {
    sh """
    . .env/bin/activate
    pip install -r requirements/preinstall.txt
    """
}
...
sh """
. .env/bin/activate
pip install -r requirements/test.txt
"""
}
stage("Unittests") {
    sh """
    . .env/bin/activate
    ./manage.py test --noinput
    """
}

或运行合二为一shell

sh """
. .env/bin/activate
if [[ -f requirements/preinstall.txt ]]; then
    pip install -r requirements/preinstall.txt
fi
pip install -r requirements/test.txt
./manage.py test --noinput
"""

就像 Rik 发布的那样,virtualenvs 在 Jenkins 管道环境中不能很好地工作,因为每个命令都会创建一个新的 shell。

我创建了一个插件来减轻这个过程的痛苦,可以在这里找到:https://wiki.jenkins.io/display/JENKINS/Pyenv+Pipeline+Plugin。它本质上只是以一种在 运行 命令之前激活 virtualenv 的方式包装每个调用。这本身就很棘手,因为一些 运行 内联多个命令的方法被 Jenkins 分成两个单独的命令,导致激活的 virtualenv 不再适用。

我是 Jenkins 文件的新手。以下是我一直在解决虚拟环境问题的方法。 (我是 运行ning Python3,Jenkins 2.73.1)

警告:明确一点,我并不是说这是解决问题的好方法,我也没有对此进行足够的测试以支持这种方法,但今天对我有用的是:

我一直在尝试通过直接调用虚拟环境的 python 解释器来绕过 venv 'activate'。所以代替:

source ~/venv/bin/activate    

一个人可以使用:

~/venv/bin/python3 my_script.py

我通过 shell 的 rc 文件将路径传递到我的虚拟环境 python 解释器(在我的例子中,~/.bashrc。)理论上,每个 shell Jenkins 调用应该读取这个资源文件。实际上,我必须在更改 shell 资源文件后重新启动 Jenkins。

HOME_DIR=~
export VENV_PATH="$HOME_DIR/venvs/my_venv"
export PYTHON_INTERPRETER="${VENV_PATH}/bin/python3"

我的 Jenkinsfile 看起来类似于:

pipeline {
    agent {
        label 'my_slave'
    }

    stages {
        stage('Stage1') {
            steps {
                // sh 'echo $PYTHON_INTERPRETER'
                // sh 'env | sort'
                sh "$PYTHON_INTERPRETER my_script.py "
            }
        }
    }
}

因此,当管道为 运行 时,sh 设置了 $PYTHON_INTERPRETER 环境值。

请注意,此方法的一个缺点是现在 Jenkins 文件不包含正确 运行 脚本所需的所有信息。希望这会让你离开地面。