Einführung
Software Engineering ist ein schnelllebiger und wettbewerbsintensiver Bereich. Wenn Sie Ihre Produkte schneller für die Benutzer bereitstellen, verschafft Ihnen das einen Vorteil gegenüber Ihren Mitbewerbern. Positiv zu vermerken ist, dass es bewährte Branchenpraktiken gibt, die Unternehmen dabei helfen, gleiche Voraussetzungen zu schaffen.
Continuous Integration und Continuous Development (CICD) ist ein Beispiel für eine Strategie, die bewährte Branchenpraktiken nutzt, um Unternehmen in diesem wettbewerbsintensiven Bereich einen Vorteil zu verschaffen.
GitHub, ein webbasiertes Repository mit Git, einem Versionskontrollwerkzeug, ermöglicht es Softwareentwicklern, -ingenieuren und -architekten, CI/CD zu implementieren. Continuous Development (CD) ist die Praxis der Automatisierung von Builds, Tests und Deployments. Continuous Integration (CI) ermöglicht es vielen Personen, am selben Projekt zusammenzuarbeiten und zu überprüfen, ob der Code funktioniert, ohne sich über Merge-Konflikte Gedanken machen zu müssen.
GitHub Actions ermöglichen es uns, Schritte zu schreiben, die Builds, Tests und Deployments automatisieren.
In diesem Tutorial lernen Sie, wie Sie Continuous Integration mit GitHub Actions einrichten. Wir beginnen mit der Einrichtung eines Git-Repositorys zum Hosten unseres Codes. Anschließend konfigurieren wir einen GitHub-CI-Prozess, um Änderungen in unserem Code zu überwachen, einen CI-Runner zu initiieren, um Tests auszuführen, und unsere Anwendung auf einem Ubuntu 22.04-Server mit Nginx zu erstellen und bereitzustellen.
Voraussetzungen
Um diesem Tutorial folgen zu können, benötigen Sie Folgendes:
-
Einen Server mit Ubuntu 22.04. Sie können diesem Tutorial für die erste Einrichtung des Ubuntu-Servers, einen Nicht-Root-Benutzer hinzufügen, und die UFW-Firewall von Ubuntu aktivieren.
-
Sie müssen Node.js auf Ihrem Server installiert haben, vorzugsweise in Version 14 oder höher. Wir haben ein Tutorial über die Installation von Node.js auf Ubuntu.
-
Sie müssen die Nginx-Serversoftware installiert haben. Wir haben eine Anleitung über die Installation von Nginx auf einem Server mit Ubuntu.
-
Sie benötigen Docker und Docker Compose auf Ihrem lokalen Rechner installiert, um eine isolierte Entwicklungsumgebung auszuführen. Bitte folgen Sie unserem Tutorial, um zu lernen, wie man Docker installiert und bedient in der Cloud.
Da wir nun alles haben, was wir brauchen, fangen wir an.
Schritt 1. Klonen des Projekt-Repositorys.
Wir werden dieses Tutorial auf Reactjs aufbauen, einer deklarativen Javascript-Bibliothek zur Erstellung von Benutzeroberflächen. Wenn Sie ein neues Projekt von Grund auf neu einrichten möchten, können Sie diese Ressource zur Einrichtung einer React-App verwenden. Der Kürze halber verwenden wir einen Klon dieses React.js-Repos das wir bereits auf GitHub eingerichtet haben.
Die Anwendung, die wir klonen, ist eine einfache React-Anwendung mit react-router 6 und einem Test, der mit React Testing Library durchgeführt wurde, was uns Methoden für den Zugriff auf das DOM bietet.
Um das Repository zu klonen, klicken Sie auf die grüne Schaltfläche und kopieren Sie die URL.

Öffnen Sie das Terminal in Ihrem Arbeitsbereich und führen Sie den folgenden Befehl aus, um die App zu klonen:
|
1 |
git clone git@github.com:EspiraMarvin/cicd-tut.git |
Sobald Sie das Repository geklont haben, navigieren Sie in das Projektverzeichnis:
|
1 |
cd cicd-tut |
Führen Sie den Befehl docker-compose up aus, um die App zu erstellen und auszuführen:
|
1 |
docker-compose up --build --force-recreate |
Wenn der Prozess abgeschlossen ist, rufen Sie http://localhost:3000
Sie sollten etwas Ähnliches wie das hier sehen:

