Aller au contenu principal

Pipelines Jenkins


Introduction aux Pipelines

Un pipeline Jenkins est une suite d'étapes automatisées définies en code Groovy.


Pipeline Déclaratif vs Scripté

Déclaratif (Recommandé)

Structure prédéfinie, plus simple à apprendre.

pipeline {
agent any
stages {
stage('Build') {
steps {
sh 'mvn clean package'
}
}
}
}

Scripté

Plus flexible, syntaxe Groovy pure.

node {
stage('Build') {
sh 'mvn clean package'
}
}

Comparaison

AspectDéclaratifScripté
SyntaxeStructuréeLibre
FlexibilitéMoyenneHaute
ValidationÀ l'écritureÀ l'exécution
ApprentissageFacileMoyen
Recommandé✅ OuiPour cas complexes

Structure d'un Pipeline Déclaratif

pipeline {
// Où exécuter le pipeline
agent any

// Variables d'environnement
environment {
APP_NAME = 'my-app'
VERSION = '1.0.0'
}

// Options globales
options {
timeout(time: 30, unit: 'MINUTES')
buildDiscarder(logRotator(numToKeepStr: '10'))
}

// Paramètres d'entrée
parameters {
string(name: 'BRANCH', defaultValue: 'main')
choice(name: 'ENV', choices: ['dev', 'prod'])
}

// Déclencheurs
triggers {
pollSCM('H/5 * * * *')
}

// Étapes du pipeline
stages {
stage('Build') {
steps {
sh 'echo "Building ${APP_NAME}"'
}
}

stage('Test') {
steps {
sh 'npm test'
}
}

stage('Deploy') {
steps {
sh 'kubectl apply -f k8s/'
}
}
}

// Actions post-pipeline
post {
always {
cleanWs()
}
success {
slackSend message: "Build réussi!"
}
failure {
mail to: '[email protected]',
subject: "Build échoué: ${JOB_NAME}",
body: "Vérifier: ${BUILD_URL}"
}
}
}

Agent

L'agent définit où le pipeline s'exécute.

Types d'agents

// N'importe quel agent disponible
agent any

// Pas d'agent (pour stages individuels)
agent none

// Agent avec label spécifique
agent {
label 'linux'
}

// Agent Docker
agent {
docker {
image 'node:18'
args '-v /tmp:/tmp'
}
}

// Agent Kubernetes
agent {
kubernetes {
yaml '''
apiVersion: v1
kind: Pod
spec:
containers:
- name: maven
image: maven:3.8-openjdk-17
command: ['sleep', 'infinity']
'''
}
}

// Dockerfile dans le repo
agent {
dockerfile {
filename 'Dockerfile.build'
dir 'docker'
args '-v /tmp:/tmp'
}
}

Agent par stage

pipeline {
agent none

stages {
stage('Build') {
agent {
docker { image 'maven:3.8' }
}
steps {
sh 'mvn clean package'
}
}

stage('Test') {
agent {
docker { image 'node:18' }
}
steps {
sh 'npm test'
}
}

stage('Deploy') {
agent {
label 'kubernetes'
}
steps {
sh 'kubectl apply -f k8s/'
}
}
}
}

Stages et Steps

Stage

Un stage est une phase logique du pipeline.

stages {
stage('Checkout') {
steps {
checkout scm
}
}

stage('Build') {
steps {
sh 'mvn clean package -DskipTests'
}
}

stage('Unit Tests') {
steps {
sh 'mvn test'
}
}

stage('Integration Tests') {
steps {
sh 'mvn verify -Pintegration'
}
}

stage('Deploy') {
steps {
sh './deploy.sh'
}
}
}

Steps courants

steps {
// Exécuter un script shell
sh 'echo "Hello"'
sh '''
echo "Multi-line"
echo "Script"
'''

// Windows batch
bat 'echo Hello'

// PowerShell
powershell 'Write-Host "Hello"'

// Checkout Git
checkout scm
git branch: 'main', url: 'https://github.com/user/repo.git'

// Afficher un message
echo 'Building...'

// Archiver des artifacts
archiveArtifacts artifacts: 'target/*.jar'

// Publier les résultats de tests
junit 'target/surefire-reports/*.xml'

// Envoyer un email
mail to: '[email protected]',
subject: 'Build',
body: 'Done'

// Slack
slackSend channel: '#builds',
message: "Build ${BUILD_NUMBER} terminé"

// Attendre une approbation
input message: 'Déployer en production?'

// Définir une variable
script {
env.MY_VAR = 'value'
}
}

