問題:
Jenkinsfile内で宣言された変数をsh
コマンドに渡してsshを実行し、リモートホストで実行すると、変数の内容はリモートホストで保持されません。
組み込みのJenkins変数は、ローカルとリモートホストの両方で正常に保持されます。定義した変数はローカルで正常に機能しますが、リモートホストでは変換されません。
この問題はDockerを参照していますが、Dockerの有無に関係なくすべての例に当てはまる可能性があるため、これは実際には100%Jenkinsパイプラインベースです。
背景:
現在のビルドタグに基づいて動的にイメージ名を作成し、その名前を変数に入れようとしています。
次に、その変数をsh
ステップに渡します。このステップは、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}
?? (リモートホストでは空/ nullになります)
個々のステージが同じexecutorノードで実行されることが保証されていないため(ステージが同じnode
ブロックでラップされていない限り)、ステージ間で情報を共有するためにファイルを使用することは信頼できません。代わりに変数を使用します。
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} .'"
}
ちなみに、-i
フラグを手動でSSHに渡す代わりに、sshAgent
とJenkinsの組み込み認証情報ストアを使用してSSHキーを管理することもおすすめします。