Continuous Integration mit Jenkins

Im September 2016 kündigte ein Blogpost auf jenkins.io Blue Ocean und damit die deklarativen Pipelines an, mit denen auch der build- und deployment Prozess im Repository verwaltet werden kann. Mittlerweile sind die entsprechenden Plugins ein wenig abgehangen und ergänzende Plugins wurden entwickelt bzw. die Kompatibilität hergestellt.

Travis hat das .travis.yml, GitLab das .gitlab-ci.yml, BITRISE das bitrise.yml und Drone das .drone.yml. Nun hat auch Jenkins mit dem Jenkinsfile nachgezogen. Neben der Verwaltung des Prozesses im CVS ermöglicht ein Jenkinsfile auch das schnelle Kopieren zwischen Projekten.

Team Projekte

Nach der Einrichtung eines Jenkins Servers steht man zu allererst vor der Frage was für ein Projekt man einrichten sollte. Für die iOS Entwicklung hat sich lange das “Free Style” Projekt angeboten. Seit dem Update gibt es das Bitbucket Branch Source Plugin bzw. GitHub Branch Source Plugin mit denen sich vor allem Team Folder anlegen lassen.

Bitbucket Team/Project

Einmal eingerichtet sucht Jekins in regelmäßigen Abständen in allen Repositories des Teams nach Branches mit einem Jenkinsfile und richtet für diese Repositories Projekte und für die Branches Jobs ein. Neue Projekte müssen somit nicht mehr mühsam im Jenkins angelegt werden. Es reicht ein Jekinsfile in den Hauptordner des Projektes zu legen. Jenkins legt dabei auch für Pull Requests einen Job an und führt somit einen Commit sowohl im Kontext des Branches, als auch im Kontext des Pull Requests aus. Umgehen lässt sich das über die Option Discover branches oder Automatic branch project triggering.

Discover branches Automatic branch project triggering

Blue Ocean

Blue Ocean ist die neue Jenkins Oberfläche, die parallel zum alten Interface existiert. Nicht alles wird in Blue Ocean abgebildet, aber vor allem die tägliche Arbeit wird darin abgebildet.

Durch das Team Projekt legt Jenkins für jeden Branch einen eigenen Job an. Diese werden in dem Projekt samt ihres Zustandes aufgelistet.

Liste der Jobs in Blue Ocean Jobs

Jenkinsfile

Die Build Pipeline wird in einem Jenkinsfile direkt im root Verzeichnis des Repositories angelegt. Im Jenkinsfile wird der Job konfiguriert und die entsprechenden Stages definiert. Um bei einem Buildfehler schneller das Problem eingrenzen zu können empfiehlt es sich den Prozess in mehrere Stages zu verteilen die jeweils einen Bereich abdecken. Bspw. checkout, prepare, tests, codestyle, deployment, archive.

Alle Aufgaben (abgesehen von Konfigurationen) müssen auf einem Node ausgeführt werden. Das kann der Jenkins Server selbst sein. Um besser skalieren zu können ist es ratsam zusätzliche Systeme einzurichten, die sich mit dem Jenkins Server verbinden und die offenen Aufgaben durchführen. Jedem Node können Tags vergeben werden, die erfüllten Voraussetzungen entsprechen. Ein Tag könnte macos und einer linux sein. Oder man wählt die Tags feiner, bspw xcode9, nodejs, ruby2.1.6.

Ein Jenkinsfile könnte dann so aussehen.

#!groovy

// Dies definiert die Anzahl der zu speichernden builds
properties([buildDiscarder(logRotator(artifactDaysToKeepStr: '30', artifactNumToKeepStr: '50', daysToKeepStr: '30', numToKeepStr: '50'))])

// Diese Stages benötigen einen Node mit Xcode 8 und Fastlane
node('xcode8 && fastlane') {

  // Aktiviert das Ansi Color Plugin für die folgenden Stages
  wrap([$class: 'AnsiColorBuildWrapper', 'colorMapName': 'XTerm', 'defaultFg': 1, 'defaultBg': 2]) {

    stage('Checkout') {
      checkout scm
    }

    stage('Bundle install') {
      sh 'bundle update'
      sh 'bundle install'
    }

    stage('Tests') {
      sh "killall Simulator || true"
      sh "SNAPSHOT_FORCE_DELETE=yes snapshot reset_simulators"
      sh 'fastlane test sdk:"9.3" device:"iPhone 5s"'
      sh 'fastlane test sdk:"10.2" device:"iPhone 5s"'
      publishHTML([allowMissing: true, alwaysLinkToLastBuild: false, keepAll: false, reportDir: 'build/reports/', reportFiles: 'report.html', reportName: 'HTML Test Report'])
      junit allowEmptyResults: true, testResults: 'build/reports/report.junit'
      archiveArtifacts allowEmptyArchive: true, artifacts: 'build/reports/*', onlyIfSuccessful: true
    }
  }
}

Das Ansi Color Plugin bringt Unterstützung für ANSI Escape Zeichen mit und verbessert die Darstellung der Konsolen Ausgabe.

Für jeden erfolgen Build kann die Pipeline geöffnet werden und Details zu jeder Stage und jedem Schritt untersucht werden. An dieser Stelle findet man auch Testergebnisse, archivierte Artefakte und kann ggf. einen Build neu starten.

Ansicht eines einzelnen Jobs in Blue Ocean Jobs