CI/CD in Plesk: Node.js, React, Angular, Vue & Co. automatisch deployen
Mit Plesk CI/CD kann man Node.js, React, Angular, Vue und andere Technologien automatisch auf dem Server bereitstellen. In diesem Artikel zeige ich dir, wie Plesk CI/CD genutzt werden kann, um Deployment-Prozesse zu automatisieren und die Entwicklungszeit zu verkürzen.
Beim Entwickeln von Fullstack Anwendungen mit Node.js, Deno und Frontend Frameworks wie Vue, React oder Angular ist der Deyploment-Prozess, also der Schritt in dem die entwickelte Anwendung live gestellt wird immer ähnlich. Diese Arbeiten manuell durchzuführen benötigt sehr viel Zeit und ist bei manueller Bearbeitung auch sehr fehleranfällig. Und genau hier kommt CI/CD zum Einsatz.
In meinem Blogpost Was ist CI/CD? erfährst du alles zum Konzept von CI/CD, den CI/CD Tools und DevOps.
Was dich in diesem Tutorial erwartet:
Wir bauen eine komplette Plesk CI/CD Pipeline. Lokale Änderungen commitest du auf deinen develop Branch im Remote Respository und erstellst einen Pull Request (PR) auf deinen main Branch. Deine App wird automatisch getestet und dein Quellcode formatiert (linting) und bei Erfolg alles auf deinem main Branch gepusht. Das Frontend wird dann automatisch gebuilded. Plesk erkennt diese Änderungen und stellt alle Änderungen automatisch für deine Nutzer bereit. Du kannst diesen Workflow aber auch für statische Webseiten nutzen.
Dieses Diagramm soll visualisieren, wie die komplette Plesk CI/CD Pipeline mit samt allen Schritten aussieht. Nimm dir einen Moment Zeit und schaue dir die einzelnen Schritte genau an.
Voraussetzungen/Annahmen
Zu Beginn treffe ich ein paar Annahmen über die App, nach der die Pipeline entwickelt wird. Es ist aber natürlich nicht schlimm, wenn du andere Voraussetzungen hast, an ein paar Stellen musst du deine Plesk CI/CD Pipeline dann anpassen.
- Backend und Frontend sind in getrennten Repositories (am besten GitHub, da ich hier GitHub Actions nutze)
- Das Frontend ist mit einem JS Framework erstellt (z.B. Vue, React oder Angular). Dementsprechend kommt
npm
oderyarn
zum Einsatz - Das Backend ist eine Node.js Anwendung
- Die Plesk Git extension muss in deinem Plesk installiert sein (per Klick unter Erweiterungen > „Git“)
GitHub Actions: CI/CD Workflows erstellen
Mit GitHub Actions können wir verschiedene Workflows erstellen, die jeweils eine spezielle Aufgabe in unserer CI/CD Pipeline übernehmen. Einen neuen Workflow legst du wie folgt an.
Du erhältst diesen Editor, der eine Datei im YAML Format bereitstellt.
Hier erstellen wir jetzt verschiedene YAML-Dateien für die einzelnen Steps in unserer Pipeline.
Unit Tests ausführen
Wenn du für deinen Code Unit Tests angelegt hast, z.B. mit Mocha oder supertest, kannst du die folgende YAML-Datei verwenden. Enthält dein Code keine Tests, kann ich dir nur dringend empfehlen welche zu erstellen. In einem anderen Artikel habe ich bereits gezeigt, wie du mit ChatGPT Unit Tests generieren lassen kannst oder mithilfe von Postman deine Rest API testen kannst.
name: Execute Unit Tests on: push: branches: [ "develop" ] pull_request: branches: [ "main" ] jobs: test: runs-on: ubuntu-latest strategy: matrix: node-version: [16.x] steps: - uses: actions/checkout@v3 - name: Use Node.js ${{ matrix.node-version }} uses: actions/setup-node@v3 with: node-version: ${{ matrix.node-version }} cache: 'npm' - name: Install dependencies and run tests run: | npm install npm run test env: CI: true # set environment variable to run tests in CI mode
Diese Datei habe ich testing.yml benannt. Sie wird ausgeführt, wenn ein Commit auf dem develop Branch ankommt oder ein Pull Request auf dem main Branch angelegt wird. Sie lädt zuerst den aktuellen Code aus dem Repo, installiert dann alle Dependencies und führt dann npm run test
aus. In deiner package.json muss natürlich auch das entsprechende Skript hinterlegt sein. So sieht der Abschnitt in der package.json aus, wenn du Mocha als Test-Framework verwendest und deine Tests im test/ Ordner liegen:
{ [...] "scripts": { [...] "test": "mocha test/**/*.test.js", [...] }, [...] }
Linting/Formatting ausführen
Ich kann außerdem nur dringend dazu raten, einen Linter bzw. Formatter für dein Projekt aufzusetzen. Dieser prüft und korrigiert automatisch die Code Formatierung. Besonders bei der Arbeit mit mehreren Entwicklern ist das ein großer Vorteil, um die Code Qualität zu gewährleisten. Die YAML-Datei für GitHub Actions kann so aussehen:
name: Execute Linting on: push: branches: [ "develop" ] pull_request: branches: [ "main" ] jobs: test: runs-on: ubuntu-latest strategy: matrix: node-version: [16.x] steps: - uses: actions/checkout@v3 - name: Use Node.js ${{ matrix.node-version }} uses: actions/setup-node@v3 with: node-version: ${{ matrix.node-version }} cache: 'npm' - name: Install dependencies and lint code run: | npm install npm run lint env: CI: true # set environment variable to run tests in CI mode
Und in der package.json muss wieder das entsprechende Skript hinterlegt sein. Hier als Beispiel bei der Nutzung von eslint.
{ [...] "scripts": { [...] "lint": "./node_modules/.bin/eslint .", [...] }, [...] }
Frontend bauen
Wenn wir lokal entwickeln starten wir immer einen Entwicklungsserver auf unserem Rechner. Für den Livegang (Production) müssen wir einen Befehl wie npm run build
oder ähnliches ausführen. Diesen Prozess wollen wir jetzt automatisieren.
Mit der folgenden Vorlage werden mehrere Jobs ausgeführt. Die Dependencies werden installiert, der Code wird wieder gelintet und das Frontend wird gebaut. Optional kannst du hier wieder die Ausführung von Unit Tests ergänzen.
Im letzten Schritt pushen wir den kompletten Build auf den Branch build des gleichen Repositories. Vermutlich musst die markierte Zeile anpassen. Hier gibst du den Namen des Ordners an, in dem dein Frontend gebaut wurde. Bei Vue.js ist das standardmäßig der dist/ Ordner. Bei React ist das meist der public/APPNAME/ Ordner. Der Pfad kann aber auch über die Config des jeweiligen JS Frameworks angepasst werden.
name: Build Application on: push: branches: [ "main" ] jobs: test-and-build: runs-on: ubuntu-latest strategy: matrix: node-version: [16.x] steps: - uses: actions/checkout@v3 - name: Use Node.js ${{ matrix.node-version }} uses: actions/setup-node@v3 with: node-version: ${{ matrix.node-version }} cache: 'npm' - name: Install dependencies run: | npm ci - name: Lint code run: | npm run lint env: CI: true # set environment variable to run tests in CI mode - name: Build Frontend run: npm run build env: CI: false - name: Push to build branch uses: s0/git-publish-subdir-action@develop env: REPO: self BRANCH: build # The branch name where you want to push the assets FOLDER: ./dist # The directory where your assets are generated GITHUB_TOKEN: ${{ secrets.ACCESS_TOKEN }} # GitHub will automatically add this - you don't need to bother getting a token MESSAGE: "Build: ({sha}) {msg}" # The commit message
Sobald du die Workflow Datei abspeicherst wird der Job automatisch ausgeführt und dein Frontend gebaut und auf den build Branch gepusht. Das kann je nach Frontend auch mal 1-2 Minuten dauern.
Git Repository in Plesk einrichten
Im nächsten Schritt müssen wir unsere beiden Git Repositories in Plesk einrichten. Für Frontend und Backend richten wir jeweils eine unterschiedliche Bereitstellung aus.
Backend
Wähle für das Backend Repository folgende Einstellungen aus:
- Nutze die SSH Repository URL deines Backends (git@github.com:USERNAME/REPO.git)
- Branch: main
- Bereitstellungsmodus: automatisch
- Serverpfad: /httpdocs
- Bereitstellungsaktionen (um nicht benötigte Dateien direkt zu löschen):
- touch tmp/restart.txt
- rm -R .github/
- rm .env.template
- rm -R test/
- rm README.md
- rm .gitignore
- rm .eslintrc.js
Alles Infos zum Hosting einer Node Anwendung erfährst du in meinem ausführlichen Beitrag zum Thema Node.js App Hosting mit Plesk.
Frontend
Die zweite Repo-Instanz in Plesk ist nur fürs Frontend. Wählen hier folgende Einstellungen aus:
- Nutze die SSH Repository URL deines Frontends (git@github.com:USERNAME/REPO.git)
- Branch: build (falls dieser noch nicht existiert, erstelle ihn, den benötigen wir später)
- Serverpfad: /httpdocs/public
- Bereitsstellungsmodus: automatisch
Das Anzeigen des Frontends machen wir über unser Backend. Dazu müssen in der index.js der Node.js App folgende Zeilen ergänzt werden:
// handle production if (process.env.NODE_ENV === "production") { // static folder app.use(express.static(__dirname + "/public")); // handle SPA app.get(/.*/, (req, res) => res.sendFile(__dirname + "/public/index.html")); }
Ich habe ein Node.js Backend mit express Webserver. Nutzt du andere Technologien, kannst du das entsprechend umschreiben lassen.
Bis hierher werden unsere Dateien bereitgestellt, wenn wir den Pull manuell in Plesk ausführen. Wenn wir also lokal einen Commit machen und ihn in unser Remote Repository pushen müssten wir uns immer in Plesk anmelden und den „Jetzt Pull ausführen“ Button klicken. Diese Automatisierungen konfigurieren wir im nächsten Schritt.
Plesk Git SSH-Key in GitHub einrichten
Zuvor müssen wir aber Plesk noch erlauben auf unser privates GitHub Repository zuzugreifen. Dazu müssen wir den von Plesk erstellten öffentlichen SSH-Schlüssel kopieren.
Diesen Schlüssel musst du in deinem GitHub Account unter Settings > SSH and GPG Keys > New SSH key einfügen.
Eine ausführliche Anleitung zu diesem Schritt findest du in meinem Beitrag privates GitHub Repository mit Plesk klonen.
Webhooks: Automatisches Abrufen neuer Commits
Was haben wir bisher: Frontend und Backend werden jetzt in den richtigen Verzeichnissen auf unserem Plesk Server gehostet und unser Frontend wird automatisch mit GitHub Actions gebaut. Für einen kompletten Plesk CI/CD Workflow fehlt nur noch, dass neue Commits automatisch von Plesk erkannt werden und bereit gestellt werden. Dazu nutzen wir Webhooks.
In den Repository Einstellungen in Plesk findest du eine Webhook-URL, die du dir rauskopieren musst.
Anschließend gehst du in die Repository Einstellungen in deinem GitHub Repo unter Settings > Webooks und klickst auf Add webhook. Hier fügst du die URL ein und lässt alle anderen Einstellungen auf ihren Standardwerten.
Sollte dein Workflow nicht funktionieren und Fehlermeldungen mit fehlenden Berechtigungen erscheinen, musst du eventuell unter GitHub Settings > Developer seettings > Personal access tokens > Tokens (classic) einen neuen Token generieren und alle Berechtigungen auf „repo“ erlauben.
Das war’s! Alle Bestandteile unsere Plesk CI/CD Pipeline stehen und sind funktionsfähig.
Das Aufsetzen des Workflows hat sicherlich etwas Zeit in Anspruch genommen, dafür spart es in Zukunft sehr viel Zeit ein. 🙂
Wie fandest du diesen Beitrag?
-
Pingback: ChatGPT und KI in der Softwareentwicklung (Tipps und Best Practices)
-
Pingback: Docker vs. virtuelle Maschinen: Die wichtigsten Unterschiede verstehen