Continuous Deployment mit git, codeship.io und nightwatch.js bei youhear.it

Im November sprechen Christof und ich von youhear.it auf der Webcon über unsere Entwicklungsumgebung und Prozesse. Heute möchte ich jedoch bereits einen kleinen Vorgeschmack geben und einen wichtigen Teil unseres Entwicklungsprozesses vorstellen: Den Deployment-Prozess.

Wir versuchen in der Entwicklung von youhear.it möglichst nah an einen kontinuierlichen Prozess ranzukommen. Die bekanntesten Vertreter sind Continuous Integration (CI) und Continuous Deployment (CD). Beim Continuous Deployment geht es darum, automatisiert und ohne manuelle Eingriffe Änderungen, Bugfixes und neue Features in das Live-System zu integrieren.

Wie sieht das in der Praxis aus? Sobald wir eine Änderung auf unserem Produktionsbranch vornehmen, werden folgende Schritte durchgeführt:

  • Die Installationsskripte werden geprüft (npm install und bower)
  • Die Unittests werden ausgeführt
  • Alle Javascript-Dateien werden einem code linting unterzogen

Wenn das alles reibungslos funktioniert hat, kommt das eigentliche Deployment:

  • Überspielen der Daten auf das Staging-System und Installation dort
  • Ausführung von Selenium-Tests
  • Wenn Tests erfolgreich: Überspielen der Daten auf das Live-System
  • Kurze Selenium-Tests ob die Basis-Funktionen korrekt funktionieren und die Seite ansprechbar ist

Auf diesem Weg reicht jederzeit in der Entwicklung ein kurzes git push um etwas in das Live-System zu integrieren. Die Tests und Sicherheitsmaßnahmen sind dabei eine ausreichende Sicherung um nicht durch Unachtsamkeit die Anwendung kaputt zu machen.

Welche Tools, Schritte und Einstellungen nutzen wir dafür im einzelnen?

git

