Verwendung von Branch-basierten Deployments in der Continuous Delivery-Pipeline

Bei Continuous Delivery stellt sich die Frage, wohin die Bereitstellung erfolgen soll – und woher.

Sarah Goff-Dupont Sarah Goff-Dupont

Oft benutzen wir Begriffe wie "Pipeline", um den kontinuierlichen Codefluss vom Repository zu den Nutzern zu beschreiben. Aber wenn man sich den Vorgang genau ansieht, erscheint die Pipeline eher wie ein Netzwerk – insbesondere dann, wenn du einen Branch-and-Merge-Workflow verfolgst (den wir dir empfehlen).

Wenn du auf einem Branch entwickelst, sollte dieser Branch seinen eigenen Deployment-Pfad haben, damit Änderungen sorgfältig geprüft werden können, bevor ein Merge zum Master durchgeführt wird oder ein Release an den Kunden ansteht. Im Folgenden soll gezeigt werden, wie die Entwicklertools von Atlassian erfolgreiche Branch-Deployments ermöglichen.

Ich bespreche zunächst die drei wichtigsten Anwendungsfälle und zeige dann, wie sie durch Integrationen mit Jira Software, Bitbucket und Bamboo umgesetzt werden können.

Die Vorteile Branch-basierter Deployments

Die Integration deines Branch-Netzwerks in eine Continuous-Delivery-Pipeline ist sinnvoll, da sie dir Arbeit erspart. Wenn du eine Testumgebung mit Teamkollegen teilst, ist es einfacher, mehrere Deployments zu koordinieren, die separate Arbeitsströme darstellen, als alle Ströme vor dem Testen zusammenzuführen und sie zu entwirren, wenn weitere Änderungen (unweigerlich) erforderlich sind.

Solltest du das Glück haben, über mehrere Testumgebungen zu verfügen, wird es noch einfacher. Ähnlich ist es bei den Releases an die Kunden: Manche Teams releasen direkt von Branches und führen die Updates vom Branch bis zum Master später zusammen.

Automatisches Auslösen von Deployments über einen Feature Branch

Die Verwendung von Feature Branches für User Stories und Fehlerbehebungen ist ideal, um Änderungen an dein Repository in Bitbucket zu pushen (und somit CI für diese Änderungen ausführen zu lassen). So muss sich der Rest deines Teams nicht mit fehlerhaften Builds und fehlgeschlagenen Tests befassen, während der Prozess im Gange ist.

Falls dein Team die Auslieferung lieber über den Master durchführt, solltest du den Code für explorative Tests und Akzeptanztests in internen Umgebungen bereitstellen. Das funktioniert am besten, wenn es mehrere Testumgebungen gibt, die dein Team für Deployments nutzen kann. So muss niemand warten, bis er an der Reihe ist, um eine einzige gemeinsame Umgebung zu nutzen.

Bei Branch-Deployments in Bamboo kannst du den Deployment-Trigger für jede Umgebung konfigurieren, um die auf einem bestimmten Branch erstellten Artefakte automatisch bereitzustellen – entweder in geplanten Intervallen oder bei jedem erfolgreichen CI-Build dieses Branchs. Du kannst sogar zwei Trigger-Typen gleichzeitig verwenden.

Screenshot: Testumgebung

Angenommen, du hast eine einzige Leistungstestumgebung, die alle gemeinsam nutzen. Im Laufe des Tages führst du bei erfolgreichen Builds Master-Deployments durch. Bei den meisten Teams, die gerne mit Branches arbeiten, sind Master-Builds normalerweise das Ergebnis von neu gemergten Elementen. In diesem Fall ist es empfehlenswert, umgehend die Leistung zu testen.

Nachts, wenn das Repository nicht verwendet wird, solltest du die Deployments jedes Entwickler-Branchs sowie die entsprechenden Intervalle planen. Auf diese Weise erhält jeder mindestens einmal am Tag ein arbeitsbezogenes Leistungs-Feedback. (Deployment-Aufträge in Bamboo können mit einem Skript-, Ant- oder Maven-Task abgeschlossen werden, der die Leistungstests auslöst.) Entwickler können zudem jederzeit automatische Deployment-Trigger verwenden, um Builds an ihre Testumgebungen zu schicken, wenn die Erstellung ihres Feature Branch erfolgreich war.