Schritt 2. Die Datei Node.js.yml verstehen.
In diesem Schritt werden wir die Direktiven in der GitHub-Yaml-Datei definieren, um zu verstehen, was vor sich geht. Im Repository gibt es ein Verzeichnis .github/workflows das eine node.js.yml-Datei enthält, die Workflow-Schritte enthält, denen GitHub-Runner folgen, nachdem Sie Änderungen an Ihr Code-Repository auf GitHub übertragen haben. YAML-Syntax wird verwendet, um Workflows für GitHub Actions zu schreiben. YAML-Dateien enden mit der Dateiendung yaml oder yml.
Öffnen Sie die node.js.yml-Datei, sie sollte so aussehen:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
name: cicd-tut on: push: branches: [ "main" ] pull_request: branches: [ "main" ] jobs: build: # Der Typ des Runners, auf dem der Job ausgeführt wird runs-on: self-hosted strategy: matrix: node-version: [16.x] # Schritte stellen eine Abfolge von Aufgaben dar, die als Teil des Jobs ausgeführt werden steps: - name: 'Checkout' uses: actions/checkout@v3 - name: 'Node-Aktionen einrichten' uses: actions/setup-node@v3 with: node-version: "16" cache: 'npm' - run: npm i - run: npm test - run: npm run build # - run: cp -r ~/actions-runner/cicd-react/react-tut-test/react-tut-test/build /var/www/react-cicd |
Zum Zeitpunkt des Schreibens dieses Tutorials haben wir Version 16 von Node.js 16 verwendet. Lassen Sie uns nun den GitHub Actions-Workflow verstehen:
-
name
name: cicd-tut
Der Name Ihres Workflows. Dieser Name wird in Ihrem Repository im Actions-Tab angezeigt.
-
on
|
1 2 3 4 5 |
on: push: branches: [ "main" ] pull_request: branches: [ "main" ] |
on wird verwendet, um Ereignisse zu definieren. Ereignisse können automatisch einen Workflow auslösen oder für später geplant werden. Ereignisse können einzeln oder mehrfach sein, Sie können auch Workflow-Ausführungen auf bestimmte Branches, Tags oder Dateien beschränken. Dies funktioniert wie ein Filter.
In unserer YAML-Datei definieren wir mehrere automatische Ereignisse, diese sind:
-
Ein push-Ereignis wird ausgelöst, wenn Code in ein Repository übertragen wird
-
Ein pull_request-Ereignis wird ausgelöst, wenn ein Pull Request auf dem Main-Branch erstellt wird.
Wir geben einen Branch-Namen main an, um die Workflow-Ausführung auf diesen Branch zu beschränken. Wir können auch Branches angeben, die ignoriert werden sollen, indem wir das !-Flag gefolgt vom Branch-Namen verwenden.
-
jobs
Ein Workflow besteht im Wesentlichen aus einem oder mehreren Jobs. Diese Jobs laufen nacheinander vom ersten bis zum letzten ab.
|
1 2 3 4 |
jobs: build: # Der Typ des Runners, auf dem der Job ausgeführt wird runs-on: self-hosted |
Jeder Job wird in einer Runner-Umgebung ausgeführt, die durch runs-on angegeben ist. Sie können Jobs entweder auf GitHub-Runnern ausführen, die durch ubuntu-latest gekennzeichnet sind, oder auf einem self-hosted-Runner, der durch self-hosted gekennzeichnet ist. Ihre Wahl hängt von der Anzahl der benötigten Jobs ab. Mit selbstgehosteten Runnern haben Sie mehr Flexibilität und Kontrolle über die Ressourcen.
Im nächsten Schritt werden wir unsere Jobs zuerst auf GitHub-Runnern ausführen und später einen selbstgehosteten GitHub-Runner auf unserem eigenen Server einrichten.
-
strategy
Mit Strategy können wir Variablen in einer einzelnen Jobdefinition verwenden, um automatisch mehrere Jobläufe zu erstellen, die auf den Kombinationen von Variablen basieren.
In unserer YAML-Datei haben wir eine Variable für unsere Node-Version. Wenn wir jedoch eine weitere für die Node-Version 18 hinzufügen, wie folgt: node-version: [16.x, 18.x], dann erstellt die Matrix-Strategie 2 Jobläufe für unsere React-Anwendung sowohl für die Node-Versionen 16 als auch 18.
|
1 2 3 |
strategy: matrix: node-version: [16.x] |
-
steps
Schritte (Steps) sind eine Abfolge von Aufgaben, die einen Job ausmachen. Schritte können Befehle ausführen, Aufgaben einrichten, Aktionen in Ihrem öffentlichen Repository oder in einer Docker-Registry veröffentlichte Aktionen ausführen.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
steps: - name: 'Checkout' uses: actions/checkout@v3 - name: 'Node-Aktionen einrichten' uses: actions/setup-node@v3 with: node-version: "16" cache: 'npm' - run: npm i - run: npm test - run: npm run build |
Ein Schritt hat einen Namen. Obwohl er optional ist, können Sie ihn verwenden, um eine einfache Möglichkeit zur Identifizierung des Namens für Ihren Schritt anzugeben, der auf GitHub angezeigt wird.
In einem Schritt können Sie eine Aktion auswählen, die in Ihrem Job ausgeführt werden soll; Aktionen sind wiederverwendbar. Versionen von Aktionen werden bei der Definition einer Aktion angegeben. Dies ist wichtig, da es verhindert, dass Ihr Workflow unterbrochen wird, wenn der Eigentümer der Aktion ein Update veröffentlicht.
Im obigen Code-Snippet ist checkout@v3 ein Beispiel für eine Aktion mit einer bestimmten Version 3. Diese Aktion checkt Ihr Repository aus, damit Ihr Workflow darauf zugreifen kann.
Einige Aktionen wie die actions/setup-node@v3 oben haben Eingaben, die mit dem with-Schlüsselwort gekennzeichnet sind. Die Setup-Node-Aktionen erfordern die Node-Version 16 und dass npm gecacht wird.
-
run
Diese Aktion führt Befehlszeilenprogramme über die Shell des Betriebssystems aus.
In der obigen YAML-Datei haben wir drei Befehle, die alle in derselben Shell in der Runner-Umgebung ausgeführt werden.
-
Der erste Befehl npm i installiert alle Abhängigkeiten, die von unserer React-Anwendung benötigt werden.
-
Der zweite npm test, führt den von uns geschriebenen Test aus. Der Test erwartet, dass der Text learn react auf der Startseite gerendert wird.
-
Zuletzt npm run build -Befehl erstellt ein Build-Verzeichnis mit einem Produktions-Build unserer Anwendung. Später werden wir dieses Build-Verzeichnis in unserem Nginx-Server-Block.
Schritt 3. Testen von GitHub CI mit GitHub-Runnern.
In diesem Schritt testen wir den Continuous-Integration-Prozess mit GitHub-Runnern. Beginnen Sie mit dem Öffnen der node.js.yml-Datei. Ändern Sie den Typ des Runners, auf dem die Aktionen ausgeführt werden, in ubuntu-latest. Der Zweck besteht darin, zu testen, ob der GitHub-Workflow auf GitHub-Runnern einwandfrei funktioniert, bevor wir unsere eigenen selbstgehosteten Runner einrichten.
|
1 2 3 |
jobs: build: runs-on: ubuntu-latest |
Erstellen Sie ein neues Repository in Ihrem GitHub-Konto. Bevor wir fortfahren, gehen Sie zurück zu Ihrem Workspace-Verzeichnis und löschen Sie das .git-Verzeichnis. Wenn Sie es nicht sehen können, überprüfen Sie Ihre versteckten Dateien. Sie können den folgenden Befehl in Ihrem Terminal verwenden, um das Verzeichnis zu löschen:
|
1 |
rm -rf .git |
Jetzt können Sie alle Ihre Projektdateien mit git add hinzufügen, committen und in Ihr Repository pushen. Wenn Sie nicht weiterkommen, nutzen Sie diese Anleitung zum Verbinden Ihres Projektordners mit dem GitHub-Repository das Sie oben erstellt haben.
Wenn Sie fertig sind, klicken Sie auf den Reiter Code in Ihrem Repo. Sie sehen einen kleinen orangefarbenen Punkt neben der Gesamtzahl der Commits. Wenn Sie darauf klicken, sehen Sie ein Modal ähnlich dem folgenden, das anzeigt, dass Ihr Workflow in die Warteschlange eingereiht wurde:

