Déclaratif vs. Scripté : Choisir la syntaxe de votre pipeline Jenkins

Comparez les syntaxes de pipeline Jenkins déclaratif et scripté, avec des exemples et des conseils pratiques pour savoir quand utiliser chacune.

Déclaratif vs. Scripté : Choisir la syntaxe de votre pipeline Jenkins

Jenkins Pipeline vous offre deux façons d'écrire un Jenkinsfile : Déclaratif et Scripté. Les deux permettent de construire, tester et déployer votre application, mais ils vous orientent vers des compromis différents en termes de lisibilité, de validation et de flexibilité Groovy.

Si votre équipe choisit une syntaxe pour un nouveau pipeline, commencez par le workflow que vous devrez maintenir dans six mois. Le Déclaratif est généralement plus facile à lire et à réviser. Le Scripté vous donne un contrôle Groovy plus direct lorsque le pipeline nécessite véritablement un comportement dynamique.

Comprendre les Pipelines Jenkins

Avant de plonger dans les syntaxes, rappelons brièvement ce qu'est un Pipeline Jenkins. Un Pipeline est un ensemble de plugins qui prend en charge l'implémentation et l'intégration de pipelines de livraison continue dans Jenkins. Il s'agit essentiellement d'une séquence d'étapes automatisées qui définissent l'ensemble du processus de livraison de logiciels, du commit du code au déploiement. Ces étapes sont définies dans un Jenkinsfile, généralement écrit en Groovy, et offrent un moyen puissant de gérer des scénarios complexes de construction, de test et de déploiement.

Jenkins Pipeline as Code offre plusieurs avantages clés :

  • Contrôle de version : Le Jenkinsfile est stocké dans le contrôle de source, tout comme le code de l'application, permettant le versionnage, l'audit et la collaboration.
  • Répétabilité : Assure une exécution cohérente du processus de livraison dans différents environnements et exécutions.
  • Visibilité : Fournit une vue claire et compréhensible de l'ensemble du processus de livraison.
  • Durabilité : Les pipelines peuvent survivre aux redémarrages du maître Jenkins.
  • Extensibilité : Grâce aux bibliothèques partagées, une logique complexe peut être abstraite et réutilisée.

Pipelines Déclaratifs

Le Pipeline Déclaratif est la syntaxe plus récente et opinionnée conçue pour faciliter l'écriture et la compréhension des pipelines. Il fournit une approche structurée avec des blocs prédéfinis, ce qui aide les équipes à maintenir la cohérence des Jenkinsfiles.

Caractéristiques et Syntaxe

Les Pipelines Déclaratifs imposent une structure spécifique définie par des blocs de niveau supérieur comme pipeline, agent, stages, steps, post, environment, parameters, options, triggers, tools, input et when. Cette structure simplifie la définition du pipeline en fournissant des limites claires pour différentes parties du workflow.

Voici une structure de base d'un Pipeline Déclaratif :

pipeline {
    agent any // Ou 'label', 'docker', etc.

    stages {
        stage('Build') {
            steps {
                echo 'Construction de l'application...'
                sh 'mvn clean install'
            }
        }
        stage('Test') {
            steps {
                echo 'Exécution des tests...'
                sh 'mvn test'
            }
        }
        stage('Deploy') {
            when {
                branch 'main'
            }
            steps {
                echo 'Déploiement en production...'
                script {
                    // La logique de type Scripté peut être mise ici si absolument nécessaire
                    // Par exemple, appeler une fonction de bibliothèque partagée
                    // mySharedLibrary.deployApplication()
                }
            }
        }
    }

    post {
        always {
            echo 'Pipeline terminé.'
        }
        success {
            echo 'Pipeline réussi !'
        }
        failure {
            echo 'Pipeline échoué.'
        }
    }
}

Avantages des Pipelines Déclaratifs

  • Simplicité et Lisibilité : La structure prédéfinie rend les pipelines faciles à lire et à comprendre, même pour les non-experts. Cela ressemble plus à un fichier de configuration.
  • Approche Structurée : Impose les meilleures pratiques et la cohérence entre les pipelines, réduisant la courbe d'apprentissage et le potentiel d'erreurs.
  • Fonctionnalités Intégrées : Offre un ensemble riche de fonctionnalités intégrées pour les modèles CI/CD courants, tels que l'exécution conditionnelle (when), les actions post-construction (post), l'exécution parallèle des étapes et diverses options pour gérer le flux du pipeline.
  • Plus Facile à Apprendre : Les développeurs sans connaissances approfondies de Groovy peuvent rapidement démarrer grâce à sa syntaxe opinionnée.
  • Validation : Jenkins peut valider davantage la structure avant l'exécution car le Déclaratif a des règles plus strictes.

Limitations des Pipelines Déclaratifs

  • Moins Flexible : La structure rigide peut être restrictive pour des workflows hautement complexes ou dynamiques nécessitant une logique Groovy personnalisée en dehors des blocs prédéfinis.
  • Accès Groovy Direct Limité : Bien qu'un bloc script puisse être utilisé pour injecter la syntaxe du Pipeline Scripté, une utilisation excessive peut compromettre les avantages de la syntaxe Déclarative et rendre le pipeline plus difficile à lire.

