Дженкинс: невозможно определить переменную на этапе конвейера

106

Я пытаюсь создать декларативный сценарий конвейера Jenkins, но возникают проблемы с простым объявлением переменной.

Вот мой сценарий:

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

Однако я получаю эту ошибку:

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

Я использую Jenkins 2.7.4 и Pipeline 2.4.

Малькольм Крам
источник

Ответы:

101

Декларативная модель для Jenkins Pipelines имеет ограниченный набор синтаксиса, который она допускает в stageблоках - см. Руководство по синтаксису для получения дополнительной информации . Вы можете обойти это ограничение, заключив свои шаги в script { ... }блок, но в результате вы потеряете проверку синтаксиса, параметров и т. Д. Внутри scriptблока.

абайер
источник
5
Что, если я захочу использовать эту переменную вне блока скрипта?
Ян Стейнке
3
для использования переменной вне блока скрипта проверьте это stackoverflow.com/questions/43879733/…
Senthil A Kumar
56

Я думаю, что ошибка исходит не из указанной строки, а из первых трех строк. Попробуйте вместо этого:

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

Я думаю, у вас были лишние строки, которые недействительны ...

РЕДАКТИРОВАТЬ

Из документации по environmentдекларативной модели конвейера кажется, что вам нужно использовать блок объявления для объявления ваших переменных, например:

pipeline {
   environment {
     FOO = "foo"
   }

   agent none
   stages {
       stage("first") {
           sh "echo ${FOO}"
       }
   }
}
Pom12
источник
1
Вы также можете добавить блок среды в этап (например, если ваша переменная зависит от чего-то, сделанного на предыдущем этапе).
Тереза ​​Томцова
34

Согласитесь с @ Pom12, @abayer. Для завершения ответа вам необходимо добавить блок скрипта

Попробуйте что-то вроде этого:

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
источник
4
Обратите внимание, что в этом примере предполагается, что уже существует определенная переменная среды «ENVIRONMENT_NAME», доступная для jenkins.
Альберто
1
Может ли блок сценария изменить значения среды?
pitchblack408
Да, вы можете изменить значение среды внутри блока скриптов.
NicoPaez
8

В Jenkins 2.138.3 есть два разных типа конвейеров.

Декларативные и скриптовые конвейеры.

«Декларативные конвейеры - это новое расширение конвейерного DSL (это, по сути, конвейерный сценарий с одним шагом, шаг конвейера с аргументами (называемыми директивами), эти директивы должны следовать определенному синтаксису. Суть этого нового формата в том, что он является более строгим и, следовательно, должен быть проще для тех, кто плохо знаком с конвейерами, допускает графическое редактирование и многое другое. конвейеры со сценариями - это запасной вариант для расширенных требований ".

Конвейер Дженкинса: агент против узла?

Вот пример использования окружения и глобальных переменных в декларативном конвейере. Из того, что я могу сказать, enviroment статичны после того, как они установлены.

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
смольчерный408
источник
Я получаю следующую ошибку из приведенного выше кода: [Pipeline] Начало конвейера [Pipeline] readMavenPom [Pipeline] End of Pipeline org.jenkinsci.plugins.workflow.steps.MissingContextVariableException: Требуемый класс контекста hudson.FilePath отсутствует Возможно, вы забыли окружить код с шагом, обеспечивающим это, например: node
mancocapac
Нет, все заработало как есть. Это декларативный конвейер. Агент любые средства , которые он может работать на любом узле
pitchblack408
@ pitchblack408, вы правы, у меня был [агент none] на вершине моего конвейера. Не уверены, что вы имеете в виду под: среда статична после установки? Их можно изменить в сценарии, например script {IMAGE = "newVal}
mancocapac
Например, посмотрите ИЗОБРАЖЕНИЕ. Это не переменная, которая может или должна изменяться конвейерами. Насколько я понимаю, это должно рассматриваться как статическое значение после определения как часть среды.
pitchblack408
0

Вы используете декларативный конвейер, который требует шага сценария для выполнения кода Groovy. Это огромная разница по сравнению со скриптовым конвейером. где в этом нет необходимости.

В официальной документации сказано следующее:

Шаг скрипта берет блок Scripted Pipeline и выполняет его в Declarative Pipeline.

pipeline {
   agent none
   stages {
       stage("first") {
           script {
               def foo = "foo" 
               sh "echo ${foo}"
           }
       }
   }
}
Майкл Кеммерцелл
источник