git als Versionsverwaltungssystem (und Alternative zu Subversion oder CVS) sollte jedem Entwickler ein Begriff sein. Dennoch gibt einem git relativ wenig zur Projektorganisation vor. Wir setzen auf das git flow Modell (https://github.com/nvie/gitflow). Eine gute Einführung in git flow findet man unter http://nvie.com/posts/a-successful-git-branching-model/.

Hieraus ergibt sich folgende Branch-Struktur:

  • Master (entspricht immer der Live-Version)
  • Develop (aktuell stabiler Entwicklungsstand)
  • Feature-Branches (werden nach Fertigstellung in develop gemerged)
  • Hotfix-Branches (werden für schnelle Änderungen direkt in den Master gemerged)
  • Release-Branches (Um einen definierten Stand von develop zur Produktionsreife zu bringen)

Um nun ein deployment auf den live Server zu starten reicht folgender Befehl:

git push origin develop

Bei youhear.it setzen wir in codeship (siehe weiter unten) zwei verschiedene Konfigurationen ein. Jeder push auf den Master Branch führt alle oben beschriebenen Schritte des Deployments durch. Ein push des develop-branches hingegen hört nach dem Selenium-Test auf dem staging-Server auf.

Als externes repository nutzen wir bitbucket (wir integrieren auch unser JIRA direkt damit).

codeship.io

cs_logo

Codeship.io ist ein richtig cooler Service der uns eine Menge abnimmt (sobald er einmal sauber eingerichtet ist 😉 ). Ziel ist es dem ganzen Team eine einheitliche Integrations-Plattform zu bieten, die den Code nach jedem commit prüft und ggf. in die Staging- oder Produktionsumgebung überspielt. Dabei spielt codeship extrem gut mit unserem Workflow und unserer anderen Tools zusammen. Durch eine direkte Bitbucket-Anbindung ist die Verknüpfung zu git schnell gemacht. Anschließend muss man nur noch definieren, welche Test-Schritte ausgeführt werden sollen und welche Schritte für das Deployment nötig sind. Sind diese Einstellungen gemacht kann man sich live ansehen wie das Projekt gebaut wird und sieht sofort ob alles geklappt hat (grün) oder nicht (rot). Besonders klasse gelöst im rot-Fall: Man kann sich per ssh in die build-Maschine einwählen und fehlgeschlagene Builds auf der Konsole debuggen!

codeship1

 

Unser Integration-Skript für das Frontend:

nvm install 0.10.26
nvm use 0.10.26
npm cache clear
npm cache clean
rm -rf ./~npm
rm -rf /home/rof/.npm/
npm update -g
npm set registry https://registry.npmjs.org/
npm install -g grunt-cli bower grunt karma-coverage istanbul
npm install
bower install
grunt --force
grunt jshint
grunt karma

Besonders beachten sollte man dabei folgende Zeilen:

npm cache clear
npm cache clean
rm -rf ./~npm
rm -rf /home/rof/.npm/
npm update -g
npm set registry https://registry.npmjs.org/

Diese paar Zeilen haben mich fast 2 Tage gekostet und mir einige graue Haare eingebracht. Ich war schon drauf und dran codeship an den Nagel zu hängen. Das Problem: Der build schlug random-mäßig fehl, noch weit bevor der eigentliche Applikationscode ausgeführt wurde, bei npm install. Doch auch hier hat sich eine Stärke von codeship gezeigt, der spitzen Service. Ich habe bisher auf jede meiner Mails innerhalb von 2 Stunden eine kompetente und freundliche Antwort erhalten und konnte so Probleme schnell fixen. In diesem Fall hätte ich mich wohl nicht so lange selbst die Zähne ausbeißen sollen…

Und abschließend hier noch unser Deployment Skript:

git remote add staging dokku@###.###.###.##:youhearit
git push staging develop:master
npm install nightwatch -g
cd ..
nightwatch
git remote add prod dokku@xxx.xxx.xxx.xxx:youhearit
git push prod master

Und das war es schon! Jeder commit landet nun nach erfolgreichen Test auf dem Server und ist online. Für die Installation und das Management des Deployments auf Server-Seite nutzen wir Dokku. Das führt aber für diesen Artikel etwas zu weit.

nightwatch.js

nightwatch

Das letzte Tool in unserem Stack das ich vorstellen möchte ist nightwatch.js. Der Eine oder Andere kennt vielleicht bereits Selenium. Selenium ist letzlich ein headless Browser, also ein Internet-Browser, nur ohne Bedienoberfläche wie man das vom Chrome oder Firefox kennt. Dieser Browser erlaubt einem Skripte auszuführen, die einen realen Benutzer vortäuschen. Ich kann also Testszenarien sehr fachlich definieren:

  • Rufe URL www.google.de auf
  • Überprüfe das der Titel der Seite “Google” ist
  • Tippe “nightwatch” in das Suchfeld ein
  • Schicke das Formular ab
  • Überprüfe ob die Ergebnisseite den Text “The Night Watch” enthält

Der Code sieht dazu wie folgt aus:

module.exports = {
  "Demo test Google" : function (client) {
    client
      .url("http://www.google.com")
      .waitForElementVisible("body", 1000)
      .assert.title("Google")
      .assert.visible("input[type=text]")
      .setValue("input[type=text]", "nightwatch")
      .waitForElementVisible("button[name=btnG]", 1000)
      .click("button[name=btnG]")
      .pause(1000)
      .assert.containsText("#main", "The Night Watch")
      .end();
  }
};

Einfach, oder?

Zusammenfassung

Wir glauben in der Kombination von git, codeship.io, dokku und nightwatch einen günstigen, einfach handhabbaren und gut laufenden Prozess gefunden zu haben den wir jedem Startup ans Herz legen können. Wir haben uns damit viel Stress genommen und können uns voll auf die Entwicklung konzentrieren ohne zu viele Randthemen ständig im Auge haben zu müssen.

Als Projektleiter von Großprojekten und vor allem Projekten im Finanz-Sektor bin ich es gewohnt mit maximal einer Lieferung pro Monat auszukommen und extrem viel Aufwand in der Testplanung und Testdurchführung zu betreiben. Ein agiler, schlanker Prozess wie oben beschrieben erlaubt es uns mehrmals täglich Produktionscode zu releasen ohne dabei Kopfschmerzen haben zu müssen.

 

Leave A Reply

Navigate