Forgejo Runner

Wäre es nicht schön zu wissen, ob der zuletzt hochgeladene Code auch korrekt gebaut werden kann?
Dafür haben wir CI/CD Features und Build-Agents auf unterschiedlichen Plattformen.

Codeberg bietet dafür sein Woodpecker CI an … doch etwas versteckt findet man auch Github Actions als forgejo Workflows.


Über Github actions kann der Server bei einem Ereignis (wie: “Neuer Code eingecheckt.”) einem registrierten “Runner” auftragen, ein Script auszuführen.

Und wenn dieses Script dann den neuen Code kompiliert, dann haben wir bereits einen Buildserver aufgesetzt.

Wieder ein neues YAML

Was mich an allen CI/CD Lösungen ankotzt sind deren Uneinigkeit, wie man einen Vorgang einheitlich abbilden kann. Jede f*cking Lösung erkennt, dass YAML super geeignet ist für diesen Job … und jede f*cking Lösung löst es ein bisschen anders.
Gerade so, dass man noch abstrakt erkennt, dass alle Lösungen eigentlich gleich aufgebaut sind, aber unterschiedlich genug, dass man jede Variante separat implementieren muss und ja kein Zeichen von A nach B kopieren kann.

… aber gut … genug gelästert.

Meine action-workflows liegen in der Datei /.gitea/workflows/build-platform.yml und sind etwa so aufgebaut:

 1on: [push]
 2jobs:
 3  build-linux-x64:
 4    runs-on: docker
 5    container: opendockergate/gate-build-env:deb.10.gcc.8.1
 6    steps:
 7      - name: checkout sources
 8        uses: actions/checkout@v3
 9        with:
