如何在Jenkins中创建Python virtualenv?

时间:2015-04-10 20:25:03

标签: 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

但由于某种原因,它坚持使用系统安装的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

看起来詹金斯并没有从头开始为每个版本重建环境,这让我感到奇怪,但不应该影响我的直接问题

" 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

"输出" 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

6 个答案:

答案 0 :(得分:12)

在过去的两年里,我每天都在和Jenkins一起使用python virtualenvs,在多家公司和小型项目中,我不能说我找到了“答案”。不过,我希望分享我的经验可以帮助其他人节省时间。希望我会得到进一步的反馈,以便更容易做出决定。

  • 避免ShiningPanda - 维护得不好,与Jenkins2管道不兼容,并且无法并行执行作业。它也有将孤儿环境留在磁盘上的坏习惯。
  • 通过bash和virtualenv的DIY 是我目前的最爱。在$ WORKSPACE中创建它,如果不是总是清理,则在激活它们之前运行relocatable。这是因为jenkins工作区文件夹磁盘位置可以在作业N和N + 1的执行之间发生变化。

如果您使用多个需要相同virtualenv的构建器,最简单的方法是将您的环境转储到文件并在新构建器的开头处将其源代码。

为了便于维护,我打算调查这些:

  • direnvm
  • virtualenv-wrapper(mkvirtualenv)
  • pyenv

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

答案 1 :(得分:7)

Jenkins管道可以在虚拟环境中运行,但有很多事情需要考虑。

  • Jenkins使用的默认shell是/bin/sh - 这可以在管理Jenkins - >中配置。配置系统 - >壳牌 - > Shell可执行文件。将其设置为/bin/bash将使source正常工作。
  • 激活的venv只是改变环境变量,环境变量不会在jenkins的各个阶段之间持续存在。请参阅withEnv
  • 如果您使用版本控制的多分支管道,jenkins会在路径中创建一个带有分支名称和提交哈希的工作区 - 这可能会很长。 venv脚本(例如pip)都以hashbang行开头,其中包括venv中python解释器的完整路径(python解释器本身是一个符号链接)。如,

    ~/workspace/ink_feature-use-jenkinsfile-VGRPYD53GGGDDSBIJDLSUDYPJ34QR63ITGMC5VJNB56W6ID244AA/env/bin$ cat pip
    #!/var/jenkins_home/workspace/ink_feature-use-jenkinsfile-VGRPYD53GGGDDSBIJDLSUDYPJ34QR63ITGMC5VJNB56W6ID244AA/env/bin/python3.5
    

    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

答案 2 :(得分:1)

我遇到了同样的问题。正如我所看到的 - 你的项目名为'Run Tests'。所以,这个名字包含空格。这对我来说是个问题。我刚刚重命名了项目,比如RunTests - 而且venv现在正在工作!注意 - 詹金斯会问你关于确认重命名项目的问题。

答案 3 :(得分:1)

我建议避开ShiningPanda。

我使用Anaconda / Miniconda设置了我的虚拟环境。安装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,我向/etc/profile添加了conda路径:

export PATH="/var/lib/jenkins/miniconda3/bin:$PATH"

然后在Jenkinsfile中,您可以创建和删除 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'
        }
    }
}

答案 4 :(得分:0)

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

这是我手动调用python方法的方式。不是最佳做法,但可以。

// Put this stage on top of pipeline
stage('Prepare venv') {
    steps {
        script {
            if (isUnix()) {
                env.ISUNIX = "TRUE" // cache isUnix() function to prevent blueocean show too many duplicate step (Checks if running on a Unix-like node) in python function below
                sh 'python3 -m venv pyenv'
                PYTHON_PATH =  sh(script: 'echo ${WORKSPACE}/pyenv/bin/', returnStdout: true).trim()                        
            }
            else {
                env.ISUNIX = "FALSE"
                powershell(script:"py -3 -m venv pyenv") // windows not allow call python3.exe with venv. https://github.com/msys2/MINGW-packages/issues/5001
                PYTHON_PATH =  sh(script: 'echo ${WORKSPACE}/pyenv/Scripts/', returnStdout: true).trim()
            }

            try  {
                // Sometime agent with older pip version can cause error due to non compatible plugin.
                Python("-m pip install --upgrade pip")
            } 
            catch (ignore) { } // update pip always return false when already lastest version
            // After this you can call Python() anywhere from pipeline
            Python("-m pip install -r requirements.txt")
        }                
    }
}

// Several plugins like WithPyenv is not working perfectly accross platform when using Virtual Env.
// Put this method outside pipeline
def Python(String command) {
    if (env.ISUNIX == "TRUE") {
        sh script:"source pyenv/bin/activate && python ${command}", label: "python ${command}"
    }
    else {
        powershell script:"pyenv\\Scripts\\Activate.ps1 ; python ${command}", label: "python ${command}"
    }
}

答案 5 :(得分:0)

了解了virtualenv之后,尝试将pip作为模块运行:

python -m pip install ...

python -m pippip

  • python -m pip:执行python解释程序二进制文件,该文件从站点软件包目录中读取模块pip.py
  • pip:执行从pip拾取的$PATH二进制/脚本

我发现使用python -m pip解决了遇到的大多数点子权限问题。