14 KiB
Gitea Actions und Container Registry
Das Projekt liegt auf Gitea. Der Workflow prüft Python und JavaScript, baut das Image und führt den Container-Smoke-Test aus. Bei aktivierter Veröffentlichung lädt er dasselbe getestete Image in die Gitea Container Registry. Der Workflow endet beim Image-Push; die Schritte auf dem Zielserver stehen in der Deployment-Anleitung.
Gitea und Runner einrichten
In den Repository-Einstellungen Actions aktivieren und unter Settings → Actions → Runners einen registrierten Runner prüfen oder einrichten. Gitea benötigt einen eigenen Runner-Dienst; ein GitHub-Runner-Label stellt keine Rechenkapazität bereit. Gitea Actions einrichten.
Alle Jobs verwenden vars.AIS_RUNNER_LABEL oder, wenn die Variable nicht gesetzt
ist, ubuntu-latest. Das ausgewählte Label muss einem für dieses Repository
verfügbaren, erreichbaren Linux-amd64-Runner entsprechen. Die Angabe
ubuntu-latest wählt ein Runner-Label; sie installiert kein Ubuntu-Image.
Für ein anderes Label in Settings → Actions → Variables beispielsweise
AIS_RUNNER_LABEL=ais-ci setzen und genau dieses Label am Runner konfigurieren.
Die tatsächliche Job-Umgebung benötigt Git, Bash, OpenSSL, ssh-keygen, Python
3.13 mit venv, Node.js 24 sowie Docker CLI und Buildx mit Zugriff auf einen
laufenden Docker-Daemon. Die Setup-Actions richten Python 3.13 und Node.js 24
für ihre jeweiligen Jobs ein. Die Umgebung muss außerdem bereits die
JavaScript-Laufzeit zum Ausführen der Actions unterstützen. Bei einem
Container-Runner müssen Werkzeuge und Docker-Zugriff im Job-Container verfügbar
sein, nicht nur auf dem Host. Ein Standard-Node-Image allein enthält nicht die
gesamte Build-Umgebung. Runner-Konfiguration und Label-Zuordnung sind in der
Runner-Anleitung
beschrieben.
Der Runner muss Gitea, die Registry, die absoluten Action-URLs im Workflow und
die Downloadquellen für Python, Node.js, Python-Pakete und das Docker-Basisimage
erreichen. Die Actions sind auf vollständige Commit-SHAs festgelegt.
Der Artefakt-Upload verwendet die Gitea-kompatible Action
https://gitea.com/actions/gitea-upload-artifact.
Diese Build-Umgebung ist unabhängig vom AIS-Host-Runner für die Postinstallation auf Proxmox-Hosts. CI-Code mit Docker-Zugriff auf einer dafür vorgesehenen Build-Maschine ausführen; Änderungen an Workflow und CI-Skripten vor der Übernahme prüfen.
Registry und Veröffentlichung einrichten
Ohne PUBLISH_IMAGES=true führen alle Refs ausschließlich Prüfungen durch.
In Settings → Actions → Variables folgende Repository-Variablen setzen:
| Variable | Wert und Bedeutung |
|---|---|
AIS_RUNNER_LABEL |
Optional: Label eines verfügbaren Runners; Standard ubuntu-latest |
ARTIFACT_SERVER_URL |
Optional: aus dem Job-Container erreichbare Basis-URL derselben Gitea-Instanz, etwa https://gitlab.bartelluis.de; Standard ist gitea.server_url wie beim Checkout |
REGISTRY_HOST |
Optional: Registry-Host ohne Schema oder Pfad; Standard gitlab.bartelluis.de |
REGISTRY_USERNAME |
Gitea-Benutzername des Token-Inhabers; für Veröffentlichung erforderlich |
PUBLISH_IMAGES |
Genau true, nachdem Registry-Zugang und Schutzregeln eingerichtet sind |
Im Gitea-Benutzerkonto einen Personal Access Token mit Paket-Schreibrecht
(write:package, in der Oberfläche package: Read & Write) erstellen.
Den Wert unter Settings → Actions → Secrets als REGISTRY_TOKEN speichern.
Das zugehörige Konto muss beim Paketinhaber BartelLuis Schreibzugriff besitzen.
Das kurzlebige GITEA_TOKEN des Jobs unterstützt die Paketveröffentlichung
nicht; es ersetzt dieses Secret nicht.
Gitea-Secrets,
Paketberechtigungen,
Gitea-Paketautorisierung.
Der Imagepfad ist <REGISTRY_HOST>/<kleingeschriebener Repositoryname>, hier
gitlab.bartelluis.de/bartelluis/proxmox-ais-server. Bei einem Fork oder einer
Umbenennung ändert sich der Pfad. Pakete gehören in Gitea einem Benutzer oder
einer Organisation. Nach dem ersten Push kann das Paket in seinen Einstellungen
mit dem Repository verknüpft werden, damit es auch in dessen Paketliste erscheint.
Gitea Container Registry.
Standardbranch und Release-Tags schützen
Vor PUBLISH_IMAGES=true in den Gitea-Repository-Einstellungen den
Standardbranch main und die Release-Tags schützen. Für main direkte Pushes
deaktivieren, Reviews und erfolgreiche Statuschecks verlangen sowie Force-Push
und Löschen einschränken.
Für v* die Erstellung, Änderung und Löschung auf Release-Verantwortliche
begrenzen. Release-Tags auf einen geprüften Commit mit passender Projektversion
setzen. Die Schutzregeln werden durch den Workflow-Commit nicht angelegt.
Geschützte Branches,
Geschützte Tags.
Nach dem ersten Pull-Request-Lauf die tatsächlich gemeldeten Statuskontexte
für python-tests, javascript-check, container-policy und container-verify
als verpflichtend auswählen. container-publish wird bei Pull Requests übersprungen und ist
deshalb keine Pflichtprüfung.
Die CI entscheidet anhand von PUBLISH_IMAGES, Ereignis und Ref. Sie fragt
keinen Schutzstatus ab: Giteas kompatibler ref_protected-Wert ist dafür nicht
verwendbar. Die Gitea-Schutzregeln und restriktive Schreibrechte bleiben daher
ein eigener Einrichtungsschritt.
Auslöser und Image-Tags
Der Workflow läuft bei Branch- und Tag-Pushes, bei Pull Requests sowie bei
manuellem Start über workflow_dispatch.
| Ref und Ereignis | Container-Job | Veröffentlichung |
|---|---|---|
PUBLISH_IMAGES fehlt oder ist nicht true |
container-verify |
Keine |
| Pull Request, Feature-Branch oder sonstiger Tag | container-verify |
Keine |
| Standardbranch, Push oder manueller Start, Veröffentlichung aktiviert | container-publish |
sha-<vollständiger Commit-SHA> und edge |
Tag vX.Y.Z, Push oder manueller Start, Veröffentlichung aktiviert |
container-publish |
sha-<vollständiger Commit-SHA> und X.Y.Z |
Release-Tags müssen vollständig dem Muster
v(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*) entsprechen. Führende
Nullen, Vorabversionen und Build-Zusätze veröffentlichen kein Image.
Bei einem zur Veröffentlichung ausgewählten Release muss die Version außerdem
exakt [project].version in pyproject.toml entsprechen;
eine Abweichung bricht den Publish-Job ab.
edge ist ein beweglicher Tag. Ein erneuter Lauf eines älteren Commits kann
ihn zurücksetzen. SHA-Tags enthalten alle 40 Zeichen des Commits; externe
Build-Abhängigkeiten können bei erneuten Builds zu einem anderen Digest führen.
Es gibt keinen latest-Tag. Im Betrieb den Digest aus deploy.env verwenden
und bisherige Registry-Versionen für Updates und Rollback aufbewahren.
Jobs und Artefakte
python-tests führt über ci/python-tests.sh Pytest in
einer temporären virtuellen Umgebung aus. javascript-check prüft mit
node --check provisioner/static/app.js die JavaScript-Syntax.
container-policy wählt den Container-Job aus. Nach erfolgreichen
Quellcodeprüfungen läuft genau einer der Jobs container-verify und
container-publish. Beide verwenden ci/container.sh;
das Skript prüft vor einer Veröffentlichung erneut Ereignis, Ref und Opt-in.
Der Container-Smoke-Test prüft das gebaute
linux/amd64-Image auf TLS, Anmeldung, CSRF, Webdateien und Datenerhalt über
einen Dienstneustart. Er läuft als UID 10001 mit schreibgeschütztem Dateisystem,
entfernten Linux-Capabilities und temporären Testdaten. Eine Proxmox-Installation
ist kein Bestandteil dieses Tests. Der Publish-Job lädt das getestete Image
ohne zweiten Build hoch. OCI-Labels enthalten Quellrepository, Commit und
Anwendungsversion; Provenance- und SBOM-Attestierungen werden nicht erzeugt.
| Artefakt im Gitea-Lauf | Inhalt | Angefragte Aufbewahrung |
|---|---|---|
python-test-results |
reports/pytest.xml, auch bei fehlgeschlagenen Tests, sofern erzeugt |
7 Tage |
container-build |
build.env nach erfolgreicher Verifikation |
7 Tage |
container-deploy |
build.env und deploy.env nach erfolgreicher Veröffentlichung |
30 Tage |
Die tatsächliche Aufbewahrung unterliegt der Gitea-Instanzkonfiguration.
Unter Actions den erfolgreichen Lauf öffnen und das gewünschte Artefakt
herunterladen. build.env enthält den temporären lokalen Image-Tag, Commit
und Anwendungsversion. Der lokale ci-…-Tag wird nicht veröffentlicht und am
Jobende entfernt. deploy.env enthält ausschließlich
PROVISIONER_IMAGE=gitlab.bartelluis.de/bartelluis/proxmox-ais-server@sha256:…
beziehungsweise die konfigurierte Registry-Adresse. Beide Dateien enthalten
keine Zugangsdaten. Die Image-Zeile in .env auf dem Zielserver übernehmen.
Erster Lauf und Release
Nach dem Push unter Actions prüfen, dass der Lauf einen Runner erhält und
Python-, JavaScript- und Containerprüfungen erfolgreich sind. Nach aktivierter
Veröffentlichung muss ein Standardbranch-Lauf außerdem die Image-Tags
sha-<Commit> und edge sowie container-deploy mit deploy.env liefern.
Lokale Tests ersetzen diesen Lauf mit Registry-Anmeldung und Push nicht.
Für ein Release zuerst [project].version ändern und den geprüften Commit
übernehmen. Anschließend mit einem berechtigten Konto den passenden Tag
erstellen und an den Gitea-Remote pushen. Im vorhandenen Checkout heißt er
origin; vor dem Push mit git remote -v prüfen. Für Projektversion 0.9.1,
sofern der Tag noch nicht existiert:
git tag -a v0.9.1 -m "Release 0.9.1"
git push origin v0.9.1
Der Release-Lauf muss den Image-Tag 0.9.1 erzeugen. Für einen manuellen Lauf
unter Actions den Workflow und den gewünschten Ref auswählen. Auch dabei
gelten Opt-in, Standardbranch- beziehungsweise Tag-Regel und Versionsabgleich.
Branch-Push und Pull Request können für denselben Quellstand getrennte Läufe
erzeugen. Pull Requests veröffentlichen keine Images.
Fehlersuche und Deployment
Bei Waiting beziehungsweise no matching online runner das angeforderte
Label mit den erreichbaren Runnern unter Settings → Actions → Runners
vergleichen. Der bisherige Workflow verlangte ubuntu-24.04; dafür war kein
passender Online-Runner verfügbar. AIS_RUNNER_LABEL auf ein tatsächlich
vorhandenes Label setzen oder einen geeigneten Runner registrieren und starten.
Ein Label-Wechsel allein ersetzt keine fehlende Runner-Installation.
Bei fehlendem Docker-Zugriff docker info und docker buildx version in der
Job-Umgebung prüfen. Bei DNS-, Checkout- oder Artefaktfehlern müssen Giteas
öffentliche ROOT_URL, die Checkout-Adresse und die vom Runner erreichbare
Adresse zusammenpassen. Das Projekt verwendet gitlab.bartelluis.de; eine
von der Instanz zurückgegebene abweichende Adresse wie git.bartelluis.de muss
ebenfalls auflösbar und erreichbar sein oder in der Gitea-Konfiguration
korrigiert werden.
Bei einem Timeout von ArtifactService/CreateArtifact den Wert von
ACTIONS_RESULTS_URL im Upload-Schritt prüfen. Der Runner setzt ihn zunächst
aus seiner Registrierungsadresse; Runner 3.4.2 kann ihn für die
Artefaktweiterleitung durch die Adresse seines Cache-Servers ersetzen.
Ein interner Docker-Hostname oder eine nur im Runner-Container erreichbare
Adresse kann im getrennten Job-Netz unerreichbar sein. Der gemountete
Docker-Socket verbindet diese Netze nicht miteinander.
Der Workflow setzt deshalb für alle drei Uploads ACTIONS_RESULTS_URL auf
gitea.server_url, also dieselbe Gitea-Adresse wie beim Checkout. Falls nötig,
ARTIFACT_SERVER_URL=https://gitlab.bartelluis.de als Repository-Variable setzen.
Die Basis-URL enthält Schema und Host, gegebenenfalls einen Port, aber keinen
/api/actions_pipeline-Pfad. Sie muss dieselbe Gitea-Instanz erreichen.
Die Überschreibung muss direkt im Upload-Schritt stehen, da der Runner
Umgebungsvariablen auf Workflow- oder Job-Ebene überschreiben kann.
Runner-Artefaktweiterleitung,
Gitea-Laufzeitvariablen.
Die Erreichbarkeit innerhalb eines Job-Containers prüfen:
curl --connect-timeout 5 --max-time 10 --silent --show-error --output /dev/null \
--write-out 'HTTP %{http_code}\n' \
https://gitlab.bartelluis.de/twirp/github.actions.results.api.v1.ArtifactService/CreateArtifact
Ein 405 auf diese GET-Anfrage bestätigt, dass der POST-Endpunkt erreichbar
ist; der eigentliche Upload benötigt weiterhin das vom Runner bereitgestellte
Job-Token. Bei einem Timeout DNS, Routing und Proxy-Zugriff aus dem Job-Netz
prüfen oder Runner und Jobs an ein gemeinsames erreichbares Docker-Netz
anbinden. Eine längere Wiederholungszeit behebt eine unerreichbare Adresse nicht.
Bei übersprungenem Publish-Job PUBLISH_IMAGES, Ereignis, Standardbranch und
Tagformat prüfen. Bei denied oder unauthorized Registry-Host, Benutzername,
REGISTRY_TOKEN, dessen write:package-Scope und die Rechte am Paketinhaber
kontrollieren. Bei Versionsfehlern Git-Tag und pyproject.toml abgleichen.
Fehlt container-deploy, die Build-, Smoke-, Push- und Upload-Logs prüfen.
Zum Deployment compose.yaml und
config/deployment.env.example auf den
Zielserver kopieren. Die Deployment-Anleitung beschreibt
Registry-Anmeldung, Erstinitialisierung, HTTPS-Prüfung, Updates und Rollback.
Für private Pakete benötigt das Deploymentkonto einen eigenen Token mit
read:package; öffentliche Pakete lassen sich anonym laden.