Jenkins pipeline : select nodejs version (+ python version)

I’m facing an issue with a Jenkins pipeline in a Jenkinsfile.
I have 4 different nodeJs versions on my Jenkins instance. I would like to choose which one I’m going to use in my pipeline, but official plugin examples (https://wiki.jenkins-ci.org/display/JENKINS/NodeJS+Plugin) simply don’t work.

I tried this first approach, failing because $PATH is overwritten by the tools section.

pipeline {
   agent any

   tools {
       // I hoped it would work with this command...
       nodejs 'nodejs6'
   }

   stages {
       stage('Example') {
           steps {
               sh 'npm --version'
               // Failed saying :
               // Running shell script
               //nohup: failed to run command 'sh': No such file or directory
           }
       }
   }
}

I tried this second approach, failing because the tool command seems to do nothing at all.

pipeline {
   agent any

   stages {
       stage('Example') {
           steps {
               // ... or this one
               tool name: 'nodejs6'

               sh 'node --version'
               sh 'npm --version'
               // Does not use this version of node, but the default one... 7.5.0 with npm 4.3.0
           }
       }
   }
}

Finally, I tried this one, which works for NodeJS but… does not seem to be “very smart”, and does not allow me to handle properly my specific version of “Python” –Yes I also have 2 different versions of Python that I would like to handle the same way I do for node–

pipeline {
   agent any

   stages{
       stage ('Which NodeJS'){
           steps{
               withEnv(["PATH+NODEJS=${tool 'nodejs6'}/bin","PATH+PYTHON27=${tool 'python27'}"]) {
                   // Check node version
                   sh 'which node' // Works properly
                   sh 'node -v' // Expected 6.9.x version
                   sh 'npm -v' // Expected 3.x version
                   sh 'python27 -v'
                   // Failed with 
                   // /[email protected]/xx/script.sh: python27: not found
               }
           }
       }
   }
}

I also have a 4th solution, not using pipeline syntax. It works for nodejs, but not for python (so far). And once again, it does not seems very elegant to manually define env.PATH

node {
    // Setup tools...
    stage ('Setup NodeJs'){
        def nodejsHome = tool 'nodejs6'
        env.NODE_HOME = "${nodejsHome}"
        env.PATH = "${nodejsHome}/bin:${env.PATH}"
        sh 'which node'
        sh 'node -v'
        sh 'npm -v'
    }

    stage ('Setup Python 2.7'){
        def pythonBin = tool 'python27'
        // Jenkins docker image has Jenkins user's home in "/var/jenkins_home"
        sh "rm -Rf /var/jenkins_home/tools/python ; mkdir -p /var/jenkins_home/tools/python"
        // Link python to python 2.7
        sh "ln -s ${pythonBin} /var/jenkins_home/tools/python/python"
        // Include link in path --don't use "~" in path, it won't be resolved
        env.PATH = "~/tools/python:${env.PATH}:~/tools/python"
        // Displays correctly Python 2.7
        sh "python --version"
    }
}

All in all, I’m just wondering which solution (certainly another one that I have not listed here) is the best? Which one do you advice and why?

Cheers,
Olivier

Here is Solutions:

We have many solutions to this problem, But we recommend you to use the first solution because it is tested & true solution that will 100% work for you.

Solution 1

So. This is a problem from “EnvInject” plugin: https://issues.jenkins-ci.org/browse/JENKINS-26583

My workaround #4 above is the correct solution if you want to keep EnvInject.

env.NODE_HOME="${tool 'Node 6.x'}"
env.PATH="${env.NODE_HOME}/bin:${env.PATH}"
sh 'npm -version'

Otherwise, removing EnvInject plugin is also a good solution when possible.

Solution 2

pipeline {
     agent {
                label 'slave-machine'
    }
    environment {
        NODE_HOME = tool name: 'Node 10.13.0', type: 'jenkins.plugins.nodejs.tools.NodeJSInstallation'
    }
    stages { 
        stage('test') {]
            steps {
               script {
                   env.PATH="${env.NODE_HOME}/bin:${env.PATH}"
                   sh 'node -v'
                   sh 'echo $NODE_HOME'
               }
            }
        }
    }
}

Solution 3

how about using docker image with the specific version of node and/or python in your Jenkins pipeline? this would be a clean solution since you will only need to install docker on the build machine and not side-by-side versions of python.

https://jenkins.io/doc/book/pipeline/docker/

Note: Use and implement solution 1 because this method fully tested our system.
Thank you 🙂

All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply