Проблема:
При передаче переменной, объявленной в 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.