Einleitung

Als Unternehmen hilft Ihnen eine schnelle, zuverlässige Entwicklung und Bereitstellung von Software die Möglichkeit, Ihre Wettbewerbsfähigkeit zu erhöhen. Continuous Integration/Continuous Deployment (CICD) ist ein bewährtes Verfahren, um diesen Prozess zu beschleunigen und zu optimieren. Mit Github Actions steht Ihnen ein mächtiges Tool zur Verfügung, das Ihnen ermöglicht, CICD nahtlos in Ihre Prozesse einzubinden.

Was ist CICD und wie kann es Ihrem Unternehmen helfen?

Continuous Integration (CI) ist ein Entwicklungsprozess, bei dem Code automatisiert getestet und in ein gemeinsames Repository integriert wird. Durch CI werden Fehler früher im Entwicklungsprozess erkannt und behoben, was Zeit und Geld spart und die Qualität des Codes erhöht.

Continuous Deployment (CD) ist der Prozess der Bereitstellung von Codeänderungen auf die Produktionsumgebung. Der Einsatz von CD gewährleistet, dass die Software schnell und ohne Probleme auf den Markt gebracht wird.

CICD ist die Kombination aus CI und CD. Es ermöglicht es Entwicklern, Code automatisch in einer Testumgebung zu integrieren und zu testen und anschließend nahtlos auf die Produktionsumgebung zu übertragen. Dieser Prozess erhöht die Effizienz und Zuverlässigkeit von Code-Releases.

Github Actions für effizientes CICD

Github Actions ist ein Tool, das die Integration von CICD in Github Repositories erleichtert. Es bietet eine einfache und intuitive Möglichkeit, Workflows zu definieren, die bestimmte Aktionen automatisch ausführen. Dazu können bspw. das Erstellen von Docker-Images, das Durchführen von Tests oder das Bereitstellen von Codeänderungen auf eine Produktionsumgebung gehören.

Die Verwendung von Github Actions für CICD bietet Ihrem Unternehmen zahlreiche Vorteile:

  • Effizienz: Github Actions automatisiert den Prozess der Integration und Bereitstellung von Code, was Zeit spart und die Produktivität erhöht.
  • Zuverlässigkeit: Durch den Einsatz von automatisierten Tests und Überprüfungen wird sichergestellt, dass der Code fehlerfrei ist und die Qualität des Codes erhöht wird. Es kann nicht passieren, dass Code deployed wird, der vorher nicht getestet wurde.
  • Skalierbarkeit: Github Actions ermöglicht es, den CICD-Prozess nahtlos in eine Vielzahl von Anwendungen und Umgebungen zu integrieren, was das Wachstum Ihres Unternehmens unterstützt.
  • Kosteneffizienz: Die Automatisierung von CICD mit Github Actions reduziert den Bedarf an manueller Arbeit und senkt die Betriebskosten.

Sie möchten Unterstützung oder haben Interesse an einer Zusammenarbeit?

Github Actions in der Praxis

In dieser Anleitung zeigen wir Schritt für Schritt, wie Github Actions eingerichtet und genutzt werden kann. Dabei orientieren wir uns an einer unserer Open-Source Libraries, ngx-material-entity, da diese sowohl CI als auch CD mit Github Actions nutzt und zudem öffentlich einsehbar ist.

Workflow-Datei erstellen

Die Workflow-Datei ist das Herzstück Ihrer CICD-Pipeline. Sie enthält Anweisungen, wie Github Actions Ihre Builds und Deployments automatisieren soll. Um eine neue Workflow-Datei zu erstellen, gehen Sie bei Ihrem Github-Repository zum Reiter „Actions“ > „New Workflow“.

Hier gibt es die Möglichkeit einen von vielen vordefinierten Workflows auszuwählen und anzupassen, oder einen eigenen zu erstellen. In beiden Fällen wird eine .yml-Datei im Ordner .github/workflows angelegt. Alternativ können Sie die Datei auch von Hand anlegen, ohne Github zu nutzen.

Trigger definieren

Die Trigger definieren, wann Ihre Pipeline ausgeführt wird. Zum Beispiel können Sie Ihre Pipeline ausführen lassen, wenn eine neue Änderung in Ihrem Repository vorgenommen wird oder wenn ein Pull Request erstellt wird. In der Workflow-Datei definieren Sie die Trigger mit Hilfe der „on“ Anweisung. Im Folgenden einmal das Produktivbeispiel unserer Library für den CI-Prozess:

name: CI/CD
on: push
YAML

Der Workflow reagiert auf jeden Push auf jedem Branch. Github Actions bietet allerdings auch die Möglichkeit, den Trigger bspw. auf bestimmte Branches zu begrenzen. Mehr dazu später.

Jobs definieren

Ein Job definiert das, was in Ihrer Pipeline ausgeführt werden soll. Sie können mehrere Jobs in einer Workflow-Datei definieren und diese entweder parallel oder sequenziell abarbeiten lassen. Ein Job kann dabei wiederum aus mehreren Schritten („steps“) bestehen, so gibt es bei ngx-material-entity nur einen Job, dieser führt aber mehrere Dinge aus:

