4 votes

Environnements par tâche dans Jenkins avec virtualenv

Je suis en train d'essayer d'utiliser virtualenv pour gérer de manière programmable les environnements Python pour chaque travail sur un serveur Jenkins, implémenté via une extension de Librairie Partagée pour activer les environnements sur une base de tâche. Par exemple :

/vars/activateEnvironment.groovy:

def call(String env = "/usr/local/etc/environments/jenkins-$JOB_NAME") {

    sh """
    mkdir ${env}
    virtualenv ${env}
    source ${env}/bin/activate
    """
}

Script de pipeline, dans lequel le dépôt virtualenv-scripts contient le fichier ci-dessus :

@Library('virtualenv-scripts') _

pipeline {
    agent any
    stages {
        stage("Test") {
            steps {
                activateEnvironment()
                sh 'which pip'
                sh 'echo \$PATH'
            }
        }
    }
}

En exécutant ce script de pipeline, j'obtiens la sortie suivante :

[Pipeline] sh
[example-pipeline] Exécution du script shell
+ echo /sbin:/usr/sbin:/bin:/usr/bin
/sbin:/usr/sbin:/bin:/usr/bin
[Pipeline] sh
[example-pipeline] Exécution du script shell
+ which pip
/bin/pip

J'ai essayé d'utiliser cette réponse pour que Jenkins utilise un shell de connexion, mais cela recharge toujours l'environnement à chaque appel sh.

J'ai également vu cette réponse qui nécessiterait de coller du texte supplémentaire chaque fois qu'une étape sh est utilisée dans un Pipeline -- pas idéal.

Existe-t-il un bon moyen de conserver l'environnement entre les commandes sh ? Alternativement, existe-t-il un meilleur moyen d'obtenir des environnements par travail avec virtualenv ? Merci pour toute l'aide/suggestions !

6voto

jayhendren Points 817

J'ai eu le même problème. Après avoir discuté avec des administrateurs Jenkins expérimentés, voici la solution à laquelle je suis parvenu :

def runCommandInMyEnvironment(cmd) {
  sh "setup_environment_command; source ./some/file; ${cmd}"
}

pipeline {
  agent any
  stages {
    stage("My Stage") {
      steps {
        runCommandInMyEnvironment('first_command')
        runCommandInMyEnvironment('second_command')
        // et ainsi de suite
      }
    }
  }
}

Ce n'est pas très beau et cela peut rendre la sortie de la console assez encombrée, mais c'est aussi la manière la plus fiable de le faire.

Une autre approche consisterait à analyser la sortie d'une commande et à la diviser en plusieurs variables d'environnement pour les passer à un bloc withEnv, mais cette approche peut être très délicate et peu fiable.

Quoi qu'il en soit, comme vous l'avez laissé entendre, Jenkins ne prend pas en charge la persistance des environnements sans withEnv, donc finalement il n'y a pas de bonne façon propre de le faire.

Il peut y avoir une meilleure façon d'utiliser des environnements virtuels avec Jenkins, mais je n'ai jamais écrit de tâche Jenkins qui s'exécute dans un environnement virtuel, donc je ne peux pas dire. Il y a ce plugin, mais une autre réponse stackoverflow suggère que l'approche que j'ai donnée dans cette réponse est la méthode préférée pour travailler avec des environnements virtuels dans Jenkins.

0 votes

Cela semble fonctionner relativement bien avec virtualenv. Si la configuration de l'environnement était une tâche plus lourde, je ne voudrais pas l'appeler plusieurs fois, mais dans mon cas ce n'est pas le cas. Merci, @jayhendren

0 votes

Grande et simple solution!

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X