Verwendung von Node.js und Github Webhooks, um Remote-Projekte synchron zu halten

Einführung

Wenn Sie an einem Projekt mit mehreren Entwicklern arbeiten, kann es frustrierend sein, wenn eine Person in ein Repository wechselt und eine andere Person Änderungen an einer veralteten Version des Codes vornimmt. Fehler wie diese kosten Zeit, weshalb es sich lohnt, ein Skript einzurichten, um Ihre Repositorys synchron zu halten. Sie können diese Methode auch in einer Produktionsumgebung anwenden, um Hotfixes und andere Änderungen schnell zu übertragen.

Es gibt zwar andere Lösungen, um diese spezielle Aufgabe zu erfüllen, aber das Schreiben eines eigenen Skripts ist eine flexible Option, die in Zukunft Raum für Anpassungen lässt.

MitGitHub können Siewebhooks für Ihre Repositorys konfigurieren. Hierbei handelt es sich um Ereignisse, die HTTP-Anforderungen senden, wenn Ereignisse auftreten. Sie können zum Beispiel einen Webhook verwenden, um Sie zu benachrichtigen, wenn jemand eine Pull-Anfrage erstellt oder neuen Code sendet.

In diesem Handbuch entwickeln Sie einenNode.js-Server, der auf eine GitHub-Webhook-Benachrichtigung wartet, wenn Sie oder eine andere Person Code an GitHub senden. Dieses Skript aktualisiert automatisch ein Repository auf einem Remote-Server mit der neuesten Version des Codes, sodass Sie sich nicht mehr bei einem Server anmelden müssen, um neue Commits abzurufen.

Voraussetzungen

Um dieses Tutorial abzuschließen, benötigen Sie:

  • Ein Ubuntu 16.04-Server, der von folgendenthe Ubuntu 16.04 initial server setup guideeingerichtet wurde, einschließlich eines Nicht-Root-Benutzers mitsudo-Berechtigungen und einer Firewall.

  • Git auf Ihrem lokalen Computer installiert. Sie können dem TutorialContributing to Open Source: Getting Started with Git folgen, um Git auf Ihrem Computer zu installieren und einzurichten.

  • Node.js and npm installed on the remote server using the official PPA, as explained explained in How To Install Node.js on Ubuntu 16.04. Die Installation der Distribution-Stable-Version ist ausreichend, da uns die empfohlene Version ohne zusätzliche Konfiguration zur Verfügung gestellt wird.

  • Ein Repository auf Github, das Ihren Projektcode enthält. Wenn Sie kein Projekt im Sinn haben, können Siefork this example verwenden, die wir im Rest des Tutorials verwenden werden.

[[Schritt-1 -—- Einrichten eines Webhooks]] == Schritt 1 - Einrichten eines Webhooks

Zunächst konfigurieren wir einen Webhook für Ihr Repository. Dieser Schritt ist wichtig, da Github ohne ihn nicht weiß, welche Ereignisse gesendet werden sollen, wenn etwas passiert, oder wohin sie gesendet werden sollen. Wir erstellen zuerst den Webhook und dann den Server, der auf seine Anforderungen reagiert.

Melden Sie sich bei Ihrem GitHub-Konto an und navigieren Sie zu dem Repository, das Sie überwachen möchten. Klicken Sie in der oberen Menüleiste auf der Seite Ihres Repositorys auf die RegisterkarteSettings und dann im linken Navigationsmenü aufWebhooks. Klicken Sie in der rechten Ecke aufAdd Webhook und geben Sie Ihr Kontokennwort ein, wenn Sie dazu aufgefordert werden. Sie sehen eine Seite, die so aussieht:

Webhooks Page

  • Geben Sie im FeldPayload URLhttp://your_server_ip:8080 ein. Dies ist die Adresse und der Port des Node.js-Servers, den wir bald schreiben werden.

  • Ändern SieContent type inapplication/json. Das Skript, das wir schreiben, erwartet JSON-Daten und kann andere Datentypen nicht verstehen.

  • Geben Sie fürSecret ein geheimes Passwort für diesen Webhook ein. Sie werden dieses Geheimnis auf Ihrem Node.js-Server verwenden, um Anforderungen zu überprüfen und sicherzustellen, dass sie von GitHub stammen.

  • Wählen Sie fürWhich events would you like to trigger this webhookjust the push event aus. Wir brauchen nur das Push-Ereignis, da dann der Code aktualisiert wird und mit unserem Server synchronisiert werden muss.

  • Aktivieren Sie das KontrollkästchenActive.

  • Überprüfen Sie die Felder und klicken Sie aufAdd webhook, um sie zu erstellen.

Der Ping schlägt zunächst fehl, aber Sie können sicher sein, dass Ihr Webhook jetzt konfiguriert ist. Lassen Sie uns nun das Repository auf den Server klonen.

[[Schritt 2 - Klonen des Repositorys auf den Server]] == Schritt 2 - Klonen des Repositorys auf den Server