Quand Utiliser les Pipelines Déclaratifs

Les Pipelines Déclaratifs sont le choix recommandé pour la plupart des scénarios CI/CD courants. Ils sont idéaux pour :

  • Les équipes nouvelles à Jenkins ou Pipeline as Code.
  • Les projets avec des processus de construction, de test et de déploiement simples ou modérément complexes.
  • Assurer la cohérence et la maintenabilité entre de nombreux pipelines.
  • Tirer parti des fonctionnalités intégrées de Jenkins pour des modèles courants comme l'exécution parallèle, les étapes conditionnelles et les notifications.

Pipelines Scriptés

Le Pipeline Scripté, construit directement sur le langage de programmation Groovy, était la syntaxe originale pour Jenkins Pipeline as Code. Il offre une flexibilité et une puissance maximales, permettant aux développeurs d'implémenter des flux d'automatisation hautement personnalisés et dynamiques.

Caractéristiques et Syntaxe

Les Pipelines Scriptés sont exécutés séquentiellement de haut en bas, un peu comme un script Groovy traditionnel. Ils utilisent la syntaxe complète de Groovy et exploitent le DSL (Domain Specific Language) de Jenkins Pipeline via des méthodes comme node, stage, checkout, sh, git, etc. Cela fournit un accès direct à l'API Jenkins et à toute la puissance du langage Groovy.

Voici une structure de base d'un Pipeline Scripté :

node('my-agent-label') {
    stage('Prepare') {
        echo 'Préparation de l'espace de travail...'
        checkout scm
    }

    stage('Build') {
        echo 'Construction de l'application...'
        try {
            sh 'mvn clean install'
        } catch (err) {
            echo "Échec de la construction : ${err}"
            // Gestion d'erreur personnalisée
            currentBuild.result = 'FAILURE'
            throw err
        }
    }

    stage('Test') {
        echo 'Exécution des tests...'
        // Déterminer dynamiquement les suites de tests
        def testSuites = sh(script: 'find tests -name "*.test"', returnStdout: true).trim().split('\n')
        if (testSuites.isEmpty()) {
            echo 'Aucun test trouvé.'
        } else {
            for (suite in testSuites) {
                echo "Exécution de la suite de tests : ${suite}"
                sh "./run-test.sh ${suite}"
            }
        }
    }

    stage('Deploy') {
        // Logique conditionnelle complexe
        if (env.BRANCH_NAME == 'main' && currentBuild.currentResult == 'SUCCESS') {
            echo 'Déploiement en production...'
            sh './deploy-prod.sh'
        } else if (env.BRANCH_NAME == 'develop') {
            echo 'Déploiement en staging...'
            sh './deploy-staging.sh'
        } else {
            echo 'Aucun déploiement pour cette branche.'
        }
    }

    // Les actions post-construction peuvent être implémentées avec des blocs try-finally ou une logique personnalisée
    // Par exemple, envoyer des notifications
    if (currentBuild.result == 'SUCCESS') {
        echo 'Pipeline terminé avec succès !'
        // notifySuccess()
    } else {
        echo 'Pipeline échoué.'
        // notifyFailure()
    }
}

Avantages des Pipelines Scriptés

  • Flexibilité Maximale : Offre toute la puissance de Groovy, permettant une logique hautement complexe et dynamique, des boucles personnalisées, la gestion des erreurs et la manipulation des données.
  • Accès Direct à l'API Jenkins : Offre plus de possibilités d'utilisation de l'API Jenkins et Groovy, bien que certaines opérations dépendent toujours des plugins, des autorisations et du bac à sable de sécurité des scripts.
  • Comportement Dynamique : Idéal pour les workflows nécessitant une allocation dynamique d'agents, une exécution parallèle basée sur des conditions d'exécution, ou une gestion avancée des ressources.
  • Extensibilité : Excellent pour créer des bibliothèques partagées sophistiquées qui encapsulent une logique complexe et réutilisable pour les Pipelines Déclaratifs.

Limitations des Pipelines Scriptés

  • Courbe d'Apprentissage Plus Raide : Nécessite une solide compréhension de Groovy, ce qui peut être un obstacle pour les équipes non familières avec le langage.
  • Moins Opinionné : Sans structure stricte, les pipelines peuvent devenir incohérents et plus difficiles à lire ou à maintenir entre différents projets ou développeurs.
  • Sujet aux Erreurs : La flexibilité de Groovy signifie plus d'opportunités d'erreurs de codage, et moins de validation intégrée par rapport au Déclaratif.
  • Défis de Lisibilité : Les Pipelines Scriptés complexes peuvent rapidement devenir difficiles à analyser et à comprendre, entravant la collaboration et le dépannage.
  • Moins de Syntaxe Spécifique au Pipeline : De nombreux modèles CI/CD courants (comme les actions post ou les conditions when) doivent être implémentés manuellement à l'aide de constructions Groovy (par exemple, try-catch-finally, instructions if).

