如何在Jenkins中创建Python virtualenv?

如何在Jenkins中创建Python virtualenv?,jenkins,virtualenv,Jenkins,Virtualenv,我正在使用Makefile提供一致的单个命令,用于设置virtualenv、运行测试等。我已将Jenkins实例配置为从mercurial repo中提取,然后运行“make virtualenv”,它可以实现以下功能: virtualenv --python=/usr/bin/python2.7 --no-site-packages . && . ./bin/activate && pip install -r requirements.txt 但出于某种原因

我正在使用Makefile提供一致的单个命令,用于设置virtualenv、运行测试等。我已将Jenkins实例配置为从mercurial repo中提取,然后运行“make virtualenv”,它可以实现以下功能:

virtualenv --python=/usr/bin/python2.7 --no-site-packages . && . ./bin/activate && pip install -r requirements.txt
但出于某种原因,它坚持使用系统安装的pip,并尝试在系统站点软件包而不是virtualenv中安装我的软件包依赖项:

error: could not create '/usr/local/lib/python2.7/dist-packages/flask': Permission denied
如果我添加一些调试命令并明确指向virtualenv中的pip,事情会变得更加混乱:

virtualenv --python=/usr/bin/python2.7 --no-site-packages . && . ./bin/activate && ls -l bin && which pip && pwd && ./bin/pip install -r requirements.txt
这将生成以下输出:

New python executable in ./bin/python2.7
Not overwriting existing python script ./bin/python (you must use ./bin/python2.7)
Installing setuptools, pip...done.
Running virtualenv with interpreter /usr/bin/python2.7
Jenkins似乎没有为每个构建从头开始重建环境,这让我觉得是一个奇怪的选择,但不应该影响我眼前的问题

“ls-l bin”的输出显示要安装在virtualenv和可执行文件中的pip:

-rw-r--r-- 1 jenkins jenkins    2248 Apr  9 21:14 activate
-rw-r--r-- 1 jenkins jenkins    1304 Apr  9 21:14 activate.csh
-rw-r--r-- 1 jenkins jenkins    2517 Apr  9 21:14 activate.fish
-rw-r--r-- 1 jenkins jenkins    1129 Apr  9 21:14 activate_this.py
-rwxr-xr-x 1 jenkins jenkins     278 Apr  9 21:14 easy_install
-rwxr-xr-x 1 jenkins jenkins     278 Apr  9 21:14 easy_install-2.7
-rwxr-xr-x 1 jenkins jenkins     250 Apr  9 21:14 pip
-rwxr-xr-x 1 jenkins jenkins     250 Apr  9 21:14 pip2
-rwxr-xr-x 1 jenkins jenkins     250 Apr  9 21:14 pip2.7
lrwxrwxrwx 1 jenkins jenkins       9 Apr 10 19:31 python -> python2.7
lrwxrwxrwx 1 jenkins jenkins       9 Apr 10 19:31 python2 -> python2.7
-rwxr-xr-x 1 jenkins jenkins 3349512 Apr 10 19:31 python2.7
“which pip”的输出似乎希望使用正确的输出:

/var/lib/jenkins/jobs/Run Tests/workspace/bin/pip
我当前的工作目录是我期望的:

/var/lib/jenkins/jobs/Run Tests/workspace
但是。。。wtf

/bin/sh: 1: ./bin/pip: Permission denied
make: *** [virtualenv] Error 126
Build step 'Execute shell' marked build as failure
Finished: FAILURE

我也有同样的问题。如我所见,您的项目名为“运行测试”。因此,这个名称包含空格。这就是我的问题所在。我刚刚重新命名了这个项目,就像RunTests一样——现在venv正在工作!注意-jenkins向您询问确认重命名项目。

在过去两年中,我每天都在jenkins使用python virtualenvs,在多家公司和小型项目中使用,我不能说我找到了“答案”。尽管如此,我还是希望分享我的经验能帮助其他人节省时间。希望我能得到进一步的反馈,以使决策更容易

  • 避免ShiningPanda-它没有得到很好的维护,与Jenkins2管道不兼容,并阻止并行执行作业。它还有一个坏习惯,就是将孤立环境留在磁盘上
  • 通过bash和virtualenv进行DIY是我当前的最爱。在$WORKSPACE中创建它,如果不总是清理,请在激活它们之前运行。这是因为jenkins workspace文件夹磁盘位置可以在执行作业N和N+1之间更改