Um dies einzurichten, kannst du entweder ein diskretes Deployment-Projekt in Bamboo für deinen Entwickler-Branch erstellen oder deinen Branch mit einer Umgebung innerhalb des Deployment-Projekts verknüpfen, indem du anpasst, wie Deployments an die Umgebung ausgelöst werden.

Screenshot: Deployment-Projekt erstellen

In der Bamboo-Dokumentation erhältst du Schritt-für-Schritt-Anleitungen zur Verknüpfung eines Deployment-Projekts mit einem Branch und zum Anpassen von Deployment-Triggern.

Releasen von einem Release-Branch

Für Teams, die es vorziehen, laufende Arbeiten direkt in der Hauptcodezeile unterzubringen, ist es empfehlenswert, direkt über einen Branch zu releasen. Während das Deployment von Master- oder Trunk-Branches an die Testumgebung erfolgt, werden Release-Branches in der Staging- und schließlich in der Produktionsumgebung bereitgestellt. Außerdem können Release-Branches als Teil eines Gitflow-Ansatzes verwendet werden.

Screenshot: Gitflow

Release-Branches werden regelmäßig abgeschnitten und Änderungen werden von dort aus ausgeliefert. Die meisten Teams möchten keinen automatischen Trigger verwenden und stattdessen selbst entscheiden, wann und wohin das Deployment eines Release-Branch erfolgen soll. Kein Problem.

Im Konzept von Bamboo sind "Releases" Entitäten innerhalb von Bamboo, die die aktuellsten Artefakte enthalten, die auf einem bestimmten Branch erstellt wurden. Zusätzlich enthalten sie alle Commits, Testergebnisse und Jira-Vorgänge, die mit allen Builds auf diesem Branch verbunden sind, seit das letzte Mal ein Release erstellt wurde. Ein Release umfasst also deine Artefaktpakete sowie zahlreiche Metadaten.

Genau diese umfassenden Daten sollen zusammen mit den Artefakten durch deine Continuous-Delivery-Pipeline strömen, damit du alles zurück bis zum ersten Commit und zur ursprünglichen User Story verfolgen kannst. (Ich glaube, es war Geoffrey Chaucer, der den Spruch "Alle Wege führen zu Jira Software" geprägt hat.) Eigentlich beförderst du also den Release und nicht nur einen Build durch deine Umgebungen. Dies spiegelt auch die UI von Bamboo wider.

Screenshot: Staging-Releases in einer Bamboo-Umgebung

Kommen wir zurück zu den Triggern. Wenn Deployments automatisch ausgelöst werden, wie im Fall oben, erstellt Bamboo automatisch einen Release.

Manuell ausgelöste Deployments funktionieren anders. In diesem Fall erstellst du den Release (über den Build-Ergebnis-Bildschirm oder innerhalb eines Deployment-Projekts), gibst ihm einen Namen und wählst den Build aus, von dem du die Artefakte pullen möchtest. Du kannst den Release nun in jeder beliebigen Umgebung bereitstellen – sogar in der Produktionsumgebung, falls dies wirklich erforderlich ist. Teams, die diesen Ansatz verfolgen, erstellen normalerweise mehrere Releases (genau genommen Release-Kandidaten), bevor sie den besten Release auswählen und an die Pipeline weitergeben.

Um einen Release an die nächste Umgebung weiterzugeben, gehst du zum Bildschirm All Deployment Projects. Dort werden alle deine Deployment-Projekte angezeigt sowie alle Umgebungen, die mit dem jeweiligen Projekt in Verbindung stehen. Klicke auf das Deployment-Symbol neben deiner Zielumgebung und verwende den Deployment-Vorschau-Assistenten. Wähle dazu "deploy an existing release" (einen vorhanden Release bereitstellen) aus. Mehr dazu erfährst du, wenn du auf den Link klickst.

Updates an unterstützte Versionen ausliefern

Wenn du kein SaaS verwendest, musst du wahrscheinlich mehrere Versionen deiner Software gleichzeitig unterstützen und manchmal wichtige Problembehebungen, Backport-Sicherheitsupdates usw. ausliefern. Dies bedeutet, dass stabile Versions-Branches für eine sehr lange Zeit beibehalten werden – wahrscheinlich jahrelang. Builds von diesen Branches werden normalerweise an einem gemeinsamen Ort bereitgestellt, zum Beispiel einer Website oder einem externen Repository. Kunden können hier dann auf die Updates für die von ihnen verwendeten Versionen zugreifen.

