Jenkins: no se puede definir la variable en la etapa de canalización

106

Estoy intentando crear un script de canalización declarativo de Jenkins, pero tengo problemas con la declaración de variable simple.

Aquí está mi guión:

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

Sin embargo, obtengo este error:

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

Estoy en Jenkins 2.7.4 y Pipeline 2.4.

Malcolm Crum
fuente

Respuestas:

101

El modelo declarativo para Jenkins Pipelines tiene un subconjunto restringido de sintaxis que permite en los stagebloques; consulte la guía de sintaxis para obtener más información . Puede eludir esa restricción agrupando sus pasos en un script { ... }bloque, pero como resultado, perderá la validación de la sintaxis, los parámetros, etc.dentro del scriptbloque.

abayer
fuente
5
¿Qué pasa si quiero usar esa variable fuera del bloque de script?
Jan Steinke
3
para usar una variable fuera del bloque de script, consulte esto stackoverflow.com/questions/43879733/…
Senthil A Kumar
56

Creo que el error no proviene de la línea especificada sino de las primeras 3 líneas. Prueba esto en su lugar:

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

Creo que tenías algunas líneas extra que no son válidas ...

EDITAR

De la documentación del modelo de canalización declaractiva , parece que debe usar un environmentbloque de declaración para declarar sus variables, por ejemplo:

pipeline {
   environment {
     FOO = "foo"
   }

   agent none
   stages {
       stage("first") {
           sh "echo ${FOO}"
       }
   }
}
Pom12
fuente
1
También puede agregar un bloque de entorno en una etapa (por ejemplo, si su variable depende de algo hecho en un paso anterior).
Tereza Tomcova
34

De acuerdo con @ Pom12, @abayer. Para completar la respuesta, debe agregar un bloque de script

Intente algo como esto:

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
fuente
4
Observe que este ejemplo asume que ya existe una variable de entorno definida "ENVIRONMENT_NAME" accesible para jenkins.
Alberto
1
¿Puede el bloque de secuencia de comandos cambiar los valores del entorno?
pitchblack408
Sí, puede cambiar el valor del entorno dentro del bloque de script.
NicoPáez
8

En Jenkins 2.138.3 hay dos tipos diferentes de canalizaciones.

Pipelines declarativos y con script.

"Las canalizaciones declarativas son una nueva extensión del DSL de canalización (básicamente es una secuencia de comandos de canalización con un solo paso, un paso de canalización con argumentos (llamados directivas), estas directivas deben seguir una sintaxis específica. El objetivo de este nuevo formato es que es más estricto y, por lo tanto, debería ser más fácil para los nuevos en las canalizaciones, permitir la edición gráfica y mucho más. Las canalizaciones con secuencias de comandos son la alternativa para los requisitos avanzados ".

canalización de Jenkins: agente vs nodo?

A continuación, se muestra un ejemplo del uso de variables globales y de entorno en una canalización declarativa. Por lo que puedo decir, el entorno es estático después de que se configuran.

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
tono negro408
fuente
Recibo el siguiente error del código anterior: [Pipeline] Start of Pipeline [Pipeline] readMavenPom [Pipeline] End of Pipeline org.jenkinsci.plugins.workflow.steps.MissingContextVariableException: Falta la clase de contexto necesaria hudson.FilePath Quizás se olvidó de rodear el código con un paso que proporciona esto, como: nodo
mancocapac
No, funcionó como está. Es una canalización declarativa. Agente cualquiera significa que puede funcionar en cualquier nodo
pitchblack408
@ pitchblack408, tienes razón, tenía [agente ninguno] en la parte superior de mi canalización. ¿No está seguro de lo que quiere decir con: los entornos son estáticos después de configurados? Se pueden cambiar dentro de una secuencia de comandos, por ejemplo, secuencia de comandos {IMAGE = "newVal}
mancocapac
Ejemplo, mira IMAGEN. No es una variable que pueda o deba ser cambiada por las tuberías. Tengo entendido que debe tratarse como un valor estático después de la definición como parte del entorno.
pitchblack408
0

Está utilizando un canal declarativo que requiere un paso de guión para ejecutar el código Groovy. Esta es una gran diferencia en comparación con canal de secuencia de comandos donde esto no es necesario.

La documentación oficial dice lo siguiente:

El paso de guión toma un bloque de canalización con script y lo ejecuta en la canalización declarativa.

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