Назад | Перейти на главную страницу

Файл конвейера Jenkins - передача переменных Jenkinsfile в дальнейшие команды

Проблема:

При передаче переменной, объявленной в Jenkinsfile, в sh команда, которую ssh выполняет на удаленном хосте, содержимое переменной не сохраняется на удаленном хосте.

Встроенные переменные Jenkins отлично сохраняются как локально, так и на удаленном хосте. Переменная, которую я определил, отлично работает локально, но не переводится на удаленный хост.

Хотя эта проблема относится к Docker, на самом деле это 100% конвейер на основе Jenkins, так как это можно применить к любому примеру с Docker или без него.

Задний план:

Я пытаюсь динамически создать имя изображения на основе текущего тега сборки и поместить это имя в переменную.

Затем я передаю эту переменную в sh step, который переходит к хосту Docker и запускает этап сборки с заданным именем.

Фрагмент применимых частей Jenkinsfile ...

// The below stage just echo's out some stuff into a file dockerimgname.jenkins.out
stage ('Construct Img name') {
  sh '''echo ${BUILD_TAG} | awk '{print tolower($0)}' | sed 's/jenkins-//' > dockerimgname.jenkins.out'''
}

// This stage reads that file from previous stage and puts the value into variable.
// The variable is echo'd locally which works perfectly. Then ssh is called to execute command on remote host. That's where the variable value doesn't work.
stage ('Build Target Container') {
  def jobBaseName = readFile 'dockerimgname.jenkins.out'
  echo "${jobBaseName}"
  sh 'ssh -i ~/ssh_keys/key.key user@somehost "cd /dockerdata/build/${BUILD_TAG} && docker build -t localrepo/${jobBaseName}:${BUILD_NUMBER} ."'
}

Обычно я предполагаю, что у него нет переменных, так как это удаленный хост ... Однако странно, что ${BUILD_NUMBER} и ${BUILD_TAG} переводить и нормально работать на удаленном хосте. Почему не ${jobBaseName}?? (на удаленном хосте он выходит пустым / нулевым).

Поскольку не гарантируется, что ваши отдельные этапы будут выполняться на одном и том же узле-исполнителе (если только этапы не заключены в один и тот же node block), использование файлов для обмена информацией между этапами будет ненадежным. Вместо этого используйте переменные:

def jobBaseName

stage ('Construct Img name') {
  jobBaseName = sh(
    script: "echo ${BUILD_TAG} | awk '{print tolower($0)}' | sed 's/jenkins-//'",
    returnStdout: true,
  )
}

stage ('Build Target Container') {
  sh "ssh -i ~/ssh_keys/key.key user@somehost 'cd /dockerdata/build/${BUILD_TAG} && docker build -t localrepo/${jobBaseName}:${BUILD_NUMBER} .'"
}

Кстати, я бы также предложил использовать sshAgent и встроенное хранилище учетных данных Jenkins для управления ключами SSH вместо передачи вручную -i флаг в SSH.