¿Cómo paso variables entre etapas en una canalización declarativa de Jenkins?

83

¿Cómo paso variables entre etapas en una canalización declarativa?

En una canalización con script, deduzco que el procedimiento es escribir en un archivo temporal y luego leer el archivo en una variable.

¿Cómo hago esto en una canalización declarativa?

Por ejemplo, quiero activar la construcción de un trabajo diferente, basado en una variable creada por una acción de shell.

stage("stage 1") {
    steps {
        sh "do_something > var.txt"
        // I want to get var.txt into VAR
    }
}
stage("stage 2") {
    steps {
        build job: "job2", parameters[string(name: "var", value: "${VAR})]
    }
}
John
fuente
Para la parte de escritura y lectura, hay shash / unstash por cierto.
sebkraemer
1
¿Qué pasa con el uso de variables de entorno , que actúan como variables globales?
Veverke

Respuestas:

99

Si desea usar un archivo (ya que un script es lo que genera el valor que necesita), puede usarlo readFilecomo se muestra a continuación. Si no es así, utilícelo shcon la scriptopción que se muestra a continuación:

// Define a groovy global variable, myVar.
// A local, def myVar = 'initial_value', didn't work for me.
// Your mileage may vary.
// Defining the variable here maybe adds a bit of clarity,
// showing that it is intended to be used across multiple stages.
myVar = 'initial_value'

pipeline {
  agent { label 'docker' }
  stages {
    stage('one') {
      steps {
        echo "${myVar}" // prints 'initial_value'
        sh 'echo hotness > myfile.txt'
        script {
          // OPTION 1: set variable by reading from file.
          // FYI, trim removes leading and trailing whitespace from the string
          myVar = readFile('myfile.txt').trim()

          // OPTION 2: set variable by grabbing output from script
          myVar = sh(script: 'echo hotness', returnStdout: true).trim()
        }
        echo "${myVar}" // prints 'hotness'
      }
    }
    stage('two') {
      steps {
        echo "${myVar}" // prints 'hotness'
      }
    }
    // this stage is skipped due to the when expression, so nothing is printed
    stage('three') {
      when {
        expression { myVar != 'hotness' }
      }
      steps {
        echo "three: ${myVar}"
      }
    }
  }
}
Burnettk
fuente
1
también puede usarlo def myVary usarlo después con echo ${myVar}si desea tener su configuración en la parte superior del archivo;)
bastianwegge
4
¿No es muy malo escribir en un archivo y crear también un diskio no deseado?
Dirkos
4
Tienes razón @Dirkos, pero hay una mejor manera de lograr lo que se solicitó sin involucrar la lectura / escritura de archivos. Vea esta respuesta stackoverflow.com/a/43881731/1053510
user1053510
1
Estoy volviendo a publicar mi comentario de otra respuesta, pero recomendaría usar un withEnvcontenedor en la segunda etapa, para que pueda usar la variable en el contexto de sh. De lo contrario, imprimirá una cadena vacía. Al menos lo hace con Jenkins 2.124.
Sergio
1
@ConradB debería funcionar bien usar la técnica aquí siempre que establezca la variable antes de la etapa paralela (en el ejemplo anterior, la etapa "tres" es donde haría el trabajo que necesita hacer en paralelo).
burnettk
17

Simplemente:

  pipeline {
        parameters {
            string(name: 'custom_var', defaultValue: '')
        }

        stage("make param global") {
             steps {
               tmp_param =  sh (script: 'most amazing shell command', returnStdout: true).trim()
               env.custom_var = tmp_param
              }
        }
        stage("test if param was saved") {
            steps {
              echo "${env.custom_var}"
            }
        }
  }
Zigzauer
fuente
Según el documento señalado por @KatieS, a los parámetros definidos en el bloque de parámetros {} se accede como $ {params.custom_var} y no $ {env.custom_var}. Ambos funcionan pero son una variable diferente que puede contener valores diferentes. Pero su solución con el parámetro {} bloc funciona bien para mí accediendo a ellos a través de $ {params.custom_var}
Martin
4
Estaba equivocado. Los parámetros {} se utilizan para los parámetros proporcionados utilizados y parecen ser inmutables, intentar establecerlos en la canalización (además de asignarles un valor predeterminado en los parámetros {}) hará que la etapa falle sin ningún mensaje de error. Entonces env.custom_var es el camino a seguir. En este caso, el bloque de parámetros {} se puede dejar fuera.
Martin
¿Funciona esto en varios archivos de Jenkins? Lo que estoy tratando de hacer es pasar la última confirmación en el repositorio de build.JenksinsFile a deploy.JenkinsFile?
Gurpreet Singh Drish
de todos modos para insertar algo como $ {espacio de trabajo} en los parámetros? como string (nombre: 'custom_var', defaultValue: "$ {workspace} / a")
yuxh
2
No estoy seguro de cómo funcionará esto. No creo que puedas establecer directamente una variable dentro del bloque "pasos" sin usar un paso de "guión".
Arnab
6

Tuve un problema similar ya que quería que una canalización específica proporcionara variables y muchas otras que la usaran para obtener estas variables.

Creé una canalización my-set-env-variables

script
{
    env.my_dev_version = "0.0.4-SNAPSHOT"
    env.my_qa_version  = "0.0.4-SNAPSHOT"
    env.my_pp_version  = "0.0.2"
    env.my_prd_version = "0.0.2"
    echo " My versions  [DEV:${env.my_dev_version}] [QA:${env.my_qa_version}] [PP:${env.my_pp_version}] [PRD:${env.my_prd_version}]"
}

Puedo reutilizar estas variables en otra canalización my-set-env-variables-test

script 
{
    env.dev_version = "NOT DEFINED DEV"
    env.qa_version  = "NOT DEFINED QA"
    env.pp_version  = "NOT DEFINED PP"
    env.prd_version = "NOT DEFINED PRD"
}

stage('inject variables') {

    echo "PRE DEV version = ${env.dev_version}"
    script 
    {
       def variables = build job: 'my-set-env-variables'
       def vars = variables.getBuildVariables()
      //println "found variables" + vars
      env.dev_version = vars.my_dev_version
      env.qa_version  = vars.my_qa_version
      env.pp_version  = vars.my_pp_version
      env.prd_version = vars.my_prd_version
    }
}

stage('next job') {
    echo "NEXT JOB DEV version = ${env.dev_version}"
    echo "NEXT JOB QA version = ${env.qa_version}"
    echo "NEXT JOB PP version = ${env.pp_version}"
    echo "NEXT JOB PRD version = ${env.prd_version}"

}


Emmanuel B.
fuente