Parallélisation

Stages parallèles

pipeline {
agent any

stages {
stage('Build') {
steps {
sh 'mvn clean package'
}
}

stage('Tests') {
parallel {
stage('Unit Tests') {
steps {
sh 'mvn test'
}
}
stage('Integration Tests') {
steps {
sh 'mvn verify'
}
}
stage('E2E Tests') {
agent {
docker { image 'cypress/included' }
}
steps {
sh 'cypress run'
}
}
}
}

stage('Deploy') {
steps {
sh 'kubectl apply -f k8s/'
}
}
}
}

Matrix

pipeline {
agent none

stages {
stage('Test Matrix') {
matrix {
axes {
axis {
name 'PLATFORM'
values 'linux', 'windows', 'mac'
}
axis {
name 'NODE_VERSION'
values '16', '18', '20'
}
}

excludes {
exclude {
axis {
name 'PLATFORM'
values 'mac'
}
axis {
name 'NODE_VERSION'
values '16'
}
}
}

stages {
stage('Test') {
agent {
label "${PLATFORM}"
}
steps {
sh "nvm use ${NODE_VERSION} && npm test"
}
}
}
}
}
}
}

Conditions

When

stages {
stage('Build') {
steps {
sh 'mvn package'
}
}

stage('Deploy to Dev') {
when {
branch 'develop'
}
steps {
sh 'kubectl apply -f k8s/dev/'
}
}

stage('Deploy to Prod') {
when {
allOf {
branch 'main'
environment name: 'DEPLOY', value: 'true'
}
}
steps {
sh 'kubectl apply -f k8s/prod/'
}
}

stage('Nightly Build') {
when {
triggeredBy 'TimerTrigger'
}
steps {
sh 'mvn clean install'
}
}

stage('PR Build') {
when {
changeRequest()
}
steps {
sh 'mvn verify'
}
}
}

Conditions disponibles

when {
// Branche spécifique
branch 'main'
branch pattern: 'release-*', comparator: 'GLOB'

// Tag
tag 'v*'

// Environnement
environment name: 'ENV', value: 'prod'

// Expression Groovy
expression { return params.DEPLOY == true }

// Fichier modifié
changeset '**/*.java'

// Pull Request
changeRequest()
changeRequest target: 'main'

// Combinaisons
allOf {
branch 'main'
environment name: 'DEPLOY', value: 'true'
}

anyOf {
branch 'main'
branch 'develop'
}

not {
branch 'feature/*'
}
}

Gestion des erreurs

Try-Catch

pipeline {
agent any

stages {
stage('Deploy') {
steps {
script {
try {
sh 'kubectl apply -f k8s/'
} catch (Exception e) {
echo "Deployment failed: ${e.message}"
sh 'kubectl rollback'
throw e
}
}
}
}
}
}

catchError

stage('Tests') {
steps {
catchError(buildResult: 'UNSTABLE', stageResult: 'FAILURE') {
sh 'npm test'
}
}
}

Retry et Timeout

stage('Deploy') {
steps {
retry(3) {
timeout(time: 5, unit: 'MINUTES') {
sh 'kubectl apply -f k8s/'
}
}
}
}

Post Actions

pipeline {
agent any

stages {
stage('Build') {
steps {
sh 'mvn package'
}
}
}

post {
// Toujours exécuté
always {
junit 'target/surefire-reports/*.xml'
archiveArtifacts artifacts: 'target/*.jar', fingerprint: true
cleanWs()
}

// Si succès
success {
slackSend color: 'good', message: "Build #${BUILD_NUMBER} réussi"
}

// Si échec
failure {
slackSend color: 'danger', message: "Build #${BUILD_NUMBER} échoué"
mail to: '[email protected]',
subject: "FAILED: ${JOB_NAME} #${BUILD_NUMBER}",
body: "Check: ${BUILD_URL}"
}

// Si instable (tests échoués)
unstable {
slackSend color: 'warning', message: "Build instable"
}

// Si changement de statut
changed {
echo 'Le statut du build a changé'
}

// Si revenu à la normale
fixed {
slackSend color: 'good', message: "Build réparé!"
}

// Si annulé
aborted {
echo 'Build annulé'
}
}
}

Résumé

ConceptDescription
PipelineWorkflow CI/CD en code
DéclaratifSyntaxe structurée (recommandé)
ScriptéGroovy pur (flexible)
StagePhase logique
StepAction unitaire
AgentOù s'exécute le build
WhenConditions d'exécution
PostActions post-build

← Interface et Jobs | Jenkinsfile →