web-dev-qa-db-fra.com

Passer des variables entre les étapes Jenkins

Je veux passer une variable que j'ai lue au stade A vers le stade B d'une manière ou d'une autre. Je vois dans certains exemples que les gens l'écrivent dans un fichier, mais je suppose que ce n'est pas vraiment une bonne solution. J'ai essayé de l'écrire dans une variable d'environnement, mais je n'y parviens pas vraiment. Comment puis-je le configurer correctement?

Pour le faire fonctionner, j'ai essayé beaucoup de choses et j'ai lu que je devrais utiliser le "" "au lieu de '' 'pour démarrer un shell et échapper ces variables vers \${foo} par exemple.

Voici ce que j'ai comme 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}'
            }
        }
    }
}

Comme vous pouvez le voir, le packageVersion que j'ai lu depuis l'étape Package doit également être utilisé dans l'étape Publish.

Les conseils généraux contre le pipeline sont bien sûr toujours les bienvenus.

8
Dirkos

Un problème dans votre code est que vous affectez la version de la variable d'environnement dans l'étape sh. Cette étape s'exécutera dans son propre processus isolé, héritant des variables d'environnement du processus parent.

Cependant, la seule façon de renvoyer des données au parent est via STDOUT/STDERR ou code de sortie. Comme vous voulez une valeur de chaîne, il est préférable de faire écho à la version de l'étape sh et de l'affecter à une variable dans le contexte script.

Si vous réutilisez le nœud, le contexte du script persistera et des variables seront disponibles à l'étape suivante. Un exemple de travail est ci-dessous. Notez que toute tentative de placer cela dans un bloc parallel peut échouer, car la variable d'informations de version peut être écrite par plusieurs processus.

#!/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}"
                }
            }
        }
    }
}
16
toske

Une autre option qui n'implique pas l'utilisation de script, mais qui est simplement déclarative, consiste à cacher des choses dans un petit fichier d'environnement temporaire.

Vous pouvez ensuite utiliser cette cachette (comme un cache temporaire qui ne vit que pour l'exécution) si la charge de travail est répartie sur des nœuds parallèles ou distribués, selon les besoins.

Quelque chose comme:

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'

            }
        }
    }
}
4
Michael Neale