Jenkins: Variable kann in der Pipeline-Phase nicht definiert werden

106

Ich versuche, ein deklaratives Jenkins-Pipeline-Skript zu erstellen, habe jedoch Probleme mit der einfachen Variablendeklaration.

Hier ist mein Skript:

pipeline {
   agent none
   stages {
       stage("first") {
           def foo = "foo" // fails with "WorkflowScript: 5: Expected a step @ line 5, column 13."
           sh "echo ${foo}"
       }
   }
}

Ich erhalte jedoch diesen Fehler:

org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
WorkflowScript: 5: Expected a step @ line 5, column 13.
           def foo = "foo"
           ^

Ich bin auf Jenkins 2.7.4 und Pipeline 2.4.

Malcolm Crum
quelle

Antworten:

101

Das deklarative Modell für Jenkins-Pipelines verfügt über eine eingeschränkte Teilmenge der Syntax, die in den stageBlöcken zulässig ist . Weitere Informationen finden Sie im Syntaxhandbuch . Sie können diese Einschränkung umgehen, indem Sie Ihre Schritte in einen script { ... }Block einschließen. Infolgedessen verlieren Sie jedoch die Validierung von Syntax, Parametern usw. innerhalb des scriptBlocks.

Abayer
quelle
5
Was ist, wenn ich diese Variable außerhalb des Skriptblocks verwenden möchte?
Jan Steinke
3
Für die Verwendung von Variablen außerhalb des Skriptblocks
Senthil A Kumar
56

Ich denke, der Fehler kommt nicht von der angegebenen Zeile, sondern von den ersten drei Zeilen. Versuchen Sie stattdessen Folgendes:

node {
   stage("first") {
     def foo = "foo"
     sh "echo ${foo}"
   }
}

Ich denke, Sie hatten einige zusätzliche Zeilen, die nicht gültig sind ...

BEARBEITEN

Aus der Dokumentation desenvironment deklarativen Pipeline-Modells geht hervor, dass Sie einen Deklarationsblock verwenden müssen, um Ihre Variablen zu deklarieren, z.

pipeline {
   environment {
     FOO = "foo"
   }

   agent none
   stages {
       stage("first") {
           sh "echo ${FOO}"
       }
   }
}
Pom12
quelle
1
Sie können einer Phase auch einen Umgebungsblock hinzufügen (z. B. wenn Ihre Variable von etwas abhängt, das in einem früheren Schritt ausgeführt wurde).
Tereza Tomcova
34

Stimmen Sie mit @ Pom12, @abayer überein. Um die Antwort zu vervollständigen, müssen Sie einen Skriptblock hinzufügen

Versuchen Sie so etwas:

pipeline {
    agent any
    environment {
        ENV_NAME = "${env.BRANCH_NAME}"
    }

    // ----------------

    stages {
        stage('Build Container') {
            steps {
                echo 'Building Container..'

                script {
                    if (ENVIRONMENT_NAME == 'development') {
                        ENV_NAME = 'Development'
                    } else if (ENVIRONMENT_NAME == 'release') {
                        ENV_NAME = 'Production'
                    }
                }
                echo 'Building Branch: ' + env.BRANCH_NAME
                echo 'Build Number: ' + env.BUILD_NUMBER
                echo 'Building Environment: ' + ENV_NAME

                echo "Running your service with environemnt ${ENV_NAME} now"
            }
        }
    }
}
Si Zi
quelle
4
Beachten Sie, dass in diesem Beispiel davon ausgegangen wird, dass bereits eine definierte Umgebungsvariable "ENVIRONMENT_NAME" vorhanden ist, auf die Jenkins zugreifen kann.
Alberto
1
Kann der Skriptblock die Umgebungswerte ändern?
Pitchblack408
Ja, Sie können den Umgebungswert innerhalb des Skriptblocks ändern.
NicoPaez
8

