Neuigkeiten von trion.
Immer gut informiert.

Angular Anwendungen auf GitHub Pages mit GitHub Actions publizieren

Im vorhergehenden Artikel wurde der Einsatz von GitHub Actions beschrieben, um eine Angular Anwendungen auf GitHub zu testen und zu bauen.
Das Thema Deployment wurde dabei aufgrund der Vielzahl an Varianten nicht weiter behandelt. In diesem Beitrag wird nun erklärt, wie die ebenfalls von GitHub bereitgestellte Plattform zum Hosting von statischen Seiten, GitHub Pages, genutzt werden kann, um darauf eine Angular Anwendung bereitzustellen.

Der große Vorteil von clientseitigen Frameworks kommt dabei voll zur Geltung: Es wird lediglich ein simpler Webserver benötigt, der die HTML, JavaScript und CSS Dateien ausliefert. Serverseitige Logik wird für das Angular Frontend an sich nicht benötigt.

Einrichtung GitHub Pages

GitHub Pages nutzt als Speicherplatz für die auszuliefernden Dateien ebenfalls GitHub bzw. git. Dazu wird im Repository entweder ein separater Branch gh-pages erstellt, oder im master-Branch wird der Order docs verwendet.

Wir verwenden aufgrund eines einfacheren Handlings die Variante mit einem separaten Branch. Dabei wird der Branch sogar so separat, dass er mit dem master-Branch nichts zu tun hat - damit ist kein Merge o.ä. erforderlich.

Anschließend wird der neue, bisher komplett leere, Branch gepusht.

Anlegen eines separaten (leeren) Branches
$ git checkout --orphan gh-pages
$ git clean -fd
$ git commit --allow-empty -m 'gh-pages branch'
$ git push --set-upstream origin gh-pages

Bei einem Push auf diesen Branch werden die Änderungen von GitHub automatisch verfügbar gemacht. Das URL Muster ist dabei https://<organisation oder user>.github.io/<repository>/

GitHub Actions Workflow

Mit GitHub Actions lässt sich die Angular-Anwendung bauen. Nun soll das Build-Ergebnis auch auf dem gh-pages Branch bereitgestellt werden.
Dazu muss nach dem Bauen des master-Branch zum gh-pages Branch gewechselt werden, und dort die Build-Resultate gepusht werden.

Zur Veranschaulichung wurde auf die Verwendung von (bereits existierenden) GitHub Actions und auch das ng deploy-Kommando verzichtet und die Kommandos explizit im Workflow angegeben. Bei GitHub-Actions können mehrere Kommandos durch ein Pipe-Symbol zusammengefasst um dann in einem run-Schritt nacheinander abgearbeitet zu werden.
Sollen die Kommandos in einem Docker Container ausgeführt werden, geht das nicht ganz so einfach: Wir haben dazu explizit eine Shell aufgerufen und die einzelnen Kommandos dann hintereinander ausgeführt.

Leider lässt sich bei GitHub Actions der User, mit dem der Container ausgeführt wird, nicht steuern. Damit kommt es zu Konflikten bei den Dateiberechtigungen und dem jeweiligen Besitzer der Dateien innerhalb und außerhalb des Containers. Als Workaround werden daher an mehreren Stellen angelegte, und nicht mehr benötigte Dateien gelöscht, bzw. sehr weitreichende Berechtigungen für den Dateizugriff gesetzt.

Zu beachten ist noch, dass die Anwendung später in einem Unterverzeichnis abgerufen wird. Damit das mit Angular reibungslos funktioniert, wird bei dem Build das Unterverzeichnis als base-href konfiguriert.
Das Verzeichnis wird dynamisch aus der Umgebungsvariable GITHUB_REPOSITORY ermittelt.

Beispiel GitHub Actions Workflow zum Deployment einer Angular Anwendung auf GitHub Pages
name: CI
on: [push]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Check out repository
        uses: actions/checkout@v2

      - name: Check out all branches from repository
        run: |
          git fetch --no-tags --prune --depth=1 origin +refs/heads/*:refs/remotes/origin/*
          mkdir dist
          chmod a+w dist

      - name: Clean install dependencies
        run: |
          npm ci
          chmod -R a+rwx node_modules

      - name: Production build
        uses: docker://trion/ng-cli:latest
        with:
          args: /bin/sh -c "ng build --prod --progress=false --base-href=${GITHUB_REPOSITORY#*/}; rm -rf node_modules; chmod -f -R a+rwx dist; true"

      - name: Deployment auf GitHub Pages
        env:
          GITHUB_TOKEN: ${{ secrets.github_token }}
        run: |
          git config user.name "$GITHUB_ACTOR"
          git config user.email "${GITHUB_ACTOR}@example.com"
          git checkout gh-pages
          ls | grep -v dist | xargs rm -r
          find dist -mindepth 2 -exec mv {} . \;
          rm -rf dist
          git add .
          git commit -m "updated GitHub Pages"
          git remote set-url origin "https://x-access-token:${GITHUB_TOKEN}@github.com/${GITHUB_REPOSITORY}.git"
          git push --force-with-lease origin gh-pages

Um aus der GitHub Action heraus das Repository beschreiben zu dürfen, wird das von GitHub bereitgestellte github_token verwendet.
Damit lässt sich schreibend genau nur auf das Repository zugreifen, das die Action ausführt.




Zu den Themen Angular, Architektur von SPA Anwendungen und TypeScript bieten wir sowohl Beratung, Entwicklungsunterstützung als auch passende Schulungen an.

Auch für Ihren individuellen Bedarf können wir Workshops und Schulungen anbieten. Sprechen Sie uns gerne an.

Feedback oder Fragen zu einem Artikel - per Twitter @triondevelop oder E-Mail freuen wir uns auf eine Kontaktaufnahme!

Zur Desktop Version des Artikels