Unser Skript kann ein Repository aktualisieren, das anfängliche Einrichten des Repositorys ist jedoch nicht möglich. Deshalb werden wir dies jetzt tun. Melden Sie sich bei Ihrem Server an:

ssh sammy@your_server_ip

Stellen Sie sicher, dass Sie sich in Ihrem Ausgangsverzeichnis befinden. Verwenden Sie dann Git, um Ihr Repository zu klonen. Stellen Sie sicher, dass Siesammy durch Ihren GitHub-Benutzernamen undhello_hapi durch den Namen Ihres Github-Projekts ersetzen.

cd
git clone https://github.com/sammy/hello_hapi.git

Dadurch wird ein neues Verzeichnis erstellt, das Ihr Projekt enthält. Sie werden dieses Verzeichnis im nächsten Schritt verwenden.

Wenn Sie Ihr Projekt geklont haben, können Sie das Webhook-Skript erstellen.

[[Schritt-3 -—- Erstellen des Webhook-Skripts]] == Schritt 3 - Erstellen des Webhook-Skripts

Erstellen wir unseren Server, um auf diese Webhook-Anfragen von GitHub zu warten. Wir werden ein Node.js-Skript schreiben, das einen Webserver auf Port8080 startet. Der Server wartet auf Anfragen vom Webhook, überprüft das von uns angegebene Geheimnis und ruft die neueste Version des Codes von GitHub ab.

Navigieren Sie zu Ihrem Home-Verzeichnis:

cd ~

Erstellen Sie ein neues Verzeichnis für Ihr Webhook-Skript mit dem NamenNodeWebhooks:

mkdir ~/NodeWebhooks

Navigieren Sie dann zum neuen Verzeichnis:

cd ~/NodeWebhooks

Erstellen Sie eine neue Datei mit dem Namenwebhook.js im VerzeichnisNodeWebhooks.

nano webhook.js

Fügen Sie diese beiden Zeilen zum Skript hinzu:

webhook.js

var secret = "your_secret_here";
var repo = "/home/sammy/hello_hapi";

In der ersten Zeile wird eine Variable definiert, die das in Schritt 1 erstellte Geheimnis enthält und überprüft, ob Anforderungen von GitHub stammen. In der zweiten Zeile wird eine Variable definiert, die den vollständigen Pfad zum Repository enthält, das Sie auf Ihrer lokalen Festplatte aktualisieren möchten. Dies sollte auf das Repository verweisen, das Sie in Schritt 2 ausgecheckt haben.

Fügen Sie als Nächstes diese Zeilen hinzu, die die Bibliothekenhttp undcrypto in das Skript importieren. Wir werden diese verwenden, um unseren Webserver zu erstellen und das Geheimnis zu hacken, damit wir es mit dem vergleichen können, was wir von GitHub erhalten:

webhook.js

let http = require('http');
let crypto = require('crypto');

Fügen Sie als Nächstes die Bibliothekchild_processhinzu, damit Sie Shell-Befehle aus Ihrem Skript ausführen können:

webhook.js

const exec = require('child_process').exec;

Fügen Sie als Nächstes diesen Code hinzu, um einen neuen Webserver zu definieren, der GitHub-Webhook-Anforderungen verarbeitet und die neue Version des Codes herunterfährt, wenn es sich um eine authentische Anforderung handelt:

webhook.js

http.createServer(function (req, res) {
    req.on('data', function(chunk) {
        let sig = "sha1=" + crypto.createHmac('sha1', secret).update(chunk.toString()).digest('hex');

        if (req.headers['x-hub-signature'] == sig) {
            exec('cd ' + repo + ' && git pull');
        }
    });

    res.end();
}).listen(8080);

Die Funktionhttp.createServer() startet einen Webserver an Port8080, der auf eingehende Anforderungen von Github wartet. Aus Sicherheitsgründen überprüfen wir, ob das in der Anfrage enthaltene Geheimnis dem entspricht, das wir beim Erstellen des Webhooks in Schritt 1 angegeben haben. Das Geheimnis wird im Header vonx-hub-signatureals SHA1-Hash-Zeichenfolge übergeben. Wir haben also unser Geheimnis gehasht und vergleichen es mit dem, was GitHub uns sendet.

Wenn die Anforderung authentisch ist, führen wir einen Shell-Befehl aus, um unser lokales Repository mitgit pull zu aktualisieren.

Das fertige Skript sieht folgendermaßen aus:

webhook.js

const secret = "your_secret_here";
const repo = "~/your_repo_path_here/";

const http = require('http');
const crypto = require('crypto');
const exec = require('child_process').exec;

http.createServer(function (req, res) {
    req.on('data', function(chunk) {
        let sig = "sha1=" + crypto.createHmac('sha1', secret).update(chunk.toString()).digest('hex');

        if (req.headers['x-hub-signature'] == sig) {
            exec('cd ' + repo + ' && git pull');
        }
    });

    res.end();
}).listen(8080);

