Предыстория: Jenkins работает внутри контейнера Docker, что отлично работает, но по замыслу мы хотим, чтобы все процессы сборки выполнялись внутри контейнеров Docker, чтобы минимизировать количество программного обеспечения, установленного внутри контейнера Jenkins.
Проблема: как создать трехэтапный процесс с использованием двух разных Docker-контейнеров, где все три этапа используют общие файлы?
Шаг 1: Сборка
- сборка npm
Шаг 2: Тест
- тест npm`
Шаг 3: Запустите AWS code-deploy
- aws deploy push --application-name app-name --s3-location s3://my-bucket/app-name --ignore-hidden-files
- aws deploy create-deployment --application-name app-name --s3-location bucket=my-bucket,key=app-name,bundleType=zip --deployment-group-name dg
Как разбить файл Jenkins на несколько этапов и поделиться выводом первого этапа для других этапов?
Простой двухэтапный Jenkinsfile
pipeline {
agent {
docker {
image 'node:10.8.0'
}
}
stages {
stage('Build') {
steps {
sh 'npm install'
}
}
stage('Test') {
steps {
sh 'npm test'
}
}
}
}
Но когда я добавляю третий этап, все становится интереснее, так как я не могу использовать глобальный образ Docker (агент)
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'
}
}
}
}
В приведенном выше примере 'npm test' не проходит, поскольку результаты этапа сборки теряются. И развертывание кода не будет работать, поскольку все артефакты сборки теряются.
Одним из обходных путей для выполнения теста является использование этапа «BuildAndTest», использующего изображение, но при этом теряются некоторые преимущества отдельных шагов.
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'
}
}
}
}
Еще одно (очень уродливое) решение — создать пользовательский образ, в котором установлены и node, и aws, но это означает, что каждый раз при переходе на более новую версию node и/или aws нам придется создавать еще один образ Docker с обновленной версией, хотя на самом деле это совершенно отдельные задачи.
Другое решение — смонтировать общий образ для всех экземпляров, но как создать «временный» образ, который будет доступен только для этой сборки и будет удален после завершения сборки?
решение1
Сразу после того, как я задал вопрос, я нашел статью разработчика Jenkins
https://jenkins.io/blog/2018/07/02/whats-new-declarative-piepline-13x-sequential-stages/
Вот что я придумал
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 допускает несколько этапов внутри декларативного кода, и я не знал о командах «stash/unstash», которые у меня отлично работают.