From 3d255bdea2b130aa85a27523a2ad2c00f7f7fd0e Mon Sep 17 00:00:00 2001 From: Thibault Pouch Date: Thu, 19 Mar 2026 21:06:09 +0100 Subject: [PATCH] feat: Enhance stack deployment process in Jenkins pipeline with improved payload handling and validation --- Nest/deploy-stack.groovy | 114 ++++++++++++++++++++++++++++----------- 1 file changed, 83 insertions(+), 31 deletions(-) diff --git a/Nest/deploy-stack.groovy b/Nest/deploy-stack.groovy index 660a3c7..af2014d 100644 --- a/Nest/deploy-stack.groovy +++ b/Nest/deploy-stack.groovy @@ -58,45 +58,97 @@ pipeline { } } - stage('Deploy to Portainer') { + stage('Prepare compose payload') { + steps { + sh ''' + base64 -w 0 docker-compose.prod.yml > compose-content.b64 + echo "Compose payload prepared" + ''' + } + } + + stage('Fetch Portainer stacks') { steps { withCredentials([string(credentialsId: 'portainer-token', variable: 'PORTAINER_TOKEN')]) { sh ''' - COMPOSE_CONTENT=$(base64 -w 0 docker-compose.prod.yml) - - # Get the list of stacks - STACKS=$(curl -s -X GET "''' + env.PORTAINER_URL + '''/api/stacks" \ - -H "X-API-Key: $PORTAINER_TOKEN") - - # Check whether the stack already exists - STACK_ID=$(echo "$STACKS" | jq -r '.[] | select(.Name == "''' + params.STACK_NAME + '''") | .Id') - - if [ -n "$STACK_ID" ]; then - echo "Existing stack found (ID: $STACK_ID), updating..." - 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 "Creating 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 - - # Check whether the response contains an error - if echo "$RESPONSE" | jq -e '.message' > /dev/null 2>&1; then - echo "Portainer error: $(echo $RESPONSE | jq -r '.message')" - exit 1 - fi - - echo "Stack deployed successfully" + curl -s -X GET "''' + env.PORTAINER_URL + '''/api/stacks" \ + -H "X-API-Key: $PORTAINER_TOKEN" > portainer-stacks.json + echo "Portainer stacks fetched" ''' } } } + stage('Resolve target stack') { + steps { + script { + env.STACK_ID = sh( + script: "jq -r '.[] | select(.Name == \"${params.STACK_NAME}\") | .Id' portainer-stacks.json | head -n 1", + returnStdout: true + ).trim() + + if (env.STACK_ID) { + echo "Existing stack found (ID: ${env.STACK_ID})" + } else { + echo "Stack does not exist and will be created" + } + } + } + } + + stage('Update existing stack') { + when { + expression { return env.STACK_ID?.trim() } + } + steps { + withCredentials([string(credentialsId: 'portainer-token', variable: 'PORTAINER_TOKEN')]) { + sh ''' + COMPOSE_CONTENT=$(cat compose-content.b64) + + 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}" > portainer-response.json + + echo "Stack updated" + ''' + } + } + } + + stage('Create new stack') { + when { + expression { return !env.STACK_ID?.trim() } + } + steps { + withCredentials([string(credentialsId: 'portainer-token', variable: 'PORTAINER_TOKEN')]) { + sh ''' + COMPOSE_CONTENT=$(cat compose-content.b64) + + 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\"}" > portainer-response.json + + echo "Stack created" + ''' + } + } + } + + stage('Validate Portainer response') { + steps { + sh ''' + if jq -e '.message' portainer-response.json > /dev/null 2>&1; then + echo "Portainer error: $(jq -r '.message' portainer-response.json)" + exit 1 + fi + + echo "Stack deployed successfully" + ''' + } + } + } post {