Du kannst die REST-API verwenden, um deine auf GitHub gehosteten Projekte auf einem Server in deinem Besitz bereitzustellen. Weitere Informationen zu den Endpunkten zum Verwalten von Bereitstellungen und Statusinformationen findest du unter AUTOTITLE. Du kannst auch die REST-API verwenden, um deine Bereitstellungen in dem Moment zu koordinieren, in dem dein Code im Standardzweig eintrifft. Weitere Informationen finden Sie unter AUTOTITLE.
In diesem Leitfaden wird die REST-API verwendet, um ein Setup zu veranschaulichen, das du verwenden kannst. In unserem Szenario werden wir Folgendes tun:
- Einen Pull Request zusammenführen.
- Wenn die CI abgeschlossen ist, legen wir den Status des Pull Requests entsprechend fest.
- Wenn der „Pull Request“ zusammengeführt wurde, starten wir die Bereitstellung auf unserem Server.
Unser CI-System und der Hostserver sind Produkte unserer Vorstellungskraft. Dabei könnte es sich um Heroku, Amazon oder etwas ganz anderes handeln. Im Mittelpunkt dieses Leitfadens steht die Einrichtung und Konfiguration des Servers, der die Kommunikation verwaltet.
Stelle sicher, dass du es herunterlädst und lernst, wie man es benutzt. Dieses Tool ist sehr nützlich, um lokale Anwendungen im Internet zugänglich zu machen.
Hinweis
Alternativ kannst du die Webhookweiterleitung verwenden, um deine lokale Umgebung für den Empfang von Webhooks einzurichten. Weitere Informationen finden Sie unter AUTOTITLE.
Hinweis: Du kannst den vollständigen Quellcode für dieses Projekt aus dem Repository mit den Plattformbeispielen herunterladen.
Erstellen Ihres Servers
Wir schreiben eine einfache Sinatra-App, um zu zeigen, dass unsere lokalen Verbindungen funktionieren. Beginnen wir hiermit:
require 'sinatra'
require 'json'
post '/event_handler' do
payload = JSON.parse(params[:payload])
"Well, it worked!"
end
(Wenn du nicht mit der Funktionsweise von Sinatra vertraut bist, solltest du den Sinatra-Leitfaden lesen.)
Starte diesen Server. Sinatra wird standardmäßig auf Port 4567 gestartet. Daher solltest du es so konfigurieren, dass es ebenfalls auf diesen Port lauscht.
Damit dieser Server funktioniert, müssen wir ein Repository mit einem Webhook einrichten. Dieser Webhook sollte so konfiguriert werden, dass er ausgelöst wird, wenn ein Pull Request erstellt oder zusammengeführt wird.
Erstelle nun ein Repository, mit dem du experimentieren kannst. Wie wäre es mit dem Spoon/Knife-Repository von ?
Danach erstellst du einen neuen Webhook in deinem Repository, fügst die URL hinzu, die dir gegeben wurde, und wählst den Inhaltstyp aus.
Klicken Sie auf "Aktualisieren" des Webhooks. Sie sollten einen Antwortkörper sehen. Sehr gut! Klicke auf Individuelle Ereignisse auswählen, und wähle Folgendes aus:
- Bereitstellung
- Bereitstellungsstatus
- Pull-Anforderung
Dies sind die Ereignisse, die GitHub an unseren Server sendet, wenn die relevante Aktion durchgeführt wird. Wir konfigurieren unseren Server so, dass er nur Verarbeitungen durchführt, wenn Pull Requests sofort zusammengeführt werden:
post '/event_handler' do
@payload = JSON.parse(params[:payload])
case request.env['HTTP_X_GITHUB_EVENT']
when "pull_request"
if @payload["action"] == "closed" && @payload["pull_request"]["merged"]
puts "A pull request was merged! A deployment should start now..."
end
end
end
Woran liegt das? Jedes Ereignis, das GitHub sendet, enthält einen X-GitHub-Event HTTP-Header. Wir kümmern uns jetzt nur um die PR-Veranstaltungen. Wenn ein Pull Request zusammengeführt wird (der Status lautet , und ist ), starten wir eine Bereitstellung.
Nimm einige Änderungen in einem Branch deines Testrepositorys vor, öffne einen Pull Request, und merge sie, um diesen Proof of Concept zu testen. Dein Server sollte entsprechend reagieren.
Arbeiten mit Bereitstellungen
Sobald unser Server eingerichtet ist, der Code überprüft und unser Pull Request zusammengeführt wurde, möchten wir unser Projekt bereitstellen.
Zunächst ändern wir unseren Ereignislistener so, dass er Pull Requests verarbeitet, wenn sie zusammengeführt werden, und beginnen, auf Bereitstellungen zu reagieren:
when "pull_request"
if @payload["action"] == "closed" && @payload["pull_request"]["merged"]
start_deployment(@payload["pull_request"])
end
when "deployment"
process_deployment(@payload)
when "deployment_status"
update_deployment_status
end
Anhand der Informationen aus dem Pull Request beginnen wir mit dem Ausfüllen der -Methode:
def start_deployment(pull_request)
user = pull_request['user']['login']
payload = JSON.generate(:environment => 'production', :deploy_user => user)
@client.create_deployment(pull_request['head']['repo']['full_name'], pull_request['head']['sha'], {:payload => payload, :description => "Deploying my sweet branch"})
end
Bereitstellungen können einige Metadaten an sich haben, in Form eines Platzhalters und einer weiteren Angabe. Auch wenn diese Werte optional sind, ist es hilfreich, sie zum Protokollieren und Darstellen von Informationen zu verwenden.
Wenn eine neue Bereitstellung erstellt wird, wird ein völlig separates Ereignis ausgelöst. Daher haben wir einen neuen Fall im Ereignishandler für . Du kannst diese Informationen verwenden, um benachrichtigt zu werden, wenn eine Bereitstellung ausgelöst wurde.
Bereitstellungen können eine lange Zeit dauern. Daher sollten wir auf verschiedene Ereignisse lauschen, z. B. wann die Bereitstellung erstellt wurde und in welchem Zustand sie sich befindet.
Lass uns eine Bereitstellung simulieren, die einige Aufgaben ausführt, und beobachten, wie sich dies auf die Ausgabe auswirkt. Zunächst sollten wir unsere -Methode abschließen:
def process_deployment
payload = JSON.parse(@payload['payload'])
# you can send this information to your chat room, monitor, pager, etc.
puts "Processing '#{@payload['description']}' for #{payload['deploy_user']} to #{payload['environment']}"
sleep 2 # simulate work
@client.create_deployment_status("repos/#{@payload['repository']['full_name']}/deployments/#{@payload['id']}", 'pending')
sleep 2 # simulate work
@client.create_deployment_status("repos/#{@payload['repository']['full_name']}/deployments/#{@payload['id']}", 'success')
end
Schließlich simulieren wir das Speichern der Statusinformationen als Konsolenausgabe:
def update_deployment_status
puts "Deployment status for #{@payload['id']} is #{@payload['state']}"
end
Lass uns aufschlüsseln, was gerade passiert. Eine neue Bereitstellung wird durch , was das Ereignis auslöst, erstellt. Anschließend rufen wir auf, um andauernde Prozesse zu simulieren. Während dieser Verarbeitung rufen wir ebenfalls auf, wodurch wir einen Empfänger über den Stand der Dinge informieren, während wir den Status auf festlegen.
Nach Abschluss der Bereitstellung legen wir den Status auf fest.
Schlussbemerkung
Bei GitHub haben wir eine Version von Heaven verwendet, um unsere Bereitstellungen seit Jahren zu verwalten. Der allgemeine Ablauf ist im Wesentlichen derselbe wie bei dem Server, den wir oben erstellt haben:
- Warte auf eine Antwort auf den Status der CI-Überprüfungen (Erfolg oder Fehler).
- Wenn die erforderlichen Überprüfungen erfolgreich waren, führe den Pull Request zusammen.
- Heaven nimmt den zusammengeführten Code und stellt ihn für Staging- und Produktionsserver bereit.
- In der Zwischenzeit benachrichtigt Heaven auch alle über den Build-Prozess über den Hubot, der sich in unseren Chaträumen befindet.
Das ist alles! Um dieses Beispiel zu verwenden, musst du kein eigenes Bereitstellungssetup kompilieren. Sie können sich jederzeit auf GitHub Integrationen verlassen.