Wenn Sie die Anleitung zur Einrichtung des ersten Servers befolgt haben, müssen Sie diesem Webserver erlauben, mit dem externen Web zu kommunizieren, indem Sie Datenverkehr auf Port8080zulassen:

sudo ufw allow 8080/tcp

Nachdem unser Skript eingerichtet ist, stellen wir sicher, dass es ordnungsgemäß funktioniert.

Schritt 4 - Testen des Webhooks

Wir können unseren Webhook testen, indem wirnode verwenden, um ihn in der Befehlszeile auszuführen. Starten Sie das Skript und lassen Sie den Prozess in Ihrem Terminal geöffnet:

cd ~/NodeWebhooks
nodejs webhook.js

Kehren Sie unterGithub.com zur Seite Ihres Projekts zurück. Klicken Sie in der oberen Menüleiste auf der Seite Ihres Repositorys auf die RegisterkarteSettings und anschließend im linken Navigationsmenü aufWebhooks. Klicken Sie neben dem in Schritt 1 eingerichteten Webhook aufEdit. Scrollen Sie nach unten, bis Sie den AbschnittRecent Deliveries sehen, wie in der folgenden Abbildung gezeigt:

Edit Webhook

Drücken Sie die drei Punkte ganz rechts, um die TasteRedeliver anzuzeigen. Klicken Sie bei laufendem Knotenserver aufRedeliver, um die Anforderung erneut zu senden. Sobald Sie bestätigt haben, dass Sie die Anfrage senden möchten, wird eine erfolgreiche Antwort angezeigt. Dies wird durch einen Antwortcode von200 OKnach erneuter Zustellung des Pings angezeigt.

Wir können jetzt fortfahren, um sicherzustellen, dass unser Skript im Hintergrund ausgeführt und beim Booten gestartet wird. MitCTRL+C wird der Webhook-Server des Knotens gestoppt.

[[Schritt 5 - Installieren des Webhooks als System-Service]] == Schritt 5 - Installieren des Webhooks als Systemd-Dienst

systemd ist der Task-Manager, mit dem Ubuntu Dienste steuert. Wir werden einen Dienst einrichten, mit dem wir unser Webhook-Skript beim Booten starten und mit systemd-Befehlen verwalten können, wie wir es mit jedem anderen Dienst tun würden.

Beginnen Sie mit dem Erstellen einer neuen Servicedatei:

sudo nano /etc/systemd/system/webhook.service

Fügen Sie der Servicedatei die folgende Konfiguration hinzu, die Systemd mitteilt, wie das Skript ausgeführt werden soll. Dies teilt Systemd mit, wo sich unser Knotenskript befindet, und beschreibt unseren Service.

Stellen Sie sicher, dass Siesammy durch Ihren Benutzernamen ersetzen.

/etc/systemd/system/webhook.service

[Unit]
Description=Github webhook
After=network.target

[Service]
Environment=NODE_PORT=8080
Type=simple
User=sammy
ExecStart=/usr/bin/nodejs /home/sammy/NodeWebhooks/webhook.js
Restart=on-failure

[Install]
WantedBy=multi-user.target

Aktivieren Sie den neuen Dienst, damit er beim Systemstart gestartet wird:

sudo systemctl enable webhook.service

Starten Sie jetzt den Dienst:

sudo systemctl start webhook

Stellen Sie sicher, dass der Dienst gestartet ist:

sudo systemctl status webhook

Die folgende Ausgabe zeigt an, dass der Dienst aktiv ist:

Output● webhook.service - Github webhook
   Loaded: loaded (/etc/systemd/system/webhook.service; enabled; vendor preset: enabled)
   Active: active (running) since Fri 2018-08-17 19:28:41 UTC; 6s ago
 Main PID: 9912 (nodejs)
    Tasks: 6
   Memory: 7.6M
      CPU: 95ms
   CGroup: /system.slice/webhook.service
           └─9912 /usr/bin/nodejs /home/sammy/NodeWebhooks/webhook.js

Sie können jetzt neue Commits in Ihr Repository übertragen und die Änderungen auf Ihrem Server anzeigen.

Klonen Sie auf Ihrem Desktop-Computer das Repository:

git clone https://github.com/sammy/hello_hapi.git

Nehmen Sie eine Änderung an einer der Dateien im Repository vor. Übertragen Sie dann die Datei und senden Sie Ihren Code an GitHub.

git add index.js
git commit -m "Update index file"
git push origin master

Der Webhook wird ausgelöst und Ihre Änderungen werden auf Ihrem Server angezeigt.

Fazit

Sie haben ein Node.js-Skript eingerichtet, das automatisch neue Commits für ein Remote-Repository bereitstellt. Mit diesem Vorgang können Sie zusätzliche Repositorys einrichten, die Sie überwachen möchten. Sie können es sogar so konfigurieren, dass beim Pushen Ihres Repositorys eine Website oder Anwendung für die Produktion bereitgestellt wird.