Workflow mit mehreren Versionen (Screenshot)

Bei diesen Branches lassen sich Builds am einfachsten über die Schaltfläche "create release" zu Releases machen. Sie finden die Schaltfläche auf dem Build-Ergebnis-Bildschirm des auszuliefernden Builds. Du kannst natürlich mit dem oben beschriebenen "all deployment projects"-Bildschirm beginnen. Da du dich aber auf einen ganz bestimmten Branch konzentrierst, der ausgeliefert werden soll und bei dem es sich nicht unbedingt um den aktuellsten Build des Branchs handelt, ist es besser auf dem Build-Ergebnis-Bildschirm zu beginnen. Dies gibt dir etwas mehr Sicherheit, den richtigen Build auszuwählen.

Alles zusammenfügen (eine Continuous-Delivery-Pipeline nach der anderen)

Branch-basierte Deployments sind die natürliche Erweiterung der Plan-Branches von Bamboo, die wiederum die natürliche Erweiterung des Branching-Schemas darstellen, das du für dein Team in Bitbucket einrichtest. Wie ich hier gezeigt und in anderen Artikeln

ausführlich beschrieben habe, gibt es mehrere Modelle, die für CD geeignet sind.

Dein Branching-Schema sollte widerspiegeln, wie dein Team Aufgaben angeht und erledigt.

Schauen wir uns die unterschiedlichen Elemente an, die hierbei eine Rolle spielen:

  • Jira-VorgängeVorgangsschlüssel bieten viele Vorteile. Verwende sie in Branch-Namen und Commit-Nachrichten, damit alle Commits, Builds und Deployments (und sogar Pull-Anfragen) zurück auf den Vorgang verweisen.
  • Branches – Wusstest du, dass jeder Vorgang über einen praktischen "Branch erstellen"-Link verfügt, wenn du Bitbucket mit JIRA Software verbindest? Und dass, wenn du diesen Link verwendest, der Vorgangsschlüssel automatisch dem Branch-Namen hinzugefügt wird? Das zeigt, wie wichtig es uns ist, dass ein Branch für jeden Vorgang erstellt wird, an dem du arbeitest. Probier es einfach mal bei deinem nächsten Sprint aus!
  • Plan-Branches – Bamboo erkennt automatisch neue Branches in deinen Git-, Mercurial- und Subversion-Repositorys, wenn du das automatische Branch-Management aktivierst. Wenn du dann deinen ersten Commit durchführst, hat Bamboo schon den ersten Branch getestet.
  • Deployment-Projekte – Dies ist die "Delivery"-Phase deiner Continuous-Delivery-Pipeline. Du verknüpfst ein Repository und eine oder mehr Umgebung(en) mit den jeweiligen Deployment-Projekten.
  • Umgebungen – Die Darstellung deiner Netzwerkumgebungen in Bamboo. Jede Umgebung kann mit unterschiedlichen Branches verknüpft werden, unterschiedliche Deployment-Trigger verwenden und unterschiedliche Schritte (Tasks) verfolgen, um ein erfolgreiches Deployment durchzuführen.
  • Release – Artefaktpakete und Metadaten. Wenn du dir einen bestimmten Release in Bamboo ansiehst, werden dir alle JIRA-Vorgänge (dank Vorgangsschlüsseln!), Commits, Testergebnisse und Artefakte angezeigt, die mit dem Release in Verbindung stehen. Dir werden auch die Umgebungen angezeigt, in die der Release bereitgestellt wurde, und du kannst kennzeichnen, ob er für den Übergang zur nächsten Phase genehmigt oder abgelehnt wurde.

Jeder hier erwähnte Use Case liegt in mindestens einem der Entwicklerteams von Atlassian vor. Manche Teams decken sogar mehrere Use Cases ab. Um ganz ehrlich zu sein: Die Umstellung von einer einzigen (oder gar keiner) Continuous Delivery-Pipeline auf ein ganzes Netzwerk aus Branch-basierten Pipelines wird länger dauern als du hoffst und dir einige suboptimale Aspekte eurer aktuellen Prozesse vor Augen führen, mit denen du dich dann beschäftigen musst.

Das ist aber in Ordnung. Leg einfach los und sag uns Bescheid, wie es läuft! Schreib uns bei Twitter (@Atlassian) oder folge unserem Atlassian Blog für weitere Informationen zu Agile, Git und Entwicklertools.