Hintergrund: Jenkins läuft in einem Docker-Container, was gut funktioniert, aber wir möchten, dass alle Build-Prozesse standardmäßig in Docker-Containern ausgeführt werden, um die im Jenkins-Container installierte Software zu minimieren.
Problem: Wie erstelle ich einen dreistufigen Prozess mit zwei verschiedenen Docker-Containern, bei dem alle drei Schritte Dateien gemeinsam nutzen?
Schritt 1: Erstellen
- NPM-Build - Ein Leitfaden für Entwickler
Schritt 2: Testen
- npm-Test`
Schritt 3: AWS Code-Deploy ausführen
- aws deploy push --Anwendungsname App-Name --S3-Standort s3://mein-Bucket/App-Name --ignore-hidden-files
- aws deploy create-deployment --Anwendungsname App-Name --S3-Standort Bucket=mein Bucket, Schlüssel=App-Name, BundleType=Zip --Bereitstellungsgruppenname dg
Wie teile ich die Jenkins-Datei in mehrere Phasen auf und gebe die Ausgabe der ersten Phase an die anderen Phasen weiter?
Einfaches zweistufiges Jenkinsfile
pipeline {
agent {
docker {
image 'node:10.8.0'
}
}
stages {
stage('Build') {
steps {
sh 'npm install'
}
}
stage('Test') {
steps {
sh 'npm test'
}
}
}
}
Aber wenn ich die dritte Phase hinzufüge, wird es interessanter, da ich kein globales Docker-Image (Agent) verwenden kann.
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'
}
}
}
}
Im obigen Beispiel schlägt der npm-Test fehl, da die Ergebnisse der Build-Phase verloren gehen. Und die Codebereitstellung würde nicht funktionieren, da alle Build-Artefakte verloren gehen.
Eine Problemumgehung, um den Test zum Laufen zu bringen, besteht darin, eine „BuildAndTest“-Phase zu haben, die ein Image verwendet. Dadurch gehen jedoch einige der Vorteile separater Schritte verloren.
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'
}
}
}
}
Eine andere (sehr hässliche) Lösung besteht darin, ein benutzerdefiniertes Image zu erstellen, auf dem sowohl Node als auch AWS installiert sind. Das bedeutet aber, dass wir jedes Mal, wenn wir auf eine neuere Version von Node und/oder AWS migrieren, ein weiteres Docker-Image mit der aktualisierten Version erstellen müssen, obwohl es sich in Wirklichkeit um völlig unterschiedliche Aufgaben handelt.
Die andere Lösung besteht darin, ein gemeinsames Image für alle Instanzen bereitzustellen. Wie erstelle ich jedoch ein „temporäres“ Image, das nur für diesen Build gemeinsam genutzt wird und nach Abschluss des Builds gelöscht wird?
Antwort1
Gleich nachdem ich die Frage gepostet hatte, fand ich einen Artikel von einem Jenkins-Entwickler
https://jenkins.io/blog/2018/07/02/whats-new-declarative-piepline-13x-sequential-stages/
Das ist, was mir eingefallen ist
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 ermöglicht jetzt mehrere Phasen innerhalb der Deklaration, und ich kannte die Befehle „stash/unstash“ nicht, die bei mir hervorragend funktionieren.