如果您使用的多个构建器确实需要相同的virtualenv,最简单的方法是将您的环境转储到一个文件中,并在新构建器的开始处对其进行源代码生成

为了便于维护,我计划调查以下内容:

  • 迪伦姆
  • virtualenv包装器(mkvirtualenv)
  • 皮恩夫

如果你点击shebang命令行,最好的办法是将jenkins的主目录改为just
/j

我建议不要使用ShiningPanda

我使用/设置虚拟环境。安装conda时,确保您以jenkins用户的身份运行

your_user@$ sudo -u jenkins sh
jenkins@$ wget https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh
jenkins@$ bash Miniconda3-latest-Linux-x86_64.sh
由于Jenkins运行的是
sh
而不是
bash
,因此我将conda路径添加到
/etc/profile

export PATH="/var/lib/jenkins/miniconda3/bin:$PATH"
然后在Jenkins文件中,您可以创建和删除conda环境。下面是一个为每个构建创建新环境的示例:

pipeline {
    agent any
    stages {
        stage('Unit tests') {
            steps {
            sh '''
                conda create --yes -n ${BUILD_TAG} python
                source activate ${BUILD_TAG}
                // example of unit test with nose2
                pip install nose2
                nose2
            '''
            }
        }
    }
    post {
        always {
            sh 'conda remove --yes -n ${BUILD_TAG} --all'
        }
    }
}

詹金斯管道可以用虚拟环境运行,但是有很多事情要考虑。

  • Jenkins使用的默认shell是
    /bin/sh
    ——可在管理Jenkins->配置系统->shell->shell可执行文件中配置。将此设置为
    /bin/bash
    将使
    source
    工作
  • 激活的venv只会改变环境变量,而环境变量不会在jenkins的各个阶段之间持续存在。看
  • 如果您使用的是版本控制的多分支管道,jenkins将创建一个带有分支名称的工作区,并在路径中创建一个提交散列,这可能相当长。venv脚本(例如pip)都以hashbang行开始,该行包括venv中python解释器的完整路径(python解释器本身是一个符号链接)。例如:

    Bash只读取任何可执行文件的第一个
    N
    字符,我发现其中不包括完整的venv路径:

    bash: ./pip: /var/jenkins_home/workspace/ink_feature-use-jenkinsfile-VGRPYD53GGGDDSBIJDLSU: bad interpreter: No such file or directory
    
    使用Python执行脚本可以避免这个特殊问题。例如,
    python3.5./pip


不同操作系统环境下的venv python插件存在一些问题

下面是我如何手动调用python方法。不是最佳实践,但它是有效的

//将此阶段置于管道顶部
阶段(“准备venv”){
台阶{
剧本{
if(isUnix()){
env.ISUNIX=“TRUE”//cache ISUNIX()函数,以防止blueocean在下面的python函数中显示过多重复步骤(检查是否在类Unix节点上运行)
sh'python3-m venv Pyev'
PYTHON_PATH=sh(脚本:“echo${WORKSPACE}/pyenv/bin/”,returnStdout:true)
}
否则{
env.ISUNIX=“FALSE”
powershell(脚本:“py-3-m venv-pyenv”)//windows不允许使用venv调用python3.exe。https://github.com/msys2/MINGW-packages/issues/5001
PYTHON_PATH=sh(脚本:“echo${WORKSPACE}/pyenv/Scripts/”,returnStdout:true)
}
试一试{
//有时,具有较旧pip版本的代理可能会由于插件不兼容而导致错误。
Python(“-m pip安装--升级pip”)
} 
catch(ignore){}//update pip在已经是最新版本时始终返回false
//在此之后,您可以在管道的任何位置调用Python()
Python(“-m pip安装-r requirements.txt”)
}                
}
}
//使用VirtualEnv时,WithPyenv等几个插件在跨平台上无法完美工作。
//将此方法置于管道之外
def Python(字符串命令){
if(env.ISUNIX==“TRUE”){
sh脚本:“源pyenv/bin/activate&&python${command}”,标签:“python${command}”
}
否则{
powershell脚本:“pyenv\\Scripts\\Activate.ps1;python${command}”,标签:“python${command}”
}
}

bash: ./pip: /var/jenkins_home/workspace/ink_feature-use-jenkinsfile-VGRPYD53GGGDDSBIJDLSU: bad interpreter: No such file or directory

python -m pip install ...