feat : Add Jenkins pipeline scripts for building Docker images and deploying stacks

This commit is contained in:
Thibault Pouch
2026-03-19 21:02:01 +01:00
commit 741e4043fa
2 changed files with 212 additions and 0 deletions

View File

@@ -0,0 +1,102 @@
pipeline {
agent any
parameters {
string(
name: 'REPO_URL',
defaultValue: 'https://git.crowmate.fr/crowmate/Nest.git',
description: 'URL du repo Gitea à cloner'
)
string(
name: 'BRANCH',
defaultValue: 'main',
description: 'Branche à builder'
)
string(
name: 'IMAGE_TAG',
defaultValue: 'latest',
description: 'Tag des images Docker (ex: latest, v1.0.0)'
)
}
environment {
GITEA_CREDENTIALS_ID = 'gitea-token'
REGISTRY = 'git.crowmate.fr'
REGISTRY_OWNER = 'crowmate'
}
stages {
stage('Clone') {
steps {
cleanWs()
checkout([
$class: 'GitSCM',
branches: [[name: "*/${params.BRANCH}"]],
userRemoteConfigs: [[
url: params.REPO_URL,
credentialsId: env.GITEA_CREDENTIALS_ID
]]
])
echo "✅ Repo cloné"
}
}
stage('Build & Push images') {
steps {
withCredentials([usernamePassword(
credentialsId: env.GITEA_CREDENTIALS_ID,
usernameVariable: 'REGISTRY_USER',
passwordVariable: 'REGISTRY_PASS'
)]) {
sh '''
echo "$REGISTRY_PASS" | docker login ''' + env.REGISTRY + ''' -u "$REGISTRY_USER" --password-stdin
echo "✅ Connecté au registry Gitea"
'''
sh """
echo "🔨 Build nest-api..."
docker build -t ${env.REGISTRY}/${env.REGISTRY_OWNER}/nest-api:${params.IMAGE_TAG} ./nest-backend
echo "🔨 Build nest-front..."
docker build -t ${env.REGISTRY}/${env.REGISTRY_OWNER}/nest-front:${params.IMAGE_TAG} ./nest-front
echo "🔨 Build nest-intra..."
docker build -t ${env.REGISTRY}/${env.REGISTRY_OWNER}/nest-intra:${params.IMAGE_TAG} ./nest-intra
"""
sh """
echo "📤 Push nest-api..."
docker push ${env.REGISTRY}/${env.REGISTRY_OWNER}/nest-api:${params.IMAGE_TAG}
echo "📤 Push nest-front..."
docker push ${env.REGISTRY}/${env.REGISTRY_OWNER}/nest-front:${params.IMAGE_TAG}
echo "📤 Push nest-intra..."
docker push ${env.REGISTRY}/${env.REGISTRY_OWNER}/nest-intra:${params.IMAGE_TAG}
"""
sh "docker logout ${env.REGISTRY}"
}
}
}
}
post {
success {
echo "🎉 Images buildées et pushées avec succès (tag: ${params.IMAGE_TAG})"
}
failure {
echo "💥 Échec du build/push"
}
always {
// Nettoyage des images locales pour ne pas saturer le disque
sh """
docker rmi ${env.REGISTRY}/${env.REGISTRY_OWNER}/nest-api:${params.IMAGE_TAG} || true
docker rmi ${env.REGISTRY}/${env.REGISTRY_OWNER}/nest-front:${params.IMAGE_TAG} || true
docker rmi ${env.REGISTRY}/${env.REGISTRY_OWNER}/nest-intra:${params.IMAGE_TAG} || true
"""
}
}
}

110
Nest/deploy-stack.groovy Normal file
View File

@@ -0,0 +1,110 @@
pipeline {
agent any
parameters {
string(
name: 'REPO_URL',
defaultValue: 'https://git.crowmate.fr/crowmate/Nest.git',
description: 'URL du repo Gitea (pour récupérer le docker-compose.prod.yml)'
)
string(
name: 'BRANCH',
defaultValue: 'main',
description: 'Branche'
)
string(
name: 'STACK_NAME',
defaultValue: 'nest',
description: 'Nom de la stack dans Portainer'
)
string(
name: 'IMAGE_TAG',
defaultValue: 'latest',
description: 'Tag des images à déployer'
)
}
environment {
GITEA_CREDENTIALS_ID = 'gitea-token'
PORTAINER_URL = 'https://docker.devgoblin.fr'
PORTAINER_ENV_ID = '3'
}
stages {
stage('Clone') {
steps {
cleanWs()
checkout([
$class: 'GitSCM',
branches: [[name: "*/${params.BRANCH}"]],
userRemoteConfigs: [[
url: params.REPO_URL,
credentialsId: env.GITEA_CREDENTIALS_ID
]]
])
echo "✅ Repo cloné"
}
}
stage('Validation') {
steps {
script {
if (!fileExists('docker-compose.prod.yml')) {
error("❌ docker-compose.prod.yml introuvable à la racine du repo !")
}
echo "✅ docker-compose.prod.yml trouvé"
}
}
}
stage('Deploy sur Portainer') {
steps {
withCredentials([string(credentialsId: 'portainer-token', variable: 'PORTAINER_TOKEN')]) {
sh '''
COMPOSE_CONTENT=$(base64 -w 0 docker-compose.prod.yml)
# Récupère la liste des stacks
STACKS=$(curl -s -X GET "''' + env.PORTAINER_URL + '''/api/stacks" \
-H "X-API-Key: $PORTAINER_TOKEN")
# Cherche si la stack existe déjà
STACK_ID=$(echo "$STACKS" | jq -r '.[] | select(.Name == "''' + params.STACK_NAME + '''") | .Id')
if [ -n "$STACK_ID" ]; then
echo "🔄 Stack existante (ID: $STACK_ID), mise à jour..."
RESPONSE=$(curl -s -X PUT "''' + env.PORTAINER_URL + '''/api/stacks/$STACK_ID?endpointId=''' + env.PORTAINER_ENV_ID + '''" \
-H "X-API-Key: $PORTAINER_TOKEN" \
-H "Content-Type: application/json" \
-d "{\"stackFileContent\": \"$COMPOSE_CONTENT\", \"prune\": true, \"pullImage\": true}")
else
echo "🚀 Création de la stack ''' + params.STACK_NAME + '''..."
RESPONSE=$(curl -s -X POST "''' + env.PORTAINER_URL + '''/api/stacks/create/standalone/string?endpointId=''' + env.PORTAINER_ENV_ID + '''" \
-H "X-API-Key: $PORTAINER_TOKEN" \
-H "Content-Type: application/json" \
-d "{\"name\": \"''' + params.STACK_NAME + '''\", \"stackFileContent\": \"$COMPOSE_CONTENT\"}")
fi
# Vérifie si la réponse contient une erreur
if echo "$RESPONSE" | jq -e '.message' > /dev/null 2>&1; then
echo "❌ Erreur Portainer : $(echo $RESPONSE | jq -r '.message')"
exit 1
fi
echo "✅ Stack déployée avec succès !"
'''
}
}
}
}
post {
success {
echo "🎉 Stack '${params.STACK_NAME}' déployée sur Portainer (tag: ${params.IMAGE_TAG})"
}
failure {
echo "💥 Échec du déploiement de la stack '${params.STACK_NAME}'"
}
}
}