Klicken Sie nun auf den Link Details im Modal oder gehen Sie zum Reiter Actions. Sie sehen jeden Schritt des node.js.yml-Workflows, der von GitHub-Runnern ausgeführt wird:

Wenn es erfolgreich war, klicken Sie auf den Reiter Actions. Er sollte so aussehen:

Und das war’s auch schon. Der kleine orangefarbene Punkt auf unserem Code-Reiter sollte jetzt ein grünes Häkchen sein. Der GitHub-Runner hat unsere Anwendung erfolgreich erstellt.
Now, let’s go a step further and change the build environment to use GitHub self-hosted runners in our own Ubuntu-Server-Infrastruktur.
Schritt 4. Einrichten des GitHub-Workflows zur Verwendung eines selbstgehosteten Runners.
Bevor wir den selbstgehosteten Runner auf unserem Server installieren, gehen wir zurück zu unserem Workspace und bearbeiten die node.js.yml -Workflow-Datei, damit sie auf selbstgehosteten GitHub-Runnern ausgeführt wird.
|
1 2 3 |
jobs: build: runs-on: self-hosted |
Wenn Sie die Änderungen zu diesem Zeitpunkt committen, wird der Job in die Warteschlange eingereiht, da noch kein selbstgehosteter Runner definiert wurde.
Klicken Sie in Ihrem Repository auf den Reiter
Settings. Klicken Sie in der linken Seitenleiste auf
Actions, und klicken Sie dann auf
Runners:

