Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pass variables between Jenkins stages

I want to pass a variable which I read in stage A towards stage B somehow. I see in some examples that people write it to a file, but I guess that is not really a nice solution. I tried writing it to an environment variable, but I'm not really successful on that. How can I set it up properly?

To get it working I tried a lot of things and read that I should use the """ instead of ''' to start a shell and escape those variables to \${foo} for example.

Below is what I have as a pipeline:

#!/usr/bin/env groovy

pipeline {

    agent { node { label 'php71' } }

    environment {
        packageName='my-package'
        packageVersion=''
        groupId='vznl'
        nexus_endpoint='http://nexus.devtools.io'
        nexus_username='jenkins'
        nexus_password='J3nkins'
    }

    stages{

        // Package dependencies
        stage('Install dependencies') {
            steps {
                sh '''
                    echo Skip composer installation
                    #composer install  --prefer-dist --optimize-autoloader --no-interaction
                '''
            }
        }

        // Unit tests
        stage('Unit Tests') {
            steps {
                sh '''
                    echo Running PHP code coverage tests...
                    #composer test
                '''
            }
        }

        // Create artifact
        stage('Package') {
            steps {
                echo 'Create package refs'
                sh """
                    mkdir -p ./build/zpk
                    VERSIONTAG=\$(grep 'version' composer.json)
                    REGEX='"version": "([0-9]+.[0-9]+.[0-9]+)"'
                    if [[ \${VERSIONTAG} =~ \${REGEX} ]]
                    then
                        env.packageVersion=\${BASH_REMATCH[1]}
                        /usr/bin/zs-client packZpk --folder=. --destination=./build/zpk --name=${env.packageName}-${env.packageVersion}.zpk --version=${env.packageVersion}
                    else
                        echo "No version found!"
                        exit 1
                    fi
                """
            }
        }

        // Publish ZPK package to Nexus
        stage('Publish packages') {
            steps {
                echo "Publish ZPK Package"
                sh "curl -u ${env.nexus_username}:${env.nexus_password} --upload-file ./build/zpk/${env.packageName}-${env.packageVersion}.zpk ${env.nexus_endpoint}/repository/zpk-packages/${groupId}/${env.packageName}-${env.packageVersion}.zpk"
                archive includes: './build/**/*.{zpk,rpm,deb}'
            }
        }
    }
}

As you can see the packageVersion which I read from stage Package needs to be used in stage Publish as well.

Overall tips against the pipeline are of course always welcome as well.

like image 702
Dirkos Avatar asked Nov 23 '17 19:11

Dirkos


People also ask

How do I set environment variable in Jenkins pipeline stage?

Setting Stage Level Environment Variable It is by using the env variable directly in the script block. We can define, let us say, USER_GROUP and display it. You will see that the underlying shell also has access to this environment variable. You can also set an environment variable using withEnv block.

How do you pass parameters in Jenkins pipeline?

Any Jenkins job or pipeline can be parameterized. All we need to do is check the box on the General settings tab, “This project is parameterized”: Then we click the Add Parameter button.


2 Answers

A problem in your code is that you are assigning version of environment variable within the sh step. This step will execute in its own isolated process, inheriting parent process environment variables.

However, the only way of passing data back to the parent is through STDOUT/STDERR or exit code. As you want a string value, it is best to echo version from the sh step and assign it to a variable within the script context.

If you reuse the node, the script context will persist, and variables will be available in the subsequent stage. A working example is below. Note that any try to put this within a parallel block can be of failure, as the version information variable can be written to by multiple processes.

#!/usr/bin/env groovy

pipeline {

    environment {
        AGENT_INFO = ''
    }

    agent {
        docker {
            image 'alpine'
            reuseNode true
        }
    }

    stages {

        stage('Collect agent info'){
            steps {
                echo "Current agent  info: ${env.AGENT_INFO}"
                script {
                    def agentInfo = sh script:'uname -a', returnStdout: true
                    println "Agent info within script: ${agentInfo}"
                    AGENT_INFO = agentInfo.replace("/n", "")
                    env.AGENT_INFO = AGENT_INFO
                }
            }
        }

        stage("Print agent info"){
            steps {
                script {
                    echo "Collected agent info: ${AGENT_INFO}"
                    echo "Environment agent info: ${env.AGENT_INFO}"
                }
            }
        }
    }
}
like image 51
toske Avatar answered Oct 23 '22 00:10

toske


Another option which doesn't involve using script, but is just declarative, is to stash things in a little temporary environment file.

You can then use this stash (like a temporary cache that only lives for the run) if the workload is sprayed out across parallel or distributed nodes as needed.

Something like:

pipeline {
    agent any

    stages {
        stage('first stage') {
            steps {
                // Write out any environment variables you like to a temporary file
                sh 'echo export FOO=baz > myenv'

                // Stash away for later use
                stash 'myenv'
            }
        }

        stage ("later stage") {
            steps {

                // Unstash the temporary file and apply it
                unstash 'myenv'

                // use the unstashed vars
                sh 'source myenv && echo $FOO'

            }
        }
    }
}
like image 21
Michael Neale Avatar answered Oct 23 '22 00:10

Michael Neale