Continuous Integration für Plone
Das Plone Testing & Continuous Integration Team hat in den letzten Monaten hart daran gearbeitet, eine neue Continuous Integration (CI) Infrastruktur für Plone einzurichten. Gestern konnten wir endlich mit unserem neuen System auf jenkins.plone.org. live gehen.
Ein Neuer Jenkins Server
Gil Forcada, Ramon Navarro Bosch und Timo Stollenwerk haben den Plone Jenkins-Hauptserver auf einen neuen und leistungsfähigeren Server verlagert. Wir verwenden ein verteiltes CI-System mit einem Jenkins-Server, der die Testergebnisse sammelt und bereitstellt, und einigen Knoten, auf denen die Tests ausgeführt werden. So können wir unsere CI-Infrastruktur leicht skalieren und sicherstellen, dass die Jenkins-Weboberfläche immer ansprechbar ist, auch wenn die einzelnen Server-Knoten stark belastet sind.
Für die Servereinrichtung verwenden wir Ansible, ein auf Python basierendes Open-Source-Provisioning-System. Wir sind nun in der Lage, unsere gesamte CI-Infrastruktur, einschließlich des Jenkins-Hauptservers, aller Knoten und unserer benutzerdefinierten Middleware-Komponente (mr.roboto) mit diesen beiden Ansible-Playbooks automatisch zu erstellen:
https://github.com/plone/jenkins.plone.org/blob/master/jenkins_server.yml
https://github.com/plone/jenkins.plone.org/blob/master/jenkins_node.yml
Damit andere Personen unsere Arbeit wiederverwenden können, haben wir die allgemeinen Teile der Konfiguration in zwei Ansible-Playbooks aufgeteilt:
Sven Strack und Timo Stollenwerk haben die Plone Jenkins-Knotenkonfiguration während des Plone Open Garden 2014 auf Ansible übertragen, nachdem Rackspace uns freundlicherweise neue Server zur Verfügung gestellt hatte. Gil Forcada trieb die Dinge weiter voran und schrieb die Ansible-Serverkonfiguration.
mr.roboto
mr.robotoist eine Pyramiden-basierte Middleware-Komponente, die Ramon Navarro-Bosch während des Testing/CI-Sprints 2012 in Barcelona schrieb. Der Plone-Kern hat mehr als 300 Python-Pakete in separaten Github-Repositories, was es zu einer Herausforderung macht, zu entscheiden, welches Paket gebaut und welcher CI-Job für einen bestimmten Commit ausgelöst werden muss. Darüber hinaus macht es die Art und Weise, wie die Jenkins Git/Github-Plugins geschrieben sind, sehr schwierig, Git-Commit-Nachrichten zwischen Jenkins-Jobs weiterzugeben, die ein anderes Basis-Repository verwenden.
mr.roboto übernimmt diese Art von Plone-Kern-spezifischer Komplexität für uns. Es erkennt Commits an ein beliebiges Plone-Core-Repository, indem es die Datei sources.cfg in buildout.coredev (unser Haupt-Repository für die Plone-Entwicklung) durchsucht und automatisch Post-Commit-Hooks für diese Repositories erstellt. Wenn mr.roboto einen Commit entdeckt, fügt es diesen automatisch dem entsprechenden buildout.coredev-Zweig hinzu.
Auf diese Weise erhalten wir buildout.coredev-Zweige, die alle Commits für eine bestimmte Plone-Version enthalten, als ob Plone nur ein einziges Repository hätte.
Angenommen, Sie machen eine Code-Änderung an den plone.formwidget.namedfile-Master-Branch. mr.roboto wird automatisch zwei buildout.coredev-Übergaben erzeugen, da der Master-Branch sowohl von Plone 4.3. als auch von 5.0 genutzt wird. Würde das Paket nur von einer Plone-Version verwendet werden, würde mr.roboto nur in diesen speziellen buildout.coredev-Zweig übertragen. Diese mr.roboto Commits sehen wie folgt aus:
[fc] Repository: plone.formwidget.namedfile
Das "[fc]" steht für "fake commit", da es sich nicht um eine direkte Übergabe an buildout.coredev handelt. Hier ist ein Beispiel für einen echten Commit, der von mr.roboto hinzugefügt wurde:
Wenn wir ein einziges Repository haben, das alle unsere Commits enthält, kann das Jenkins-Github-Plugin die Arbeit übernehmen. Es startet automatisch einen Jenkins-Job für jede buildout.coredev-Übertragung. Darüber hinaus ist das Plugin intelligent genug, um zu erkennen, welcher Zweig gebaut werden muss. Ein mr.roboto-Commit an den 4.3-Zweig löst zum Beispiel nur 4.3-Jobs aus und nicht die 5.0-Jobs.
Mit diesem Ansatz stellen wir sicher, dass wir die richtigen Jobs für jeden Commit ausführen, während wir die mr.roboto-Logik von Jenkins getrennt halten.
Jenkins Job Builder
Jenkins Job Builder ist ein Jenkins-Plugin, das von der Open Stack-Community entwickelt und gepflegt wird. Es ermöglicht uns, alle unsere Jenkins-Jobs innerhalb weniger Minuten automatisch zu erstellen. Es verwendet eine einfache YML-Syntax und ist, da es in schönem Python geschrieben ist, leicht zu erweitern. Gil Forcada hat in den letzten Monaten fantastische Arbeit geleistet, indem er alle unsere Jobkonfigurationen von einem benutzerdefinierten Buildout-Rezept, das ich vor einiger Zeit geschrieben habe (collective.recipe.jenkinsjobs), in Jenkins Job Builder übertragen hat. Hier ist unsere Konfigurationsdatei:
https://github.com/plone/jenkins.plone.org/blob/master/jobs.yml
Coredev Jenkins Jobs
Wir haben mehr als 8000 Tests im Plone-Kern, darunter einige lang laufende Akzeptanztests. Die Ausführung all dieser Tests dauert mehr als eineinhalb Stunden.
Ein effektives CI-System muss den Entwicklern so schnell wie möglich eine Rückmeldung geben. Deshalb haben wir den Plone-5.0-Jenkins-Job in drei separate Jobs aufgeteilt: einen für die Kerntests, einen für alle Archetypen-bezogenen Tests und einen für Robot-Framework-basierte Akzeptanztests. Dadurch können wir die Testausführungszeit auf 30 Minuten reduzieren.
30 Minuten sind schon ziemlich gut, wenn man bedenkt, wie viele Tests wir ausführen müssen. Aber das ist noch nicht alles. Cloudbees, die Firma hinter Jenkins, hat gerade ein Jenkins-Workflow-Plugin veröffentlicht, das sehr vielversprechend aussieht. Es könnte für Open-Source-CI-Systeme ein Wendepunkt werden. Dieses Plugin wird es uns ermöglichen, die Testergebnisse (die derzeit auf drei Aufträge verteilt sind) in einem einzigen Auftrag zu präsentieren, während wir unsere Tests weiterhin parallel durchführen können.
Da das Workflow-Plugin relativ neu ist, müssen andere Jenkins-Plugins noch aufholen, bevor wir es in der Produktion einsetzen können (z. B. gibt es derzeit keine Unterstützung für das xvfb-Plugin, das wir benötigen, um einen X-Server für unsere Selenium-Tests dynamisch einzurichten). Hier ein kleiner Vorgeschmack auf den neuen vereinheitlichten Plone-5-Job:
https://github.com/plone/jenkins.plone.org/blob/master/flow.groovy
Wir denken, dass das Jenkins-Workflow-Plugin uns in Zukunft erlauben wird, eine komplexe CI- und Deployment-Pipeline zu erstellen. Dies wird uns hoffentlich in die Lage versetzen, Entwicklern innerhalb von weniger als 10 Minuten eine erste Antwort zu geben und wird auch den gesamten Plone-Release-Prozess erheblich verbessern und beschleunigen.
Github Authentifizierung
Gil hat das Jenkins-Github-Plugin so eingerichtet, dass es sich gegen Github statt gegen LDAP authentifiziert. Dadurch kann sich jeder Plone-Kernentwickler bei jenkins.plone.org anmelden, ohne ein Passwort eingeben zu müssen, und bei Bedarf Jobs manuell starten.
Jenkins Theme
Wir haben unser Jenkins-Theme mit dem Dooney Jenkins-Theme und dem Simple Theme Plugin gebrandet und angepasst. So sieht es jetzt aus:
Dokumentation und Prüfung
Wir haben unsere Arbeit vollständig in einer Sphinx-basierten Dokumentation dokumentiert, die wir auf readthedocs.org hochgeladen haben:
Auf diese Weise kann jeder, der über die entsprechenden Anmeldeinformationen verfügt (derzeit Gil Forcada, Ramon Navarro-Bosch, Sven Strack und Timo Stollenwerk), unsere CI-Infrastruktur zu jedem Zeitpunkt einrichten oder reparieren.
Gil Forcada hat auch ein Vagrant-Image eingerichtet, damit wir unsere Ansible- und Jenkins Job Builder-Bereitstellung testen können, bevor wir die Dinge auf die Live-Maschine übertragen.
Zukünftige Schritte
Wir haben eine Menge Ideen, wie wir unsere Einrichtung weiter verbessern können, und es gibt eine Menge zu tun. Siehe https://github.com/plone/jenkins.plone.org/issues für Details.
Es gibt jedoch einige Punkte, die sich die Plone-Kernentwickler schon seit geraumer Zeit gewünscht haben.
- Automatisch generierte PLIP-Jobs (Plone Improvement Proposals), um es den Kernentwicklern zu erleichtern, diese PLIPs zu testen.
- Testen von Github Pull Requests. Dies ist eine Funktion, die CI-Systeme wie travis oder drone.io von Haus aus bieten, die aber mit Jenkins nicht einfach zu implementieren ist. Wir planen, Entwicklern die Möglichkeit zu geben, Pull-Request-Tests manuell auszulösen. In der Zukunft möchten wir diesen Vorgang möglicherweise vollständig automatisieren.
Mit der neuen Infrastruktur hoffen wir, diese weiteren Verbesserungen bald bereitstellen zu können. Bleiben Sie dran.