Vous devez créer un job de déploiement et cherchez à récupérer les versions de l’application de manière dynamique ?
Ce tutoriel est fait pour vous !

Contexte

Vous développez une application et Jenkins vous permet de construire et déployer les versions dans votre infrastructure.

Vous souhaitez créer un job qui déploie une version “disponible” de l’application.

Une version est dite “disponible” si elle est récupérable depuis un repository ou une registry. La forme de la version importe peu, tant que l’outil fournit une API pour requêter les versions qui y sont stockées.

Nous allons mettre en place un job Jenkins qui récupère dynamiquement ces versions.

Repository ou registry

Votre application est construite et publiée dans un repository ou une registry. Cet équipement met à disposition une API qui permet de lister les versions disponibles au format JSON.

Supposons que nous pouvons récupérer les versions disponibles à l’URL : https://ma-registry/mon-application/mon-service

Supposons que le requête retourne la sortie suivante :

{
    "name": "front",
    "releases": [
        "1.0.0",
        "1.0.1-hf",
        "1.1.0-rc"
    ]
}

Cette étape permet de lire la structure de la réponse et donc d’adapter les snippets de code qui vont suivre.

Configurer Jenkins

Jenkins est installé en v2.60 à minima (à date de l’article).

Nous pouvons créer le job de déploiement de type Pipeline.
Le job comportera un paramètre d’entrée qui sera la version de l’application à déployer.

Cependant, la configuration de base de Jenkins permet uniquement de requêter de manière séquentielle, même quand il s’agit d’exécuter une requête avant de lancer le Pipeline Jenkins.
Dans notre cas, il n’est pas d’une grande utilité de lancer le job “juste” pour mettre à jour la liste des versions déployables.

Nous devons récupérer les versions disponibles avant d’exécuter le Pipeline Jenkins.

Plugin Jenkins

Pour étoffer les paramètres des jobs Jenkins, nous allons installer le plugin Extended Choice Parameter.

Il fournir des options supplémentaires aux paramètres d’entrée des jobs Jenkins.

Job Jenkins

Créons notre job Jenkins :

  • Nom : deployStaging
  • Type : Pipeline

Cochez la case “Ce job a des paramètres” et constatez le nouvel élément : Extended Choice Parameter :

Ce qui ouvre une nouvelle section :

Choisissez l’option Basic Parameter Types et sélectionnez l’option Single Select (qui permet d’afficher une Listbox à l’utilisateur).

Dans la section Basic Parameter Types, choisissez l’option Groovy Script.

Nous allons maintenant définir le script Groovy qui servira à récupérer les versions disponibles.

import groovy.json.JsonSlurper
try {
    List<String> artifacts = new ArrayList<String>()
    def artifactsUrl = "https://ma-registry/mon-application/mon-service"
    def artifactsObjectRaw = ["curl", "-s", "-H", "accept: application/json", "${artifactsUrl}"].execute().text
    def jsonSlurper = new JsonSlurper()
    def artifactsJsonObject = jsonSlurper.parseText(artifactsObjectRaw)
    return artifactsJsonObject.releases
} catch (Exception e) {
    return "An error occured on request."
}

N’oubliez pas d’adapter la variable artifactsUrl et l’objet retourné artifactsJsonObject.releases.

Approbation du script

Vous avez inséré du script Groovy dans Jenkins à exécuter sur le master, il peut être malveillant. C’est pour cette raison que Jenkins vous demande d’approuver le contenu du script.

Au moment de la première exécution du job, le message suivant apparaîtra.

Il faut se rendre sur le lien ou à l’adresse https://jenkins:8080/scriptApproval/ et accepter le morceau de code que nous venons de déployer.

Approuvez et retournez sur la page du job de déploiement.

Exécution du job

Maintenant que tout est correctement configuré, lancez le job à l’aide du bouton “Lancer un build avec des paramètres“.

Vous verrez que le paramètre de choix configuré précédemment aura récupéré les valeurs mises à disposition par l’API.

Et voila le travail ! Il ne vous reste plus qu’à adapter ce tutoriel à votre besoin.

Les différentes méthodes

Jenkins permet d’utiliser l’interface pour réaliser les actions précédemment décrites. Néanmoins cette méthode ne fonctionne pas si vous récupérer un Pipeline depuis un repository Git.
Le pipeliné rapatrié écrasera toutes les modifications précédentes… dommage !

C’est pour cette raison qu’il faut intégrer les paramètres étendus au Pipeline lui-même.

Depuis l’interface

C’est la méthode qui a été présentée dans la section précédente.

DSL Jobs Pipelines

Beaucoup de pipelines sont écrits avec le DSL Jenkins qui permet de “développer” les pipelines à l’aide du langage Groovy.

En groovy, l’implémentation s’écrit comme présenté ci-dessous :

def GET_VERSIONS = '''
import groovy.json.JsonSlurper
try {
    List<String> artifacts = new ArrayList<String>()
    def artifactsUrl = "https://ma-registry/mon-application/mon-service"
    def artifactsObjectRaw = ["curl", "-s", "-H", "accept: application/json", "${artifactsUrl}"].execute().text
    def jsonSlurper = new JsonSlurper()
    def artifactsJsonObject = jsonSlurper.parseText(artifactsObjectRaw)
    return artifactsJsonObject.releases
} catch (Exception e) {
    return "An error occured on request."
}'''

properties([
    parameters([
        extendedChoice( 
            name: 'VERSION', 
            description: 'Version de mon application', 
            type: 'PT_SINGLE_SELECT', 
            groovyScript: GET_VERSIONS,
        )
    ])
])

Declarative pipeline

Cela fait un moment que les “declarative pipelines” ont vu le jour pour faciliter l’écriture des jobs d’intégration continue.

En declarative pipeline, l’implémentation s’écrit comme présenté ci-dessous :

def GET_VERSIONS = '''
import groovy.json.JsonSlurper
try {
    List<String> artifacts = new ArrayList<String>()
    def artifactsUrl = "https://ma-registry/mon-application/mon-service"
    def artifactsObjectRaw = ["curl", "-s", "-H", "accept: application/json", "${artifactsUrl}"].execute().text
    def jsonSlurper = new JsonSlurper()
    def artifactsJsonObject = jsonSlurper.parseText(artifactsObjectRaw)
    return artifactsJsonObject.releases
} catch (Exception e) {
    return "An error occured on request."
}'''

pipeline {
  [...]

    parameters {
        extendedChoice(
            name: 'VERSION',
            description: 'Version de mon application',
            defaultValue: '',
            type: 'PT_SINGLE_SELECT',
            groovyScript: GET_VERSIONS
        )
    }

    [...]
}

Conclusion

Vous savez récupérer dynamiquement les valeurs à partir d’un simple fichier JSON mis à disposition.
Vous pouvez maintenant aller plus loin avec la gestion de vos jobs Jenkins en agrémentant leurs paramètres.

Notre prochain article vous expliquera comment récupérer les versions des images docker dans AWS ECR depuis une instance Jenkins hébergée dans Kubernetes.