In Jenkins 2.138.3 gibt es zwei verschiedene Arten von Pipelines.

Deklarative und geskriptete Pipelines.

"Deklarative Pipelines sind eine neue Erweiterung des Pipeline-DSL (es handelt sich im Grunde genommen um ein Pipeline-Skript mit nur einem Schritt, einem Pipeline-Schritt mit Argumenten (als Direktiven bezeichnet). Diese Direktiven sollten einer bestimmten Syntax folgen. Der Sinn dieses neuen Formats ist, dass es ist strenger und sollte daher für Pipelines-Neulinge einfacher sein, grafische Bearbeitung ermöglichen und vieles mehr. Skript-Pipelines sind der Fallback für erweiterte Anforderungen. "

Jenkins Pipeline: Agent gegen Knoten?

Hier ist ein Beispiel für die Verwendung von Umgebungsvariablen und globalen Variablen in einer deklarativen Pipeline. Nach allem, was ich sagen kann, sind die Umgebungen statisch, nachdem sie eingestellt wurden.

def  browser = 'Unknown'

pipeline {
    agent any
    environment {
    //Use Pipeline Utility Steps plugin to read information from pom.xml into env variables
    IMAGE = readMavenPom().getArtifactId()
    VERSION = readMavenPom().getVersion()


    }
    stages {
        stage('Example') {
            steps {
                script {
                    browser = sh(returnStdout: true, script: 'echo Chrome')
                }
            }
        }
        stage('SNAPSHOT') {
                when {
                    expression { 
                        return !env.JOB_NAME.equals("PROD") && !env.VERSION.contains("RELEASE")
                    }
                }
                steps {
                    echo "SNAPSHOT"
                    echo "${browser}"
                }
            }
            stage('RELEASE') {
                when {
                    expression { 
                        return !env.JOB_NAME.equals("TEST") && !env.VERSION.contains("RELEASE")
                    }
                }
                steps {
                    echo "RELEASE"
                    echo "${browser}"
                }
            }
    }//end of stages 
}//end of pipeline
Pitchblack408
quelle
Der obige Code zeigt den folgenden Fehler an: [Pipeline] Beginn der Pipeline [Pipeline] readMavenPom [Pipeline] Ende der Pipeline org.jenkinsci.plugins.workflow.steps.MissingContextVariableException: Erforderliche Kontextklasse hudson.FilePath fehlt Möglicherweise haben Sie vergessen zu umgeben der Code mit einem Schritt, der dies bereitstellt, wie zum Beispiel: node
mancocapac
Nein, es hat so funktioniert wie es ist. Es ist eine deklarative Pipeline. Agent jedes Mittel , dass es auf jedem Knoten arbeiten können
pitchblack408
@ Pitchblack408, Sie haben Recht, ich hatte [Agent keine] oben in meiner Pipeline. Sie sind sich nicht sicher, was Sie damit meinen: Die Umgebung ist statisch, nachdem sie festgelegt wurde? Sie können innerhalb eines Skripts geändert werden, z. B. Skript {IMAGE = "newVal}
mancocapac
Beispiel: Schauen Sie sich IMAGE an. Es ist keine Variable, die von den Pipelines geändert werden kann oder sollte. Nach meinem Verständnis ist es nach der Definition als Teil der Umgebung als statischer Wert zu behandeln.
pitchblack408
0

Sie verwenden eine deklarative Pipeline , die ein erfordert Skript-Schritt Groovy Code auszuführen. Dies ist ein großer Unterschied zu der Scripted Pipeline, bei der dies nicht erforderlich ist.

In der offiziellen Dokumentation heißt es:

Der Skriptschritt nimmt einen Block der Skriptpipeline und führt diesen in der deklarativen Pipeline aus.

pipeline {
   agent none
   stages {
       stage("first") {
           script {
               def foo = "foo" 
               sh "echo ${foo}"
           }
       }
   }
}
Michael Kemmerzell
quelle