ci: migrate workflows to Gitea Actions
This commit is contained in:
@@ -0,0 +1,210 @@
|
||||
# Gitea Actions und Container Registry
|
||||
|
||||
Das Projekt liegt auf
|
||||
[Gitea](https://gitlab.bartelluis.de/BartelLuis/Proxmox-AIS-Server).
|
||||
Der [Workflow](../.gitea/workflows/ci.yml) 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](deployment.md).
|
||||
|
||||
## 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](https://docs.gitea.com/usage/actions/quickstart/).
|
||||
|
||||
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](https://docs.gitea.com/1.26/usage/actions/act-runner/#labels)
|
||||
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` |
|
||||
| `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](https://docs.gitea.com/usage/actions/secrets/),
|
||||
[Paketberechtigungen](https://docs.gitea.com/usage/packages/overview/#access-restrictions),
|
||||
[Gitea-Paketautorisierung](https://docs.gitea.com/usage/actions/comparison/#package-repository-authorization).
|
||||
|
||||
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](https://docs.gitea.com/usage/packages/container/).
|
||||
|
||||
## 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](https://docs.gitea.com/usage/access-control/protected-branches/),
|
||||
[Geschützte Tags](https://docs.gitea.com/usage/access-control/protected-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](../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](../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](../ci/container.sh);
|
||||
das Skript prüft vor einer Veröffentlichung erneut Ereignis, Ref und Opt-in.
|
||||
|
||||
Der [Container-Smoke-Test](../tests/container_smoke.py) 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.1.0`,
|
||||
sofern der Tag noch nicht existiert:
|
||||
|
||||
```bash
|
||||
git tag -a v0.1.0 -m "Release 0.1.0"
|
||||
git push origin v0.1.0
|
||||
```
|
||||
|
||||
Der Release-Lauf muss den Image-Tag `0.1.0` 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 ü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](../compose.yaml) und
|
||||
[config/deployment.env.example](../config/deployment.env.example) auf den
|
||||
Zielserver kopieren. Die [Deployment-Anleitung](deployment.md) 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.
|
||||
Reference in New Issue
Block a user