Le Jenkinsfile déclaratif est la syntaxe recommandée depuis Jenkins 2.x. Il définit le pipeline CI/CD en Groovy avec une structure stricte et lisible. Il doit être versionné dans le dépôt Git du projet.


Structure globale

pipeline {
    agent { ... }          // où exécuter
    environment { ... }    // variables globales
    options { ... }        // comportement du pipeline
    parameters { ... }     // paramètres utilisateur
    triggers { ... }       // déclencheurs automatiques
 
    stages {
        stage('Nom') {
            when { ... }   // condition d'exécution
            steps { ... }  // commandes
        }
    }
 
    post {                 // actions post-build
        success { ... }
        failure { ... }
        always  { ... }
    }
}

agent — où s’exécute le build

agent any                          // premier agent disponible
agent none                         // pas d'agent global (défini par stage)
agent { label 'linux && docker' }  // agent avec ces labels
agent { docker { image 'node:20' } }       // container Docker
agent { kubernetes { yaml '...' } }        // Pod Kubernetes

environment — variables et secrets

environment {
    APP_NAME    = 'mon-api'
    REGISTRY    = 'registry.example.com'
    // Injection de credentials Jenkins
    SONAR_TOKEN = credentials('sonar-token-id')         // string secret
    DOCKER_CRED = credentials('docker-registry-creds')  // user/pass → DOCKER_CRED_USR + DOCKER_CRED_PSW
}

options — comportement global

options {
    buildDiscarder(logRotator(numToKeepStr: '15'))  // garder 15 builds
    timeout(time: 45, unit: 'MINUTES')              // timeout global
    timestamps()                                    // horodatages dans les logs
    disableConcurrentBuilds()                       // pas de builds parallèles sur la même branche
    retry(2)                                        // relancer 2 fois en cas d'échec
    skipStagesAfterUnstable()                       // stop si un stage devient UNSTABLE
}

parameters — paramètres utilisateur

parameters {
    string(name: 'BRANCH',      defaultValue: 'main',        description: 'Branche à builder')
    choice(name: 'ENV',         choices: ['dev','qa','prod'], description: 'Environnement cible')
    booleanParam(name: 'SKIP_TESTS', defaultValue: false,    description: 'Passer les tests ?')
    password(name: 'API_KEY',   defaultValue: '',             description: 'Clé API')
}
// Utilisation : ${params.BRANCH}

stages — étapes du pipeline

stages {
    stage('Checkout') {
        steps {
            git branch: "${params.BRANCH}", url: 'https://github.com/org/projet.git'
        }
    }
 
    stage('Tests') {
        parallel {                         // exécution en parallèle
            stage('Unit Tests') {
                steps { sh 'mvn test' }
                post { always { junit '**/target/surefire-reports/*.xml' } }
            }
            stage('Lint') {
                steps { sh 'mvn checkstyle:check' }
            }
        }
    }
 
    stage('Build & Push') {
        when { branch 'main' }             // seulement sur main
        steps {
            script {
                def tag = "${REGISTRY}/mon-app:${env.BUILD_NUMBER}"
                sh "docker build -t ${tag} ."
                withCredentials([usernamePassword(
                    credentialsId: 'docker-cred',
                    usernameVariable: 'USER',
                    passwordVariable: 'PASS'
                )]) {
                    sh "echo ${PASS} | docker login ${REGISTRY} -u ${USER} --password-stdin"
                    sh "docker push ${tag}"
                }
            }
        }
    }
 
    stage('Deploy') {
        when {
            allOf {
                branch 'main'
                not { changeRequest() }    // pas une Pull Request
            }
        }
        input {                            // validation manuelle avant prod
            message "Déployer en production ?"
            ok "Go !"
            parameters { choice(name: 'CONFIRM', choices: ['yes','no'], description: '') }
        }
        steps {
            sh './scripts/deploy.sh ${params.ENV} ${BUILD_NUMBER}'
        }
    }
}

post — actions après le build

post {
    success {
        slackSend channel: '#ci', color: 'good',
            message: "✅ ${currentBuild.fullDisplayName} — ${env.BUILD_URL}"
        archiveArtifacts artifacts: '**/target/*.jar', fingerprint: true
    }
    failure {
        slackSend channel: '#ci', color: 'danger',
            message: "❌ ${currentBuild.fullDisplayName} — ${env.BUILD_URL}"
        emailext to: 'team@example.com', subject: "ECHEC: ${env.JOB_NAME}", body: '${BUILD_LOG}'
    }
    unstable {
        slackSend channel: '#ci', color: 'warning',
            message: "⚠️ ${currentBuild.fullDisplayName} — tests instables"
    }
    always {
        publishCoverage adapters: [coberturaAdapter('**/coverage.xml')]
        cleanWs()   // nettoyage du workspace
    }
}

Variables automatiques utiles

VariableValeur
env.BUILD_NUMBERNuméro du build courant
env.JOB_NAMENom du job
env.BRANCH_NAMEBranche Git (Multibranch)
env.BUILD_URLURL du build dans l’UI
currentBuild.resultSUCCESS, FAILURE, UNSTABLE
currentBuild.durationDurée en ms
currentBuild.fullDisplayNamejob-name #42

En relation avec