Jenkins Pipeline - How do I use the 'tool' option to specify a custom tool?

24,910

Solution 1

I ran into the same problem. I got to this workaround:

 environment {
    GROOVY_HOME = tool name: 'Groovy-2.4.9', type: 'hudson.plugins.groovy.GroovyInstallation'
}
stages {
    stage('Run Groovy') {
        steps {
            bat "${groovy_home}/bin/groovy <script.name>"
        }
    }
}

Somehow the tool path is not added to PATH by default (as was customary on my 1.6 Jenkins server install). Adding the ${groovy_home} when executing the bat command fixes that for me. This way of calling a tool is basically lent from the scripted pipeline syntax. I am using this for all my custom tools (not only groovy).

The tool part:

tool name: 'Groovy-2.4.9', type: 'hudson.plugins.groovy.GroovyInstallation'

was generated by the snippet generator like you did.

According to the Jenkins users mailing list, work is still ongoing for a definitive solution, so my solution really is a work around.

Solution 2

This is my first time commenting on stack overflow, but I've been looking for this answer for a few days and I think I have a potential solution. Checking out Fholst answer, I'd like to expand on it. That environment stanza I think may work for declarative syntax, but on a scripted pipeline you must use the withEnv() equivalent, and pass in the tools via a gString: i.e. ${tool 'nameOfToolDefinedInGlobalTools'}. For my particular use case, for reasons beyond my control, we do not have maven installed on our jenkins host machine, but there is one defined within the global tools configuration. This means I need to add mvn to the path before executing my sh commands within my steps. What I have been able to do is this:

        withEnv(["PATH+MVN=${tool 'NameOfMavenTool'}/bin"]){
            sh '''
                echo "PATH = ${PATH}"
            '''
        }

This should give you what you need. Please ignore the triple single quotes on the sh line, I actually have several environment variables loaded and simply removed them from my snippet.

Hope this helps anyone who has been searching for this solution for days. I feel your pain. Cobbled this together from looking through the console output of a declarative pipeline script (if you use tools{} stanza it will show you how it builds those environment variables and wraps your subsequent declarative steps) and the following link: https://go.cloudbees.com/docs/cloudbees-documentation/use/automating-projects/jenkinsfile/

Share:
24,910

Related videos on Youtube

jupiter22
Author by

jupiter22

Squad Lead

Updated on July 23, 2022

Comments

  • jupiter22
    jupiter22 almost 2 years

    I have a custom tool defined within Jenkins via the Custom Tools plugin. If I create a freestyle project the Install custom tools option correctly finds and uses the tool (Salesforce DX) during execution.

    However, I cannot find a way to do the same via a pipeline file. I have used the pipeline syntax snippet generator to get:

    tool name: 'sfdx', type: 'com.cloudbees.jenkins.plugins.customtools.CustomTool'
    

    I have put that into my stage definition:

    stage('FetchMetadata') {
        print 'Collect Prod metadata via SFDX'
        tool name: 'sfdx', type: 'com.cloudbees.jenkins.plugins.customtools.CustomTool'
        sh('sfdx force:mdapi:retrieve -r metadata/ -u DevHub -k ./metadata/package.xml')
    }
    

    but I get an error message stating line 2: sfdx: command not found

    Is there some other way I should be using this snippet?

    Full Jenkinsfile for info:

    node {
        currentBuild.result = 'SUCCESS'`
    
            try {
                stage('CheckoutRepo') {
                    print 'Get the latest code from the MASTER branch'
                    checkout scm
                }
    
                stage('FetchMetadata') {
                    print 'Collect Prod metadata via SFDX'
                    tool name: 'sfdx', type: 'com.cloudbees.jenkins.plugins.customtools.CustomTool'
                    sh('sfdx force:mdapi:retrieve -r metadata/ -u DevHub -k ./metadata/package.xml')
                }
    
                stage('ConvertMetadata') {
                    print 'Unzip retrieved metadata file'
                    sh('unzip unpackaged.zip .')
                    print 'Convert metadata to SFDX format'
                    sh('/usr/local/bin/sfdx force:mdapi:convert -r metadata/unpackaged/ -d force-app/')
                }
    
                stage('CommitChanges') {
                    sh('git add --all')
                    print 'Check if any changes need committing'
                    sh('if ! git diff-index --quiet HEAD --; then echo "changes found - pushing to repo"; git commit -m "Autocommit from Prod @ $(date +%H:%M:%S\' \'%d/%m/%Y)"; else echo "no changes found"; fi')
                    sshagent(['xxx-xxx-xxx-xxx']) {
                        sh('git push -u origin master')
                    }
                }
            }
            catch (err) {
                currentBuild.result = 'FAILURE'
                print 'Build failed'
                error(err)
            }
    }
    

    UPDATE I have made some progress using this example Jenkinsfile My stage now looks like this:

            stage('FetchMetadata') {
                print 'Collect Prod metadata via SFDX'
                def sfdxLoc =  tool 'sfdx'
                sh script: "cd topLevel; ${sfdxLoc}/sfdx force:mdapi:retrieve -r metadata/ -u DevHub -k ./metadata/package.xml"
            }
    

    Unfortunately, although it looks like Jenkins is now finding and running the sfdx tool, I get a new error:

    TypeError: Cannot read property 'run' of undefined
        at Object.<anonymous> (/var/lib/jenkins/.cache/sfdx/tmp/heroku-script-509584048:20:4)
        at Module._compile (module.js:570:32)
        at Object.Module._extensions..js (module.js:579:10)
        at Module.load (module.js:487:32)
        at tryModuleLoad (module.js:446:12)
        at Function.Module._load (module.js:438:3)
        at Module.runMain (module.js:604:10)
        at run (bootstrap_node.js:394:7)
        at startup (bootstrap_node.js:149:9)
        at bootstrap_node.js:509:3
    
  • Tadeusz Kleszcz
    Tadeusz Kleszcz over 4 years
    It can be improved by adding groovy to path in environemnt block: PATH = "${env.GROOVY_HOME}/bin:${env.PATH}" Then you will be able to call groovy from path.

Related