2017-07-06 2 views
0

Je crée ma propre bibliothèque partagée Jenkins pour réutiliser du code entre les pipelines. Je sais comment créer des étapes (très facile en effet) mais j'ai un problème quand je veux rendre accessible ma "classe utils" dans le fichier jenkins (ou WorkflowScript comme le dit Jenkins dans les logs). j'appelle « classe Util » une classe groovy situé dans le dossier src/ma/domaine/... qui ont beaucoup de méthodes, par exemple, je veux créer une classe de journal comme celui-ci:Bibliothèque partagée Jenkins instancier la classe util et l'utiliser dans workflowscript

# src/my/domain/group 

package my.domain.group 

class Console implements Serializable { 

    def log(msg) { 
     spit(msg, '\033[34m') 
    } 

    def error(msg) { 
     spit(msg, '\033[31m') 
    } 

    def warning(msg){ 
     spit(msg, '\033[33m') 
    } 

    def success(msg){ 
     spit(msg, '\033[32m') 
    } 

    private def spit(msg, color){ 
     ansiColor('xterm') { 
      echo color + msg + '\033[0m' 
     } 
    } 

} 

Et puis je essayez d'instancier dans un fichier /vars/library.groovy peut donc être accessible à partir du Jenkinsfile avec un code comme par exemple:

node("mynode"){ 
    console.log("Hello World!") 
} 

l'idée est d'éviter d'instancier la console dans tout le script et le faire automatiquement, j'ai essayé plusieurs choses comme

# vars/library.groovy 

import my.domain.group.Console 
import groovy.transform.Field 

@Field String console = new Console() 

ou

# vars/library.groovy 

import my.domain.group.Console 

def load(){ 
    this.console = new Console() 
    // And also 
    console = new Console() 
} 

Mais en essayant d'accéder à partir du fichier de jenkins je reçois toujours l'erreur: groovy.lang.MissingPropertyException: Aucun bien: console pour la classe: WorkflowScript

Je comprends que ce moyen que l'instance n'est pas à la bonne portée donc ne peut pas être directement vu par le script mais comment puis-je faire cela?

Merci!

Répondre

2

On dirait que vous utilisez votre script vars correctement dans votre Jenkinsfile, mais je vais essayer de résoudre quelques confusions :)

  1. scripts Groovy définis dans le répertoire vars sont appelés par leur nom de fichier « sur mesure "entrez dans votre Jenkinsfile. En supposant que votre nom de script reste library.groovy, votre Jenkinsfile devrait ressembler à ceci

    node ("mynode") { 
        library("Hello World!") 
    } 
    

    ou bien (puisque les parenthèses sont facultatives)

    node ("mynode") { 
        library "Hello World!" 
    } 
    
  2. De plus vars scripts ne doivent contenir qu'une seule fonction nommée call et nécessaire importations. Puisque vous voulez passer votre message de journal sous la forme d'une chaîne, la fonction call a en outre besoin d'un paramètre. Donc, votre script library.groovy dans vars pourrait ressembler à ceci

    # vars/library.groovy 
    
    import my.domain.group.Console 
    
    def call(msg){ 
        Console console = new Console(steps) 
        console.log(msg) 
    } 
    

    Dans la fonction call vous pouvez utiliser toutes les étapes de base (Jenkins sh, bat, etc.) que vous pourriez dans votre Jenkinsfile, ainsi que toutes les classes Groovy/Java importés via import (comme votre classe Console).

    Comme vous avez pu le remarquer, j'ai également ajouté une variable steps (qui n'a pas à être déclarée ou instanciée manuellement) au constructeur de votre classe Console. Ceci est nécessaire car vous ne pouvez pas utiliser les étapes de Jenkins directement dans l'une de vos classes définies dans le répertoire src.Résultant, la méthode

    private def spit(msg, color){   
        ansiColor('xterm') { 
         echo color + msg + '\033[0m' 
        } 
    } 
    

    ne fonctionnerait pas, parce que echo est une étape Jenkins. Pour utiliser echo dans votre classe, vous pouvez passer la variable steps au constructeur et la stocker dans une autre variable de votre classe. Ensuite, vous pouvez appeler toutes les étapes Jenkins comme steps.echo "Hello World"

    # src/my/domain/group 
    
    package my.domain.group 
    
    class Console implements Serializable { 
    
        def steps 
    
        Console(steps) { 
         this.steps = steps 
        } 
    
        def log(msg) { 
         spit(msg, '\033[34m') 
        } 
    
        def error(msg) { 
         spit(msg, '\033[31m') 
        } 
    
        def warning(msg){ 
         spit(msg, '\033[33m') 
        } 
    
        def success(msg){ 
         spit(msg, '\033[32m') 
        } 
    
        private def spit(msg, color){ 
         ansiColor('xterm') { 
          steps.echo color + msg + '\033[0m' 
         } 
        } 
    } 
    

Cela devrait le faire fonctionner.

Vous devriez penser à renommer votre library.groovy en vars (par exemple myLog.groovy). Ensuite, votre Jenkinsfile pourrait ressembler à ceci

node ("mynode") { 
    myLog "Hello World!" 
} 

Pour utiliser les autres méthodes de votre classe Console, vous pouvez créer des scripts supplémentaires à l'intérieur vars. Leur utilisation pourrait ressembler à ceci

node ("mynode") { 
    myLog "Hello World!" 
    myWarning "Hello World!" 
    myError "Hello World!" 
    mySuccess "Hello World!" 
} 

(im en utilisant le préfixe my pour éviter les collisions de noms avec des étapes Jenkins déjà existantes. Par exemple, l'étape error existe déjà et de l'appeler dans votre Jenkinsfile annulera votre build)

Pour plus d'informations sur les bibliothèques partagées consulter la documentation Jenkins à https://jenkins.io/doc/book/pipeline/shared-libraries/

Vous trouverez une liste complète de toutes les étapes de base à Jenkins https://jenkins.io/doc/pipeline/steps/workflow-basic-steps/

Obtenir Jenkins et les pipelines pour travailler peut être un énorme problème, mais à la fin, ça vaut le coup. J'espère que ce mur de texte aide un peu. Bonne chance et codage heureux :)

+0

Merci pour votre réponse Adrian! Je sais comment utiliser les étapes mais j'ai oublié de mettre ce code dans mon exemple désolé :-). En lisant votre réponse, puis-je comprendre que je ne peux pas exposer une instance d'une classe à utiliser directement dans les pipelines Jenkins? Je connais l'option de créer différentes étapes pour chacune de mes méthodes en console mais je pense qu'il est plus clair d'exposer directement une instance de console à partir de vars (je ne sais pas si c'est possible) et ensuite l'utiliser dans le fichier Jenkins directement comme je le montre dans mon exemple. – joliva

+0

Eh bien, vous pouvez complètement vous passer de votre script 'library.groovy' dans' vars' et utiliser la classe 'Console' directement dans votre Jenkinsfile. Assurez-vous simplement d'importer votre bibliothèque partagée via @Library ('[LIB_NAME]') _', où '[LIB_NAME]' est le nom de votre bibliothèque spécifié dans vos paramètres Jenkins, et votre classe via 'import my.domain. Util.Console' de l'intérieur de votre Jenkinsfile. –