Déclaratif vs. Scripté : Une Comparaison Côte à Côte

Pour résumer les différences, voici un tableau comparatif :

Fonctionnalité Pipeline Déclaratif Pipeline Scripté
Structure Syntaxique Opinionnée, blocs de niveau supérieur prédéfinis. Flexible, basé sur Groovy, exécution séquentielle.
Courbe d'Apprentissage Plus facile pour les débutants, moins de connaissances Groovy nécessaires. Plus raide, nécessite une expertise Groovy.
Lisibilité Élevée grâce aux blocs structurés et à la syntaxe claire. Peut être faible pour les scripts complexes, dépend du style du développeur.
Flexibilité Limitée aux structures prédéfinies ; blocs script pour Groovy. Illimitée, toute la puissance de Groovy.
Fonctionnalités Intégrées Ensemble riche pour les modèles CI/CD courants (post, when, parallel). Nécessite une implémentation manuelle à l'aide de constructions Groovy.
Gestion des Erreurs Blocs post pour les actions globales ou spécifiques aux étapes. Blocs try-catch-finally manuels.
Extensibilité Exploite les bibliothèques partagées pour une logique Groovy complexe. Écrit directement une logique Groovy complexe. Crée souvent des bibliothèques partagées.
Contrôle de l'Agent agent global ou agent au niveau de l'étape. Blocs node, peut définir des agents n'importe où.
Cas d'Utilisation Workflows CI/CD standard, complexité simple à modérée. Workflows hautement dynamiques, complexes et personnalisés ; développement de bibliothèques partagées.
Sensation JSON/YAML Plus proche des langages de configuration. Langage de programmation pur.

Choisir la Bonne Syntaxe

Lorsque vous décidez entre les Pipelines Déclaratifs et Scriptés, tenez compte des facteurs suivants :

  1. Expertise Groovy de l'Équipe : Si votre équipe manque de compétences solides en Groovy, le Déclaratif aura une courbe d'apprentissage beaucoup plus douce et favorisera une adoption plus rapide.
  2. Complexité du Workflow : Pour la plupart des workflows CI/CD standard (construction, test, déploiement), le Déclaratif est parfaitement adéquat et souvent supérieur en raison de sa lisibilité et de ses fonctionnalités intégrées. Pour des tâches hautement dynamiques, conditionnelles ou gourmandes en ressources personnalisées, le Scripté peut être nécessaire.
  3. Maintenabilité et Lisibilité : Les pipelines Déclaratifs sont généralement plus faciles à lire et à maintenir, en particulier pour les grandes organisations avec de nombreux pipelines et développeurs. Cette cohérence réduit la charge cognitive.
  4. Écosystème de Pipeline Existant : Si vous avez des Pipelines Scriptés existants ou un ensemble robuste de bibliothèques partagées construites avec la syntaxe Scriptée, vous pouvez vous y tenir pour des raisons de cohérence, ou migrer progressivement vers le Déclaratif lorsque cela est approprié.
  5. Croissance Future : Les pipelines Déclaratifs sont généralement suffisants et peuvent être étendus avec une logique personnalisée via des bibliothèques partagées, qui sont elles-mêmes généralement écrites en Groovy Scripté. C'est souvent la meilleure approche hybride.

Meilleures Pratiques pour la Prise de Décision

  • Commencez par le Déclaratif : Pour les nouveaux pipelines, optez par défaut pour le Déclaratif. Il couvre la grande majorité des cas d'utilisation CI/CD et favorise la cohérence et la lisibilité.
  • Tirez Parti des Bibliothèques Partagées : Lorsque vous rencontrez une logique répétitive ou complexe dans vos Pipelines Déclaratifs, abstraisez cette logique dans une bibliothèque partagée. Les bibliothèques partagées sont principalement écrites en Groovy Scripté, vous permettant de combiner le meilleur des deux mondes : la structure du Déclaratif et la flexibilité du Scripté.
  • Évitez de Trop Scripté le Déclaratif : Bien que le Déclaratif permette les blocs script, essayez de les garder minimes. Si un bloc script devient trop volumineux ou complexe, c'est un indicateur fort que la logique doit être déplacée dans une fonction de bibliothèque partagée.
  • Envisagez la Migration : Si vous avez des Pipelines Scriptés hérités qui deviennent difficiles à maintenir, envisagez de les refactoriser en syntaxe Déclarative, en déplaçant les parties complexes dans des bibliothèques partagées.

À Retenir

Pour les nouveaux Jenkinsfiles, choisissez le Déclaratif sauf si vous avez une raison concrète de ne pas le faire. Déplacez le Groovy répété ou complexe dans des bibliothèques partagées, et réservez les pipelines entièrement Scriptés pour les workflows qui ne peuvent pas s'intégrer proprement dans les étapes, conditions et actions Déclaratives.