Wie übergebe ich Variablen zwischen Stufen in einer deklarativen Jenkins-Pipeline?

79

Wie übergebe ich Variablen zwischen Stufen in einer deklarativen Pipeline?

In einer Skript-Pipeline besteht die Prozedur darin, in eine temporäre Datei zu schreiben und die Datei dann in eine Variable einzulesen.

Wie mache ich das in einer deklarativen Pipeline?

ZB möchte ich einen Build eines anderen Jobs auslösen, basierend auf einer Variablen, die durch eine Shell-Aktion erstellt wurde.

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
quelle
Für den Schreib- und Leseteil gibt es übrigens Shash / Unstash.
Sebkraemer
1
Was ist mit Umgebungsvariablen , die sich wie globale Variablen verhalten?
Veverke

Antworten:

94

Wenn Sie eine Datei verwenden möchten (da ein Skript den Wert generiert, den Sie benötigen), können Sie diese readFilewie unten gezeigt verwenden. Wenn nicht, verwenden Sie shdie folgende scriptOption:

// 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
quelle
1
Sie können es auch einfach verwenden def myVarund anschließend verwenden, echo ${myVar}wenn Sie Ihre Konfiguration oben in der Datei haben möchten;)
bastianwegge
4
Ist das Schreiben in eine Datei nicht sehr böse und erzeugt auch unerwünschtes Diskio?
Dirkos
4
Sie haben Recht, @Dirkos, aber es gibt einen besseren Weg, um das zu erreichen, was angefordert wurde, ohne das Lesen / Schreiben von Dateien. Siehe diese Antwort stackoverflow.com/a/43881731/1053510
user1053510
1
Ich reposte meinen Kommentar aus einer anderen Antwort, aber ich würde empfehlen, withEnvin der 2. Stufe einen Wrapper zu verwenden, damit Sie die Variable im Kontext von verwenden können sh. Andernfalls wird eine leere Zeichenfolge gedruckt. Zumindest mit Jenkins 2.124.
Sergio
1
@ConradB Es sollte gut funktionieren, die Technik hier zu verwenden, solange Sie die Variable vor der parallelen Stufe festlegen (im obigen Beispiel wird in Stufe "drei" die Arbeit ausgeführt, die Sie parallel ausführen müssen).
Burnettk
18

Einfach:

  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
quelle
Gemäß dem Dokument, auf das @KatieS verweist, wird auf die im Parameterblock {} definierten Parameter als $ {params.custom_var} und nicht als $ {env.custom_var} zugegriffen. Beide funktionieren, sind jedoch eine unterschiedliche Variable, die unterschiedliche Werte enthalten kann. Aber Ihre Lösung mit dem Parameter {} Block funktioniert gut für mich, wenn ich über $ {params.custom_var} auf sie zugreife
Martin
4
Ich lag falsch. Parameter {} werden für verwendete bereitgestellte Parameter verwendet und scheinen unveränderlich zu sein. Wenn Sie versuchen, sie in der Pipeline festzulegen (neben der Zuweisung eines Standardwerts in den Parametern {}), schlägt die Stufe ohne Fehlermeldung fehl. Die env.custom_var ist also der richtige Weg. In diesem Fall kann der Parameterblock {} weggelassen werden.
Martin
Funktioniert dies in mehreren Jenkins-Dateien? Ich versuche, das neueste Commit für das Repo von build.JenksinsFile an deploy.JenkinsFile weiterzuleiten.
Gurpreet Singh Drish
trotzdem etwas wie $ {workspace} in Parameter einfügen? like string (Name: 'custom_var', defaultValue: "$ {workspace} / a")
yuxh
2
Ich bin mir nicht sicher, wie das funktionieren wird. Ich glaube nicht, dass Sie eine Variable direkt im "Schritte" -Block festlegen können, ohne einen "Skript" -Schritt zu verwenden.
Arnab
5

Ich hatte ein ähnliches Problem, da ich wollte, dass eine bestimmte Pipeline Variablen bereitstellt und viele andere sie verwenden, um diese Variablen abzurufen.

Ich habe eine Pipeline mit my-set-env-Variablen erstellt

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}]"
}

Ich kann diese Variablen in einer anderen Pipeline my-set-env-variables-test wiederverwenden

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.
quelle