web-dev-qa-db-ja.com

Jenkinsfileおよび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内ではなくグローバルenvでpipを更新しようとしているように見え、各shステップが独自のコンテキスト上にあるように見えますが、同じコンテキスト内で実行するにはどうすればよいですか?

23
James Lin

あなたがしようとしていることは機能しません。 shコマンドを呼び出すたびに、jenkinsは新しいシェルを作成します。

これは、.env/bin/activate内のshは、そのシェルセッションのソースのみになります。その結果、新しいshコマンドでファイルを再度ソースする必要があります(コンソール出力を詳しく見ると、Jenkinsがコマンドを実行するたびに一時的なシェルファイルを実際に作成することがわかります。

したがって、.env/bin/activate各シェルコマンドの先頭にあるファイル(複数行の文字列にトリプルqoutesを使用できます)

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
    """
}

またはすべてを1つのシェルで実行します

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
"""
16
Rik

Rikが投稿したように、virtualenvはJenkins Pipeline Environment内ではうまく機能しません。これは、コマンドごとに新しいシェルが作成されるためです。

このプロセスの苦痛を少し軽減するプラグインを作成しました。このプラグインは https://wiki.jenkins.io/display/JENKINS/Pyenv+Pipeline+Plugin にあります。基本的には、コマンドを実行する前にvirtualenvをアクティブにする方法で各呼び出しをラップします。複数のコマンドをインラインで実行するいくつかの方法がJenkinsによって2つの別個のコマンドに分割され、アクティブ化されたvirtualenvが適用されなくなるため、これ自体は注意が必要です。

6
cstarner