Blog

Rock CI mit Docker und Jenkins 2

Für Jenkins liegt aktuell die finale Version 2.0 vor, und es hat sich einiges getan: Die neue Version kommt mit einer höheren Zugriffssicherheit, einer verbesserten Plug-in-Auswahl sowie einem überarbeiteten Job-Konfigurationsformular daher. Letzteres bietet bei der Anzeige komplexer Formulare nun eine visuell klarere Struktur; zudem wurden dem Formular mehrere Registerkarten hinzugefügt, um die Navigation zu beschleunigen.
Auch der Weiterentwicklung der Plug-in-Auswahl des Setup-Dialogs haben sich die Jenkins-Macher gewidmet. Ab sofort werden das Git-Plug-in und weitere populäre Erweiterungen  standardmäßig mitinstalliert. Im Hinblick auf das Pipeline-Plug-in wurden die ergänzende Module Pipeline Stage View und GitHub Organization Folder einbezogen. Das Plug-in Pipeline Stage View erlaubt einen schnellen Überblick über die Continuous-Delivery-Pipeline, während GitHub Organization Folder automatisch nach GitHub-Repositorien mit Pipeline-Definitionen sucht und Jobs für diese einrichtet. Dabei kann das Build-Skript für den Job im Versionskontrollsystems auch mit hinterlegt werden und es gibt sehr gute Unterstützung für mehrere Branches, ohne dass separate Jobs angelegt werden müssen.

CD_PipelineView

Ein Beispiel ist hier zu finden.Eine Übersicht über sämtliche bislang bekannten Highlights von Jenkins 2.0 ist auf der entsprechenden Unterseite zu finden; auf dieser steht zudem der neue Build zum Download bereit.

Das Buildskript wird in einer Groovy-DSL geschrieben:

node {
   env.JAVA_HOME = tool 'jdk-8-oracle'
   def mvnHome = tool 'Maven 3.3.1'
   env.PATH="${env.JAVA_HOME}/bin:${mvnHome}/bin:${env.PATH}"
   
   stage 'Checkout'
   git url: 'https://github.com/holisticon/continous-delivery-demo.git'

   stage 'Build'
   sh "${mvnHome}/bin/mvn clean package"
   
   stage 'Unit-Tests'
   sh "${mvnHome}/bin/mvn test"
   
   stage 'Integration-Tests'
   wrap([$class: 'Xvfb']) {
        sh "export DOCKER_HOST=tcp://localhost:4243 && ${mvnHome}/bin/mvn -Pdocker clean verify"
   }
   
   step([
       $class: 'ArtifactArchiver', 
       artifacts: '**/target/*.jar', 
       fingerprint: true
    ])
   step([
       $class: 'JUnitResultArchiver', 
       testResults: 'angular-spring-boot-webapp/target/surefire-reports/TEST*.xml,target/failsafe-reports/TEST*.xml'
   ])
   publishHTML(target: [
       reportDir:'angular-spring-boot-webapp/target/site/serenity/',
       reportFiles:'index.html',
       reportName:'Serenity Test Report', 
       keepAll:true, 
       alwaysLinkToLastBuild:true,
       allowMissing: false
    ])
}

Bei der Erstellung hilft der Snippet-Editor:

CD_SnippetGenerator

Ansonsten gibt es auf der Github-Seite von Jenkins-CI und auf der Pipeline-Plugin-Seite weitere Beispiele.

Außerdem wurde auch eine Multibranch-Jobkonfiguration im neuen Jenkins angelegt, die es erlaubt, den Job in mehreren Branches auszuführen. Das ist besonders interessant, wenn man mit Release-Branches arbeitet und Hotfixes in derselben Pipeline testen will. Bisher musste dafür entweder ein separater Jenkins-Jobs angelegt oder aber mit Parametern gearbeitet werden. Gerade bei langlebiger Software kann sich aber durchaus der Build- und/oder Deploy-Prozess zwischen Releases ändern. Dadurch, dass man die Job-Konfiguration in Form einer DSL mit eincheckt, wird nun Abhilfe geschaffen. Ein passendes Beispiel ist hier zu finden. Interessant für größere Umgebungen ist auch das Feature, die DSL um eigene Bibliotheksfunktionen zu erweitern. Diese können natürlich auch in einem Versionskontrollsystems hinterlegt werden.

Den gesamten Prozess der Testautomatisierung kann man zudem auch noch mit Docker kombinieren. Dabei werden Integrations-Tests gegen ein Docker-Image ausgeführt, das im normalen Build erstellt, gestartet und wieder gestoppt wird. Dazu nutzt man ein Maven-Plugin, das es auch erlaubt, die Orchestrierung mehrerer Images inkl. Verlinkung und Ersetzung von Build-Artefakten zu nutzen:

<plugin>
    <groupId>com.alexecollins.docker</groupId>
    <artifactId>docker-maven-plugin</artifactId>
    <configuration>
        <prefix>ngspring</prefix>
        <!-- (optional) remove images created by Dockerfile (default true) -->
        <removeIntermediateImages>true</removeIntermediateImages>
        <!-- (optional) do/do not cache images (default false), disable to get the freshest images -->
        <cache>true</cache>
    </configuration>
    <executions>
        <execution>
            <id>docker-prepare</id>
            <goals>
                <goal>stop</goal>
                <goal>clean</goal>
                <goal>package</goal>
                <goal>start</goal>
            </goals>
            <phase>package</phase>
        </execution>
    </executions>
</plugin>

Neben dem Dockerfile benötigt man eine YAML-Datei für die dynamischen Anteile:

# additional data require to create the Docker image
packaging:
  # files to add to the build, usually used with ADD in the Dockerfile
  add:
    - target/${project.build.finalName}.jar
# optional list of port to expose on the host
ports:
  - ${server.port}
healthChecks:
  pings:
    - url: http://localhost:${server.port}/
      timeout: 60000
links:
  - mysql:db
# how long in milliseconds to sleep after start-up (default 0)
sleep: 5000
# tag to use for images
tag: ngspring/app:${project.version}

So lassen sich bequem die einzelnen Server beschreiben und für das Testen nutzen. Die Container werden dann vom Plugin im Maven-Lifecycle erstellt und auch wieder gelöscht.
Das gesamte Beispiel ist auf GitHub verfügbar. Man kann sich zum Experimentieren mit Jenkins 2 auch ein Docker-Image laden und selbst loslegen

 

Über den Autor

Antwort hinterlassen