10          submodules: true
11      - name: run linux GCC X64 build scripts
12        run: |
13          env | sort
14          cd scripts
15          ./build-make.sh
16          cd ..
17          mkdir -p ./dist/linux_x64
18          cp -r ./build/make/deploy/bin/* ./dist/linux_x64
19          ls -l ./dist/linux_x64
20      - name: compress artifacts
21        run: |
22          tar -cJvf artifacts-linux-x64.tar.xz -C ./dist/ .
23      - name: upload artifacts
24        uses: actions/upload-artifact@v3
25        with:
26          name: artifacts-linux-x64.tar.xz
27          path: artifacts-linux-x64.tar.xz
28          retention-days: 7

Man definiert also, dass bei einem push was passieren soll, und zwar wird der Job build-linux-x64 gestartet, der auf einem Runner läuft, den man unter dem Tag docker findet, und der soll den Container opendockergate/gate-build-env:deb.10.gcc.8.1 benutzen (also mein Dockerhub Repo).

Jetzt braucht man etwas Detailwissen. Man könnte sich jetzt gleich ein Shell-Script schreiben, das per GIT alles auscheckt und dann baut, doch dafür gibt es bereits fertigen Code, der das fehlertolerant abwickelt.
Man muss nur wissen, dass unter dem Namen actions/checkout@v3 ein GIT-Clone implementiert ist, und dass sich hinter actions/upload-artifact@v3 die HTTP API zum Hochladen von Build-Ergebnissen zum Forgejo/Codeberg Server verbirgt.

Denn diese Codes werten das Gewirr von Umgebungsvariablen aus und setzen die notwendigen Aktionen um mit wenig Einstellung zum Ziel zu kommen.

In der Mitte befindet sich dann unter run “mein Buildcode”, der im geklonten Repository die nötigen Schritte setzt, damit die Sourcen gebaut werden.

Docker Image brauch nodejs

Damit actions scripts wie checkout oder upload-artifact funktionieren, brauch das Docker image zwingend nodejs installiert.

Ein Basis Build-Image für C++ unter Codeberg Actions fängt bei mir also so im Dockerfile an:

1apt-get install build-essential cmake git nodejs apt-transport-https ca-certificates

Ohne nodejs treten jede Menge Fehler auf, die nicht unmittelbar auf die fehlende Node-Installation hinweisen.

Einen Runner braucht man auch

Der forgejo-runner ist ein kleiner Dienst, den man sich von der Github Release-Seite herunterladen und auf einer gängigen Linux-Distro mit Docker-Setup installieren kann.

Zuerst setze ich also eine neue Debian Maschine auf und installiere Docker darauf:

 1sudo apt update
 2sudo apt upgrade -y
 3sudo apt install -y ca-certificates curl
 4sudo install -m 0755 -d /etc/apt/keyrings
 5sudo curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc
 6sudo chmod a+r /etc/apt/keyrings/docker.asc
 7echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian $(. /etc/os-release && echo $VERSION_CODENAME) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
 8sudo apt update
 9sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
10sudo systemctl start docker

Den forgejo-runner installiere ich dann in /opt/forgejo:

1sudo mkdir /opt/forgejo
2sudo chown $USER /opt/forgejo
3cd /opt/forgejo
4wget https://code.forgejo.org/forgejo/runner/releases/download/v3.3.0/forgejo-runner-3.3.0-linux-amd64
5chmod +x ./forgejo-runner-3.3.0-linux-amd64
6ln -s ./forgejo-runner-3.3.0-linux-amd64 ./forgejo-runner

Auf Codeberg.org erhält man in den “Actions/Runners” Einstellungen einen Registration-Token.

codeberg.org new runner screenshot

Diesen TOKEN nutzt man dann auf der Runner Maschine mit dem register Kommando und danach erzeugt man noch eine Standard-Konfiguration:

1./forgejo-runner register --no-interactive --token TOKEN --name my_runner_name --instance https://codeberg.org
2./forgejo-runner generate-config > config.yml

Nun hat man die versteckte Registrierungsdatei .runner und eine einsatzbereite Konfigurationsdatei config.yml im Verzeichnis und kann den neuen Runner auch schon im WebUI auf codeberg.org sehen.
Weitere Infos findet man dann unter docs.codeberg.org/ci/actions/.

Damit der Dienst bei jedem Systemstart ausgeführt wird, hilft einem bei systemd ein Eintrag wie in
/etc/systemd/system/forgejo-runner.service

 1[Unit]
 2Description=forgejo runner
 3After=network.target
 4
 5[Service]
 6ExecStart=/opt/forgejo/forgejo-runner daemon
 7WorkingDirectory=/opt/forgejo
 8Type=simple
 9User=mybuilduser
10Group=mybuildgroup

Die Kommandos:

1sudo systemctl enable forgejo-runner
2sudo systemctl start forgejo-runner

lassen den neuen forgejo-runner Dienst dann im Hintergrund ausführen.

Mein Runner läuft in einer kleinen VM auf meinem Server zu Hause und dieser fragt stets den Codeberg Server, ob neue Jobs anstehen.
Wenn neuer Code per git commited und gepusht wird, springt der Runner an, baut alles und lädt das Ergebnis zum Codeberg Server hoch, wo man es für einige Tage direkt wieder herunterladen kann.

Hinweis: Es dürfte ein Limit von 10 MB pro Upload gesetzt sein, wer mehr hochlädt bekommt HTTP Fehler zurück.
Ich habe meine Binaries vor dem Upload per
tar -cJvf artifacts.tar.xz -C ./output-dir/ . komprimieren lassen, um nicht zu schnell in das Limit hineinzulaufen.

Fazit

CI/CD kostenlos und alles mit Open-Source Software.
Wer hätte sich das vor 15 Jahren gedacht?

Zwar weist das Forgejo-Projekt immer auf seinen Alpha-Status hin und dass noch einige Fixes fehlen, bis man sich traut “produktiv” genannt zu werden, doch seitdem ich verstanden habe, wie das Ding funktioniert, liebe ich es.

Ja … es wäre mir lieber, wenn Gitlab, Bitbucket und Github sich auf ein YAML Format hätten einigen können, doch da das Setup so einfach umzusetzen ist, kann jedes GIT-Projekt schnell in ein CI-Projekt umgewandelt werden.

Codeberg und Forgejo beweisen, dass sie es trotz ihres vergleichsweise kleinen Team mit den großen Anbietern aufnehmen können und alle notwendigen modernen Features für ein Softwareprojekt bereitstellen können.

📧 📋 🐘 | 🔔
 

Meine Dokus über:
 
Weitere externe Links zu:
Alle extern verlinkten Webseiten stehen nicht in Zusammenhang mit opengate.at.
Für deren Inhalt wird keine Haftung übernommen.



Wenn sich eine triviale Erkenntnis mit Dummheit in der Interpretation paart, dann gibt es in der Regel Kollateralschäden in der Anwendung.
frei zitiert nach A. Van der Bellen
... also dann paaren wir mal eine komplexe Erkenntnis mit Klugheit in der Interpretation!