Einrichtung des GitHub Workflow

In den letzten beiden Teilen (1 / 2) der Serie habe ich Dir gezeigt, wie du einen Raspberry PI aufsetzt und den GitHub Runner auf diesem installierst. der nächste Schritt ist es nun, den GitHub Workflow einzurichten, der dafür sorgt, dass das System selber und die darauf laufende Anwendung (in meinem Fall Ansible) aktualisiert wird.

Für das Verständnis dieses Artikels ist grundsätzliches Git Know-How notwendig. Ich liste die notwendigen Befehle zwar auf, aber ein bisschen Verständnis links und rechts schadet nicht.

Basics / Vorbereitung

Als erstes muss das in Teil 2 der Artikelserie eingerichtete Repository lokal gekloned werden. Installiere hierfür bitte zuerst den Git Client auf deinem System.

Tip: Wenn du wissen willst, wie du Dir einen komplette Entwicklungsumgebung als Portable Edition inkl. Git Client auf deinem System einrichtest, hier eine Anleitung dafür. Mit einer ganz normalen, klassischen Installation ist das natürlich auch kein Problem.

und clone das Repository mit folgendem Befehl:

git clone https://<deine git url>/<dein repo>.git

Die vollständige URL kannst du direkt in der Ansicht deines Repositories erzeugen.

Nun öffnest du das Verzeichnis mit dem Editor deiner Wahl, ich nutze im folgenden VSCode. Im Falle von VSCode empfehle ich Dir noch die Verwendung der Extension “GitHub Actions” die für dich gleich die Gültigkeit deiner YAML Datei validiert.

Anlegen des GitHub Workflow

In diesem Schritt wird der GitHub Workflow angelegt. Erstelle dafür als erstes das Verzeichnis “.github” im root des git-Verzeichnisses. In diesem wird das Unterverzeichnis “workflows” erstellt, in dem du dann beliebige YAML Dateien (mit der Dateiendung YAML oder YML, das ist GitHub egal) erstellen kannst.

  • <root>
    • .github
      • workflows
        • workflow1.yaml
        • workflow2.yaml

Ich habe in meiner Umgebung einen Workflow der sowohl das OS als auch die von Ansible verwendeten Dateien aktualisiert. Ich gehe nun Schritt für Schritt die workflow Datei mit Dir durch, am Ende dieses Artikels findest du die Datei noch einmal als ganzes.

Trigger

Mein Master System auf dem GitHub läuft, trägt den Name “Pamela” also der GitHub Workflow in Zeile 1 erst einmal entsprechend benannt.
Die Zeile 2 beschreibt, wann der Workflow ausgeführt werden soll. GitHub stellt hier verschiedene Events zur Verfügung, deren Dokumentation du hier findest. Ggf. macht noch ein “workflow_dispatch” event zusätzlich Sinn, dass es Dir ermöglicht den Workflow auch manuell auszuführen.

1: name: pamela-update
2: on: [push]
3: 
4: env:
5:   GITHUB_WORKFLOW_DESCRIPTION: A workflow to setup the initial system of HomeNet

Preperation Jobs

Nun werden die “Jobs” beschrieben, die der Workflow ausführen soll. In diesem Workflow wird es nur eine Job geben, den ich aus diesen Gründen in Zeile 8 identisch zum Workflow benenne.

Zeile 9 beschreibt, wo der Job laufen soll. Jeder runner bekommt einen oder mehrere Tags über die du steuern kannst, welcher Job wo laufen soll. Bei kleineren Projekten läuft natürlich alles auf einem zentralen runner der mit dem Standard-Tag “self-hosted” beschrieben wird.

In Zeile 10 leiten wir nun die “Steps” ein, also die verschiedenen Schritte, die im Rahmen des Jobs durchgeführt werden sollen. Wir sehen hier 3 Schritte, in denen das Repository gecloned wird. Ich möchte das Repo jeweils in einem ein für diesen Lauf dedizierten Pfad liegen haben. Aus diesem Grund erzeuge ich erst einen 5-stelligen Zufallswert der in die Variable _GITHUB_WORKFLOW_WORKDIR geschrieben wird. Im Aschluß wird das Verzeichnis gemäß dem Zufallswert angelegt und das Repository in dieses Pfad mit dem Unterverzeichnis “HomeNet” ausgecheckt.

07: jobs:
08:   update-pamela:
09:     runs-on: self-hosted
10:     steps:
11: 
12:       - name: Create random value for checkout directory
13:         run: |
14:           _GITHUB_WORKFLOW_WORKDIR=./checkout/$(echo $RANDOM | md5sum | head -c 5; echo;); \
15:           echo GITHUB_WORKFLOW_WORKDIR=$_GITHUB_WORKFLOW_WORKDIR >> $GITHUB_ENV
16: 
17:       - name: Create checkout directory
18:         run: mkdir -p ${{ env.GITHUB_WORKFLOW_WORKDIR }}
19: 
20:       - name: Checkout base repository
21:         uses: actions/checkout@v2
22:         with:
23:           repository: Frickeldave/HomeNet
24:           path: ${{ env.GITHUB_WORKFLOW_WORKDIR }}/HomeNet

