web-dev-qa-db-fra.com

Fichier de pipeline Jenkins - Passer des variables Jenkinsfile dans d'autres commandes

Problème:

En passant une variable déclarée dans Jenkinsfile à une commande sh qui ssh s'exécute et s'exécute sur un hôte distant, le contenu de la variable n'est pas conservé sur l'hôte distant.

Les variables Jenkins intégrées se conservent bien à la fois localement et sur l'hôte distant. La variable que j'ai définie fonctionne bien localement mais ne se traduit pas sur l'hôte distant.

Bien que ce problème fasse référence à Docker, il s'agit en fait d'un pipeline 100% Jenkins car il pourrait s'appliquer à n'importe quel exemple avec ou sans Docker.

Contexte:

J'essaie de créer dynamiquement un nom d'image basé sur la balise de construction actuelle et de mettre ce nom dans une variable.

Ensuite, je passe cette variable à l'étape sh qui remote vers un hôte Docker et exécute une étape de génération avec le nom défini.

Extrait des parties applicables du fichier Jenkins ...

// 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} ."'
}

Normalement, je suppose qu'il n'a pas les variables car c'est un hôte distant ... Cependant, il est étrange que ${BUILD_NUMBER} et ${BUILD_TAG} traduire et fonctionner correctement sur l'hôte distant. Pourquoi ${jobBaseName} ?? (il sort vide/nul sur l'hôte distant).

4
emmdee

Comme il n'est pas garanti que vos étapes individuelles s'exécuteront sur le même nœud exécuteur (sauf si vous avez les étapes enveloppées dans le même bloc node), l'utilisation de fichiers pour partager des informations entre les étapes ne sera pas fiable. Utilisez plutôt des variables:

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} .'"
}

Soit dit en passant, je suggère également d'utiliser sshAgent et le magasin d'informations d'identification intégré de Jenkins pour gérer les clés SSH au lieu de passer manuellement le -i drapeau vers SSH.

3
jayhendren