name: CI/CD
# Controls when the action will run.
on: push
# workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
    test:
        # The type of runner that the job will run on
        runs-on: ubuntu-latest
        steps:
            # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
            - uses: actions/checkout@v3
            # runs npm i inside the root directory
            - name: npm i root
              run: |
                  cd $GITHUB_WORKSPACE
                  npm i
            # runs npm i inside the ngx-material-entity directory
            - name: npm i
              run: |
                  cd $GITHUB_WORKSPACE/projects/ngx-material-entity
                  npm i
            # builds the library
            - name: build package
              run: |
                  cd $GITHUB_WORKSPACE
                  npm run build:prod
            # runs linting
            - name: Linting
              run: |
                  cd $GITHUB_WORKSPACE
                  npm run lint
            # runs jest tests
            - name: Jest
              run: |
                  cd $GITHUB_WORKSPACE
                  npm run test
            # runs cypress e2e tests
            - name: Cypress
              run: |
                  cd $GITHUB_WORKSPACE
                  npm run e2e:run
            # updates codecov for the badge
            - name: update codecov
              uses: codecov/codecov-action@v3
              with:
                token: ${{ secrets.CODECOV_TOKEN }}
YAML

Dieser Workflow definiert einen Job mit dem Namen „test“, der auf der neuesten Ubuntu-Version ausgeführt wird. In den einzelnen Schritten wird:

  1. Der Code ausgecheckt
  2. Abhängigkeiten installiert
  3. Die Library gebaut
  4. Linting ausgeführt
  5. Unit- und End-to-End Tests ausgeführt

Als Schritt kann aus einer Vielzahl vordefinierter Schritte ausgewählt werden. Oder man definiert selbst was ausgeführt werden soll. In der Regel bestehen Workflow-Dateien aus einer Mischung der beiden Varianten.

Vorgefertigter Schritt

Ein vorgefertigter Schritt ist sehr simpel und lässt sich meistens innerhalb von einer Zeile definieren. So beginnt bspw. fast jeder Workflow mit dem Auschecken des Codes:

name: CI/CD
# Controls when the action will run.
on: push
# workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
    test:
        # The type of runner that the job will run on
        runs-on: ubuntu-latest
        steps:
            # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
            - uses: actions/checkout@v3
YAML

Durch das uses: actions/checkout@v3 wird das Repository unter $GITHUB_WORKSPACE für andere Schritte bereitgestellt.

Eigene Schritte

Mit einem eigenen Schritt haben Sie die volle Kontrolle über das, was ausgeführt werden soll. Wenn Sie Ubuntu als „runs-on“ definiert haben befinden Sie sich zu Beginn des Schritts als Root User auf dem Betriebssytem. Sie können also mit jeglichen zur Verfügung stehenden Linux-Befehlen arbeiten. Ein Beispiel dafür befindet sich in den Zeilen 12-16:

name: CI/CD
# Controls when the action will run.
on: push
# workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
    test:
        # The type of runner that the job will run on
        runs-on: ubuntu-latest
        steps:
            # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
            - uses: actions/checkout@v3
            # runs npm i inside the root directory
            - name: npm i root
              run: |
                  cd $GITHUB_WORKSPACE
                  npm i
YAML

Mit name: npm i root wird lediglich ein name für den Schritt festgelegt. Die eigentliche Logik findet unter run: #... statt. Die | zu Beginn gibt dabei an, dass die Befehle hintereinander ausgeführt werden sollen. Der Schritt navigiert in den zuvor ausgecheckten Workspace um dort mit npm i Abhängigkeiten zu installieren. $GITHUB_WORKSPACE wird dabei durch den zuvor ausgeführten Schritt zur Verfügung gestellt und gibt das root-Verzeichnis des Repositories an.

Secrets

Ein weiterer Schritt der ausgeführt wird ist das Bereitstellen der Code Coverage über codecov.io, um eine Badge in der README Datei anzuzeigen:

            # ...
            # updates codecov for the badge
            - name: update codecov
              uses: codecov/codecov-action@v3
              with:
                token: ${{ secrets.CODECOV_TOKEN }}
YAML

Wie am uses: codecov/codecov-action@v3 zu erkennen handelt es sich um einen vordefinierten Schritt. Eine Besonderheit ist, dass hier der Parameter „token“ angegeben wurde. Dieser wird benötigt, um das Repository zuordnen zu können. Da dies nur von berechtigten Nutzern erfolgen soll, befindet sich das Token hier nicht im Klartext sondern wird als Secret erst zur Laufzeit eingefügt. Auch Datenbankpasswörter etc. sollten nie im Klartext vorliegen, auch nicht bei privaten Git-Repositories.

Um solche Secrets zu definieren gehen Sie unter dem Github Repository zu „Einstellungen“ > „Secrets and variables“ > „Actions“. Dort können Sie alle sicherheitskritischen Informationen als KeyValue Paare aufbewahren.