Aktualisieren des Systems und Ansible

Anschließend wird das Betriebssystem aktualisiert, python3 installiert/aktualisiert und Ansible installiert. Hier sehen wir auch fest eingetragene Versionsnummern für Ansible. Der Hintergrund ist, ich möchte die Ansible Version kontrollieren, die zum Einsatz kommt und spätestens beim Wechsel der Version das gesamte System aktualisiert wissen (Du erinnerst dich, der Workflow wird beim Push angestoßen, also wenn ich hier Versionsnummern verändere).

Ich verlassen mich hier auch blind darauf, dass die python Version schon passen wird. Im professionellen Umfeld sollten hier noch ein paar Checks eingebaut werden, für meine kleine HomeNet Umgebung reicht mir das so aus.

30:       - name: Update system
31:         run: sudo apt update -y
32: 
33:       - name: Upgrade system
34:         run: sudo apt upgrade -y
35: 
36:       - name: Install prerequisites
37:         run: sudo apt install -y curl sudo git python3 python3-pip python3-apt
38: 
39:       - name: Ansible core
40:         run: sudo python3 -m pip install ansible-core==2.15.3
41: 
42:       - name: Ansible lint
43:         run: sudo python3 -m pip install ansible-lint==6.20.3

Aktualisieren der Ansible Dateien

Jetzt geht es um den eigentlich code. Ich speichere meinen Ansible Code direkt mit im HomeNet Repository. Man kann Ihn auch in einem eigenen Repository unterbringen und dieses klonen. Das ist OK wenn das Repository public ist. Ist es private musst du auch noch einen SSH Key erzeugen und diese bei der “Clone” Action mit angeben. Das ist für das kleine HeimNet völlig unnötiger Aufwand, daher alles in ein Repository.

Im Prinzip passiert in den folgenden Zeilen nur ein simpler “Copy” aller Ansible Dateien in die richtigen Zielverzeichnisse. Auch der Einfachheit halber, kopiere ich hier alle Ansible Dateien direkt in das home Verzeichnis des github users.

48:       - name: Create ansible directory
49:         run: sudo mkdir -p /home/github/ansible
50: 
51:       - name: Create ansible logs directory
52:         run: sudo mkdir -p /home/github/ansible/logs
53: 
54:       - name: Copy ansible configuration file
55:         run: sudo cp ${{ env.GITHUB_WORKFLOW_WORKDIR }}/HomeNet/ansible/ansible.cfg /home/github/ansible/ansible.cfg
56: 
57:       - name: Copy ansible hosts directory
58:         run: sudo rsync -va ${{ env.GITHUB_WORKFLOW_WORKDIR }}/HomeNet/ansible/hosts /home/github/ansible
59: 
60:       - name: Copy ansible playbooks directory
61:         run: sudo rsync -va ${{ env.GITHUB_WORKFLOW_WORKDIR }}/HomeNet/ansible/playbooks /home/github/ansible
62: 
63:       - name: Copy ansible roles directory
64:         run: sudo rsync -va ${{ env.GITHUB_WORKFLOW_WORKDIR }}/HomeNet/ansible/roles /home/github/ansible
65: 
66:       - name: Copy ansible library directory
67:         run: sudo rsync -va ${{ env.GITHUB_WORKFLOW_WORKDIR }}/HomeNet/ansible/library /home/github/ansible
68:
69:       - name: Create the logfile directory
70:         run: |
71:           if [ ! -d /home/github/logs ]; then mkdir /home/github/logs; fi

Secret erzeugen

Damit Ansible sich auch auf remote Systeme verbinden kann (auch das master-system ist aus Ansible Sicht ein remote System), wird ein SSH key benötigt (Im Falle von Windows entweder ein Zertifikat oder entsprechende Credentials). auf jeden Zielsystem muss ein public-key liegen, auf dem ausführenden System der private key. Der private key darf natürlich nicht einfach im Klartext im Workflow erscheinen. Dafür eignen sich “GitHub-Secret”. Wie du ein Secret anlegst, zeige ich Dir unten. In den Zeilen 73-89 wird dieses GitHub-Secret ausgelesen, in eine lokale Datei geschrieben und diese entsprechend geschützt.

73:       - name: Write ansible vault secret to disk
74:         run: sudo bash -c "echo ${{ secrets.HOMENET_ANSIBLE_VAULT }} > /home/github/ansible/av.secret"
75: 
76:       - name: Change ownership of vault secret file
77:         run: sudo chown github:github "/home/github/ansible/av.secret"
78: 
79:       - name: Secure ansible vault secret file
80:         run: sudo chmod 600 "/home/github/ansible/av.secret"
81: 
82:       - name: Write ansible ssh key to disk
83:         run: sudo bash -c "echo \"${{ secrets.HOMENET_ANSIBLE_PRVKEY }}\" > /home/github/.ssh/ansible_ssh.key"
84: 
85:       - name: Change ownership of ansible private key file
86:         run: sudo chown github:github "/home/github/.ssh/ansible_ssh.key"
87: 
88:       - name: Secure ansible private key file
89:         run: sudo chmod 600 "/home/github/.ssh/ansible_ssh.key"

