title: How do I properly set up my Python dependencies within Jenkins using pip and virtualenv?
body: <p>I am a rookie to Jenkins trying to set up a Python <strong>pytest</strong> test suite to run. In order to properly execute the test suite, I have to install several Python packages. I'm having trouble with this particular step because Jenkins consistently is unable to find <code>virtualenv</code> and <code>pip</code>:</p>
  
  <pre><code>pipeline {
      parameters {
        gitParameter branchFilter: 'origin/(.*)', defaultValue: 'master', name: 'BRANCH', type: 'PT_BRANCH', quickFilterEnabled: true
      }
  
      agent any
  
      stages {
          stage('Checkout source code') {
              steps {
  
                  checkout([$class: 'GitSCM', branches: [[name: '*/master']], doGenerateSubmoduleConfigurations: false, extensions: [], submoduleCfg: [], userRemoteConfigs: [[credentialsId: '------', url: 'git@github.com:path-to-my-repo/my-test-repo.git']]])
              }
          }
  
          stage('Start Test Suite') {
              steps {
                      sh script: 'PATH=/Library/Frameworks/Python.framework/Versions/3.6/bin/:$PATH'
                      echo "Checking out Test suite repo."
  
                      sh script: 'virtualenv venv --distribute'
                      sh label: 'install deps', script: '/Library/Frameworks/Python.framework/Versions/3.6/bin/pip install -r requirements.txt'
                      sh label: 'execute test suite, exit upon first failure', script: 'pytest --verbose -x --junit-xml reports/results.xml'
  
                  post {
                      always {
                          junit allowEmptyResults: true, testResults: 'reports/results.xml'
                      }
                  }
              }
          }
  </code></pre>
  
  <p>On the <code>virtualenv venv --distribute</code> step, Jenkins throws an error (I'm running this initially on a Jenkins server on my local instance, although in production it will be on an Amazon Linux 2 machine):</p>
  
  <blockquote>
    <ul>
    <li>virtualenv venv --distribute /Users/Shared/Jenkins/Home/workspace/my-project-name@tmp/durable-5045c283/script.sh:
    line 1: virtualenv: command not found</li>
    </ul>
  </blockquote>
  
  <p>Why is this happening? The step before, I make sure to append where I know my <code>virtualenv</code> and <code>pip</code> are:</p>
  
  <pre><code> sh script: 'PATH=/Library/Frameworks/Python.framework/Versions/3.6/bin/:$PATH'
  </code></pre>
  
  <p>For instance, when I type in</p>
  
  <pre><code>sudo su jenkins
  which pip
  which virtualenv
  </code></pre>
  
  <p>I get the following outputs as expected:</p>
  
  <blockquote>
    <p>/Library/Frameworks/Python.framework/Versions/3.6/bin/pip
    /Library/Frameworks/Python.framework/Versions/3.6/bin/virtualenv</p>
  </blockquote>
  
  <p>Here are the things I do know:</p>
  
  <ul>
  <li>Jenkins runs as a user called <code>jenkins</code></li>
  <li>best practice is to create a virtual environment, activate it, and the perform my pip installations inside there</li>
  <li>Jenkins runs <code>sh</code> by default, not <code>bash</code> (but I'm not sure if this has anything to do with my problem)</li>
  </ul>
  
  <p>Why is Jenkins unable to find my <code>virtualenv</code>? What's the best practice for installing Python libraries for a Jenkins build?</p>
  
  <p><strong>Edit:</strong> I played around some more and found a working solution:</p>
  
  <p>I don't know if this is the proper way to do it, but I used the following syntax:</p>
  
  <pre><code>withEnv(['PATH+EXTRA=/Library/Frameworks/Python.framework/Versions/3.6/bin/']) {
                              sh script: "pip install virtualenv"
                   // do other setup stuff
      }
  </code></pre>
  
  <p>However, I'm now stuck w/ a new issue: I've clearly hardcoded in my Python path here. If I'm running on a remote Linux machine, am I going to have to install that specific version of Python (3.6)?</p>