Ich nutze Forgejo als Git Server, und seit kürzlich habe ich Forgejo auch duch einen Runner erweitert.
Jetzt habe ich einen ersten Task für meinen Runner erzeugt, den ich gern aufschreiben möchte.
Die Aufgabe
Meine Idee: Sobald ich einen tag in ein Repo pushe, soll das folgende passieren:
- Baue ein Container Image, basierend auf dem bereitgestellten Dockerfile
- Pushe dieses Image in meine lokale Container Registry. Der Tag des Images sollte dem Tag des originalen Images entsprechen.
- Keine unsicheren Secrets!
Ein bisschen mehr Detail: Ich muss mein Apache Airflow Image erweitern durch einige virtuelle Python Environments, und per Dokumentation mache ich das durch Erweiterung des Images. Das ist für mich ein gutes Beispiel um zu lernen.
Beachte: Airflow kommt in diesem Artikel eher am rande vor, darüber schreibe ich später vielleicht. Hier fokussiere ich mich auf den Forgejo Actions-Teil.
Das Repo
Das Airflow Image liegt in meinem Repo im Verzeichnis ./airflow-image und enthält zwei wesentliche Dateien: Die requirements.txt, und das Dockerfile. Das Requirements-File ist nicht sehr aufregend, aber im Dockerfile sind ein paar Vorbereitungen notwendig, da ich den Tag den ich gepushed habe nutzen möchte als Tag für das Base Image und für das daraus entstehende Image. Daher schaut mein Dockerfile wie folgt aus:
| |
Forgejo Actions
Für die Forgejo Action erzeugen wir im Repo ein weiteres Verzeichnis /.forgejo/workflows. Zusätzlich könnte es möglich sein dass Actions für das Repo erst aktiviert werden muss; das get über die Weboberfläche im Repo unter Settings - Units.
Im workflows Verzeichnis erstellen wir jetzt die Datei build-airflow-image.yaml mit dem folgenden Inhalt:
| |
Was passiert:
name: Einfach einen Namen definieren; ich glaube dass dieser hauptsächlich auf die Darstellung wirkt.on: Hier definieren wir, wann die Action passieren soll. In meinem Fall soll sie bei Tags ausgeführt werden die mitairflow-beginnen, also zum Beispielairflow-v2.10.4.jobs.build.steps: Hier passiert die tatsächliche Arbeit.Checkout the repoundSetup Docker Buildxsind vordefinierte Actions, die unsere Arbeitsumgebung aufsetzen.Extract the correct tag: Das ist ein cooler Einzeiler, der den korrekten Tag extrahiert. Wir starten mit dem hinteren Teil des Befehls:echo ${{ env.GITHUB_REF_NAME }} | grep -oP '(?<=airflow-v)[^/]+'. Hier bekommen wir den Github Ref Namen als Input, also zum Beispielairflow-v2.10.4. Darauf passiert eingrep, der im Wesentlichen denairflow-v-Teil entfernt. Übrig bleibt der korrekte Tag (2.10.4).
Außerhalb passiert noch einecho. Dieses setzt den Output (::set-output) mit dem namentagund dem Wert2.10.4.
Eigentlich passiert hier nur ein bisschen Magie mit Shell und regulären Expressions.
Beachte: Ich nutze dieses Repo für mehrere Dinge; zum Beispiel liegen auch alle meine DAG Files darin. Das ist der Grund, warum der Tag kompliziert sein muss.- Als nächstes definieren wir die korrekte Version im Dockerfile. Wir hatten ja die Zeile
FROM apache/airflow:AIRFLOW_VERSION_PLACEHOLDERdarin, die möchten wir jetzt nachFROM apache/airflow:2.10.4ändern.
Hier hilft der vorige Schritt: Der korrekte Tag steht jetzt in der Variablensteps.extract_tag.outputs.tag. Fehlt also nur noch einsed-Befehl… - Der letzte Schritt baut das Image und schreibt es in die Image Registry. Ich habe Harbor bereits laufen, und nutze das hier. Der Schritt ist nicht allzu kompliziert, da alle Komplexität bereits in der bereitgestellten Action passiert: Login bei der Container Registry, baue das Image mit definiertem Dockerfile, tagge es korrekt und pushe es. Erneut kommt der vorher extrahierte Tag vor.
Secrets
Für die Container Registry benötigen wir einen User, da ich keine anonymen Pushes auf die Registry erlaube. Dafür benötigen wir zwei Schritte:
- Öffne im Harbor UI die Bibliothek auf die du pushen möchtest (in meinem Fall also
harbor.tech-tales.blog/chris, die Bibliothek heißt dannchris). Finde dort deRobot AccountsTab und erzeuge einen neuen Roboter. Wähle einen Namen der dir gefällt. Ich habe keinen Ablauf für den Account definiert; das kannst du gerne zu deiner Zufriedenheit anpassen.
Im zweiten Schritt des Setup wirst du gefragt, was der Robot machen können soll. Ich habe Repository Pull und Repository Push Permissions gegeben - Push ist offensichtlich benötigt, und Push geht scheinbar nicht ohne Pull.
Nach der Bestätigung bekommst du den Namen und das Passwort angezeigt. Der Name lautet in meinem fallrobot$chris+airflow-pusher, wie im Actions File ersichtilch. Das Passwort ist einfach nur ein Passwort. - Gehe jetzt ins Forgejo Interface und öffne das Repo an dem du gerade arbeitest. Gehe nach Settings - Actions - Secrets. Erzeuge ein neues Secret mit dem Namen
HARBOR_PASSWORDund als Wert das Passwort des Roboters. Beachte dass du das Secret nicht mehr sehen wirst; Forgejo sichert es verschlüsselt.
Fertig!
Wie nutze ich dieses Setup jetzt: Ich tracke die Airflow Releases. Wenn ein neues Release veröffentlich wird, erzeuge ich im Repo einen Tag mit dem Namen airflow-vx.y.z und pushe den Tag ins Repo. Dadurch startet die Action und erzeugt mein Image, so wie vorgesehen. Als Abschluss (und zur Zeit noch manuell) aktualisiere ich dann meine Airflow Installation.