Um das GitHub-Secret anzulegen, navigiere in die Settings des Repositories und wechsel in “Secrets & Variables -> Actions”. Dort kannst du über den Button “New repository secret” ein neues Secret erstellen.

Einchecken der Änderung/ Workflow ausführen

Nun wird es ernst. Mit “git add .” fügst du alle bisher durchgeführten Änderungen hinzu. Anschließend führst du die Befehle “git commit -m "update to new Ansible version"” und “git push” aus, um die Änderungen mit den GitHub System zu synchronisieren.

Nachdem Checkin sollte der Workflow direkt loslaufen. Du kannst dies in der “Actions” Ansicht deines Repositories überprüfen.

Klickst du auf die entsprechende Commit-Message, erhältst du detaillierte Aussagen über die Ausführung deiner Jobs.

Fazit

Wie du siehst ist es super simpel eine GitHub Action zu definieren und auszuführen. Zudem bekommst du kostenlos ein grafisches Interface mit entsprechend detailliertem Logging. In diesem Artikel haben wir auch nur die Basics behandelt. GitHub Actions bieten jede Menge Möglichkeiten. All dies zu behandeln würde aber den Rahmen dieses Blogs sprengen und wir wollen ja keine GitHub Dokumentation schreiben.

Im nächsten Schritt werden wir nun das installierte Ansible nutzen um Anwendungen auf dem lokalen System zu installieren und einen Docker Container mit homeassistens zur Verfügung zu stellen. Abschließend findest du noch einmal das gesamte Workflow Script.

name: pamela-update
on: [push]

env:
  GITHUB_WORKFLOW_DESCRIPTION: A workflow to setup pamela, the initial system of the HomeNet environment

jobs:
  pamela-update:
    runs-on: self-hosted
    steps:

      - name: Create random value for checkout directory
        run: |
          _GITHUB_WORKFLOW_WORKDIR=./checkout/$(echo $RANDOM | md5sum | head -c 5; echo;); \
          echo GITHUB_WORKFLOW_WORKDIR=$_GITHUB_WORKFLOW_WORKDIR >> $GITHUB_ENV

      - name: Create checkout directory
        run: mkdir -p ${{ env.GITHUB_WORKFLOW_WORKDIR }}

      - name: Checkout base repository
        uses: actions/checkout@v2
        with:
          repository: Frickeldave/HomeNet
          path: ${{ env.GITHUB_WORKFLOW_WORKDIR }}/HomeNet

    #####################################################################    
    ## Update the system and install ansible
    ######################################################################

      - name: Update system
        run: sudo apt update -y

      - name: Upgrade system
        run: sudo apt upgrade -y

      - name: Install prerequisites
        run: sudo apt install -y curl sudo git python3 python3-pip python3-apt

      - name: Ansible core
        run: sudo python3 -m pip install ansible-core==2.15.3

      - name: Ansible lint
        run: sudo python3 -m pip install ansible-lint==6.20.3

      ######################################################################
      ## Update ansible files
      ######################################################################
      - name: Create ansible directory
        run: sudo mkdir -p /home/github/ansible

      - name: Create ansible logs directory
        run: sudo mkdir -p /home/github/ansible/logs

      - name: Copy ansible configuration file
        run: sudo cp ${{ env.GITHUB_WORKFLOW_WORKDIR }}/HomeNet/ansible/ansible.cfg /home/github/ansible/ansible.cfg

      - name: Copy ansible hosts directory
        run: sudo rsync -va ${{ env.GITHUB_WORKFLOW_WORKDIR }}/HomeNet/ansible/hosts /home/github/ansible

      - name: Copy ansible playbooks directory
        run: sudo rsync -va ${{ env.GITHUB_WORKFLOW_WORKDIR }}/HomeNet/ansible/playbooks /home/github/ansible

      - name: Copy ansible library directory
        run: sudo rsync -va ${{ env.GITHUB_WORKFLOW_WORKDIR }}/HomeNet/ansible/library /home/github/ansible

      - name: Create the logfile directory
        run: |
          if [ ! -d /home/github/logs ]; then mkdir /home/github/logs; fi

      - name: Write ansible vault secret to disk
        run: sudo bash -c "echo ${{ secrets.HOMENET_ANSIBLE_VAULT }} > /home/github/ansible/av.secret"

      - name: Change ownership of vault secret file
        run: sudo chown github:github "/home/github/ansible/av.secret"

      - name: Secure ansible vault secret file
        run: sudo chmod 600 "/home/github/ansible/av.secret"

      - name: Write ansible ssh key to disk
        run: sudo bash -c "echo \"${{ secrets.HOMENET_ANSIBLE_PRVKEY }}\" > /home/github/.ssh/ansible_ssh.key"

      - name: Change ownership of ansible private key file
        run: sudo chown github:github "/home/github/.ssh/ansible_ssh.key"

      - name: Secure ansible private key file
        run: sudo chmod 600 "/home/github/.ssh/ansible_ssh.key"

Schreibe einen Kommentar

WordPress Cookie Hinweis von Real Cookie Banner