Klicken Sie auf New self-hosted runner, und wählen Sie Linux als Betriebssystem aus.
Sie sehen Anweisungen, die Ihnen zeigen, wie Sie den Runner herunterladen und auf Ihrem Server installieren.
Schritt 5. Installieren und Konfigurieren eines selbstgehosteten GitHub-Runners auf unserem Server.
In diesem Schritt werden wir einen selbstgehosteten GitHub-Runner einrichten. Ein selbstgehosteter Runner ist ein System, das die Ausführung von Jobs aus GitHub Actions auf der GitHub-Website bereitstellen und verwalten kann. Ein Vorteil des selbstgehosteten Runners gegenüber dem von GitHub gehosteten Runner ist die Flexibilität. Er bietet mehr Kontrolle über das Betriebssystem, die Hardware und andere Tools, die an Ihre gewünschten Anwendungsanforderungen angepasst werden können.
Selbstgehostete Runner können auf verschiedenen Ebenen hinzugefügt werden, wie z. B.:
-
Runner auf Repository-Ebene, diese sind für ein einzelnes Repository bestimmt.
-
Runner auf Organisationsebene, diese können Jobs für mehrere Repositories in einer Organisation verarbeiten.
-
Enterprise-Ebene, die mehreren Organisationen zugewiesen werden kann.
Um fortzufahren, melden Sie sich über SSH auf Ihrem Server an:
|
1 |
ssh username@server_ip |
Wechseln Sie mit dem Befehl in Ihr Home-Verzeichnis:
|
1 |
cd ~ |
Erstellen Sie dann ein Verzeichnis namens action-runners und navigieren Sie hinein:
|
1 |
mkdir actions-runner && cd actions-runner |
Laden Sie als Nächstes die neueste Version des Runner-Pakets herunter:
|
1 |
curl -o actions-runner-linux-x64-2.298.2.tar.gz -L https://github.com/actions/runner/releases/download/v2.298.2/actions-runner-linux-x64-2.298.2.tar.gz |
Entpacken Sie dann das heruntergeladene Paket mit dem Befehl:
|
1 |
tar xzf ./actions-runner-linux-x64-2.298.2.tar.gz |
Zurück in Ihrem Repository, klicken Sie auf der Registerkarte Settings im linken Seitenbereich auf Actions, dann auf Runners, genau wie wir es in Step 4.
Sie sehen einen aufgelisteten Befehl, der ein Token enthält, das Ihren selbstgehosteten Runner mit Ihrem GitHub-Repository verknüpft. Während Sie sich noch in dem Verzeichnis befinden, in das Sie den GitHub-Runner-Code entpackt haben, verwenden Sie den aufgelisteten Befehl, um Ihren Runner zu verknüpfen, zum Beispiel:
|
1 |
./config.sh --url https://github.com/EspiraMarvin/react-tut-test --token XXXXXXXXXXXXXXXXXXXXXXXXXXX |
Es sollte sich erfolgreich authentifizieren:

Press enter for the Default runner group.
Geben Sie dann einen Namen für Ihren Runner ein, zum Beispiel my-runner, und drücken Sie die Eingabetaste.
Drücken Sie die Eingabetaste, um das Hinzufügen weiterer Labels zu überspringen. Sie sollten die Erfolgsmeldung im folgenden Screenshot sehen:

Geben Sie den Namen Ihres Arbeitsverzeichnisses ein, zum Beispiel react-cicd, es sollte erfolgreich sein mit dem Text settings saved.
Führen Sie schließlich ./run.sh aus, dies sollte Connected to Github:

anzeigen. Aber dies läuft nicht im Hintergrund. Wenn wir ctrl+c in unserem Terminal eingeben, wird der Runner gestoppt. Wir müssen ihn durch den .svc.sh Dienst ersetzen, damit der Runner als Dienst weiterläuft und wir weiterhin mit ihm interagieren können.
Stoppen Sie den Runner mit ctrl+c. Sie können den .svc.sh-Dienst installieren, indem Sie folgenden Befehl ausführen:
|
1 |
sudo ./svc.sh install |
Sobald er installiert ist, starten Sie den Dienst mit dem Befehl:
|
1 |
sudo ./svc.sh start |
Dies sollte erfolgreich sein und active (running).
anzeigen. Um zu bestätigen, dass der svc.sh Dienst aktiv ist und läuft, führen Sie den Befehl aus:
|
1 |
sudo ./svc/sh status |

