Antecedentes: Jenkins se ejecuta dentro de un contenedor acoplable, lo cual funciona muy bien, pero por diseño queremos que todos los procesos de compilación se ejecuten dentro de contenedores acoplables para minimizar el software instalado dentro del contenedor Jenkins.
Problema: ¿Cómo creo un proceso de 3 etapas usando dos contenedores Docker diferentes, donde los tres pasos comparten archivos?
Paso 1: construir
- compilación npm
Paso 2: prueba
- prueba npm`
Paso 3: Ejecute la implementación de código de AWS
- aws implementar push --nombre-aplicación nombre-aplicación --ubicación-s3 s3://mi-bucket/nombre-aplicación --ignore-archivos-ocultos
- aws implementar crear-implementación --nombre-aplicación nombre-aplicación --s3-ubicación depósito=mi-depósito,clave=nombre-aplicación,bundleType=zip --deployment-grupo-nombre dg
¿Cómo divido el archivo Jenkins en varias etapas y comparto el resultado de la primera etapa para las otras etapas?
Archivo Jenkins simple de dos etapas
pipeline {
agent {
docker {
image 'node:10.8.0'
}
}
stages {
stage('Build') {
steps {
sh 'npm install'
}
}
stage('Test') {
steps {
sh 'npm test'
}
}
}
}
Pero, cuando agrego en la tercera etapa, las cosas se vuelven más interesantes, ya que no puedo usar una imagen acoplable global (agente).
pipeline {
agent none
stages {
stage('Build') {
agent {
docker { image 'node:10.8.0' }
}
steps {
sh 'npm install'
}
}
stage('Test') {
agent {
docker { image 'node:10.8.0' }
}
steps {
sh 'npm test'
}
}
stage('Deploy') {
agent {
docker { image 'coreos/awscli' }
}
steps {
sh 'echo "Deploying to AWS"'
sh 'aws help'
}
}
}
}
En lo anterior, la 'prueba npm' falla porque se pierden los resultados de la etapa de compilación. Y la implementación del código no funcionaría porque todos los artefactos de compilación se pierden.
Una solución alternativa para que la prueba funcione es tener una etapa 'BuildAndTest' que utilice una imagen, pero esto pierde algunas de las ventajas de los pasos separados.
pipeline {
agent none
stages {
stage('Build And Test') {
agent {
docker { image 'node:10.8.0' }
}
steps {
sh 'npm install'
sh 'npm test'
}
}
stage('Deploy') {
agent {
docker { image 'coreos/awscli' }
}
steps {
sh 'echo "Deploying to AWS"'
sh 'aws help'
}
}
}
}
Otra solución (súper fea) es crear una imagen personalizada que tenga instalados node y aws, pero eso significa que cada vez que migramos a una versión más nueva de node y/o aws, tenemos que crear otra imagen de Docker con la versión actualizada. , cuando en realidad son tareas completamente separadas.
La otra solución es montar una imagen compartida entre todas las instancias, pero ¿cómo creo una imagen "temporal" que solo se comparte para esta compilación y que se elimina una vez que se completa la compilación?
Respuesta1
Justo después de publicar la pregunta, encontré un artículo de un desarrollador de Jenkins.
https://jenkins.io/blog/2018/07/02/whats-new-declarative-piepline-13x-sequential-stages/
Esto es lo que se me ocurrió
pipeline {
agent none
stages {
stage('Build and Test') {
agent {
docker 'node:10.8.0'
}
stages {
stage('Build') {
steps {
sh 'npm install'
}
}
stage('Test') {
steps {
sh 'npm test'
}
}
}
post {
success {
stash name: 'artifacts', includes: "node_modules/**/*"
}
}
}
stage('Deploy') {
agent {
docker 'coreos/awscli'
}
steps {
unstash 'artifacts'
sh 'echo "Deploying to AWS"'
sh 'aws help'
}
}
}
}
Jenkins ahora permite múltiples etapas dentro del declarativo, y no conocía los comandos 'stash/unstash', que funcionan muy bien para mí.