An diesem Punkt sollte jeder Workflow, der eventuell in der Warteschlange auf einen selbstgehosteten Runner gewartet hat, erfolgreich ausgeführt werden. Sie können auch eine Datei bearbeiten und Dinge ausprobieren. Ändern Sie beispielsweise die Über.tsx-Datei, committen und pushen Sie die Änderungen. Der selbstgehostete Runner wird den Job erfolgreich abschließen.
Schritt 6. Einrichten des Nginx-Server-Blocks
In diesem Schritt werden wir einen Server-Block in Nginx einrichten, um die Build-Version unserer React-Anwendung anzuzeigen. Wir haben ein Tutorial zum Einrichten von Nginx-Server-Blöcken, das Sie vielleicht hilfreich finden.
Unten finden Sie ein Beispiel für einen in diesem Tutorial verwendeten Server-Block:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
server { listen 80; listen [::]:80; server_name react.test; root /var/www/react-cicd/build; index index.html index.htm index.nginx-debian.html; add_header X-Frame-Options "SAMEORIGIN"; add_header X-XSS-Protection "1; mode=block"; add_header X-Content-Type-Options "nosniff"; charset utf-8; location / { try_files $uri $uri/ =404; } } |
Sie erstellen eine Nginx-Server-Block-Konfigurationsdatei im Verzeichnis /etc/nginx/sites-available .
Öffnen Sie eine Datei für die Server-Block-Konfiguration Ihrer Website mit dem Nano-Editor über den Befehl:
|
1 |
sudo nano /etc/nginx/sites-available/react-cicd |
Kopieren Sie den oben freigegebenen Server-Block, passen Sie ihn an Ihre Verzeichnispfade an und fügen Sie ihn in die geöffnete Datei ein. Wenn Sie mit der Bearbeitung fertig sind, drücken Sie Strg+x, drücken Sie dann y und Eingabe zum Speichern und Beenden.
Erstellen Sie nach dem Speichern einen Symlink für die Server-Block-Konfiguration react-cicd von /etc/nginx/sites-available nach /etc/nginx/sites-enabled indem Sie folgenden Befehl ausführen:
|
1 |
sudo ln -s /etc/nginx/sites-available/react-cicd /etc/nginx/sites-enabled/ |
Damit die Änderungen wirksam werden, müssen Sie Nginx neu starten. Bevor Sie den Nginx-Dienst jedoch neu starten können, überprüfen Sie, ob die Nginx-Konfigurationen gültig sind, indem Sie folgenden Befehl ausführen:
|
1 |
sudo nginx -t |
Wenn die Konfiguration korrekt ist, sollte der Test erfolgreich sein.
Haben Sie den Wert der Direktive server_name “ react.test ” im Server-Block bemerkt? Sie fügen diesen Wert in Ihre hosts -Datei auf Ihrem lokalen Rechner ein. Dies ermöglicht es Ihnen, die Anwendung in Ihrem Browser zu öffnen. Dieser Schritt ist nur für virtuelle Domains erforderlich, die in lokalen Entwicklungsumgebungen verwendet werden. Wenn Sie einen registrierten Domainnamen haben, der mit einer öffentlichen IP Ihres Servers verknüpft ist, sollte der Domainname bereits in Ihrem Browser erreichbar sein.
Öffnen Sie auf Ihrem lokalen Rechner die hosts-Datei mit dem Befehl:
|
1 |
sudo nano /etc/hosts |
Fügen Sie in der hosts-Datei die IP-Adresse Ihres Servers hinzu, z. B. 127.0.0.1, gefolgt von Ihrem virtuellen Domainnamen.
Ein Beispiel wird unten gezeigt. Schließen Sie dann die Datei und speichern Sie:
|
1 |
192.168.3.123 react.test |
Zurück auf Ihrem Server im Verzeichnis /var/www erstellen Sie ein neues Verzeichnis. Sie können es react-cicd nennen, indem Sie Folgendes ausführen:
|
1 |
mkdir react-cicd |
In dieser Phase werden wir die Auskommentierung des letzten Befehls in der node.js.yml -Datei aufheben.
Dieser Befehl kopiert den Build-Ordner unserer React-Anwendung von der Stelle, an der wir unseren Arbeitsordner im Verzeichnis actions-runner im vorherigen Schritt 5.
angegeben haben, und legt den Ordner public im Verzeichnis /var/www/react-cicd ab.
Der Server-Block kann nun auf unsere App zugreifen und sie in einem Browser anzeigen.
Starten Sie zuletzt den Nginx-Dienst mit dem Befehl neu:
|
1 |
sudo service nginx restart |
Jetzt können Sie eine Änderung in der Datei Über.tsx vornehmen, Ihre Änderungen committen und in Ihr Repository pushen. Nach einem erfolgreichen Build sehen Sie die Build-Version Ihrer React-App unter http://react.test oder unter dem von Ihnen angegebenen Domainnamen. Vermeiden Sie es, das Element href in der Datei Home.tsx zu bearbeiten, da dies dazu führen kann, dass der bereits geschriebene Test fehlschlägt. Der Tab Actions in Ihrem Repository sollte ebenfalls den abgeschlossenen Job-Build anzeigen.

Fazit
Die kontinuierliche Integration mit Github Actions bringt viele Vorteile mit sich, darunter eine gute Entwicklererfahrung, Unterstützung bei kontinuierlichen Tests, einfachere Zusammenarbeit in größeren Teams, verkürzte Entwicklungszeit, schnelle Veröffentlichungen neuer Funktionen, Echtzeit-Feedback und Kundenzufriedenheit, was Ihnen einen Vorsprung vor Ihren Mitbewerbern verschafft. Um auf diesem Wissen aufzubauen, möchten Sie vielleicht auch mehr erfahren über das Einrichten von GitLab Continuous Integration (CI) Pipelines auf Ubuntu. und die Verwendung einer selbstverwalteten GitLab-Instanz, um Ihre Docker-Images zu hosten und private Builds auszuführen.
Viel Spaß beim Computing!
Kommentare
Noch keine Kommentare. Schreiben Sie den ersten.