ci: migrate workflows to Gitea Actions
This commit is contained in:
+3
-202
@@ -1,203 +1,4 @@
|
||||
# GitHub Actions und Container Registry
|
||||
# CI/CD ist nach Gitea umgezogen
|
||||
|
||||
Der [Workflow](../.github/workflows/ci.yml) führt die Python-Tests aus, prüft die
|
||||
JavaScript-Syntax und baut und testet das Anwendungsimage. Freigegebene Builds
|
||||
werden in die GitHub Container Registry (GHCR) veröffentlicht. Der Workflow
|
||||
endet beim Image-Push und aktualisiert keinen Zielserver. Die anschließenden
|
||||
Betriebsschritte stehen in der [Deployment-Anleitung](deployment.md).
|
||||
|
||||
## Auslöser und Image-Tags
|
||||
|
||||
Der Workflow läuft bei Pushes auf alle Branches und Tags, bei Pull Requests
|
||||
und beim manuellen Start mit `workflow_dispatch`.
|
||||
|
||||
| Ref und Ereignis | Container-Job | Veröffentlichung |
|
||||
| --- | --- | --- |
|
||||
| Pull Request, auch aus einem Fork | `container-verify` | Keine |
|
||||
| Feature-Branch, ungeschützter Ref oder sonstiger Tag | `container-verify` | Keine |
|
||||
| Geschützter Standardbranch bei Push oder manuellem Start | `container-publish` | `sha-<vollständiger Commit-SHA>` und `edge` |
|
||||
| Geschützter Tag `vX.Y.Z` bei Push oder manuellem Start | `container-publish` | `sha-<vollständiger Commit-SHA>` und `X.Y.Z` |
|
||||
|
||||
Release-Tags müssen dem Muster `v(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)`
|
||||
vollständig entsprechen. Führende Nullen, Vorabversionen wie `v1.0.0-rc.1` und
|
||||
Build-Zusätze veröffentlichen daher kein Image. Bei einem gültigen geschützten
|
||||
Release-Tag muss dessen Version außerdem exakt `[project].version` in
|
||||
[pyproject.toml](../pyproject.toml) entsprechen; eine Abweichung bricht den Lauf ab.
|
||||
|
||||
Das Image liegt für dieses Repository unter `ghcr.io/netivra/proxmox-ais`.
|
||||
Der Workflow leitet den Pfad aus dem kleingeschriebenen GitHub-Repositorynamen
|
||||
ab; bei einem Fork oder einer Umbenennung ändert sich deshalb der Imagepfad.
|
||||
`edge` bezeichnet den zuletzt veröffentlichten Standardbranch-Build. Ein
|
||||
erneuter Lauf eines älteren Commits kann `edge` zurücksetzen. SHA-Tags enthalten
|
||||
alle 40 Zeichen des Commits; erneute Builds desselben Quellstands können durch
|
||||
externe Build-Abhängigkeiten einen anderen Digest ergeben. Es gibt keinen
|
||||
`latest`-Tag. Im Betrieb den Digest aus `deploy.env` verwenden und die
|
||||
zugehörigen Registry-Versionen für Updates und Rollback aufbewahren.
|
||||
|
||||
## Jobs und Artefakte
|
||||
|
||||
`python-tests` und `javascript-check` prüfen den Quellstand. Das Skript
|
||||
[ci/python-tests.sh](../ci/python-tests.sh) installiert `.[dev]` in einer
|
||||
eigenen temporären virtuellen Umgebung, führt Pytest aus und entfernt die
|
||||
Umgebung anschließend. Die JavaScript-Prüfung verwendet
|
||||
`node --check provisioner/static/app.js`; sie ist kein Browsertest.
|
||||
`container-policy` bestimmt anhand des GitHub-Ereignisses, des Ref-Schutzes
|
||||
und des Branch- beziehungsweise Tag-Namens, welcher Container-Job laufen darf.
|
||||
|
||||
Nach erfolgreichen Python- und JavaScript-Prüfungen läuft genau einer der
|
||||
Jobs `container-verify` und `container-publish`. Beide bauen über
|
||||
[ci/container.sh](../ci/container.sh) ein `linux/amd64`-Image und prüfen es
|
||||
mit dem [Container-Smoke-Test](../tests/container_smoke.py). Der Publish-Job
|
||||
lädt genau das bereits getestete Image hoch, ohne einen zweiten Build.
|
||||
Die Veröffentlichung wird im Skript erneut auf Ereignis und Ref geprüft;
|
||||
dort erfolgt auch der Abgleich mit der Projektversion.
|
||||
|
||||
Publish-Jobs teilen eine Warteschlange mit `queue: max` und laufen einzeln.
|
||||
Bis zu 100 Jobs können warten; ein laufender Publish-Job wird durch neue
|
||||
Commits nicht abgebrochen. Die Reihenfolge richtet sich nach dem Eintritt in
|
||||
die Warteschlange, nicht zwingend nach dem Alter der Commits. Bei Pull Requests
|
||||
und ungeschützten Refs ersetzt ein neuer Lauf den vorherigen Lauf desselben Refs.
|
||||
[GitHub-Parallelität und Warteschlangen](https://docs.github.com/en/actions/how-tos/write-workflows/choose-when-workflows-run/control-workflow-concurrency).
|
||||
|
||||
Der Smoke-Test prüft TLS, Anmeldung, CSRF, ausgelieferte 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 Build verwendet `--provenance=false --sbom=false` und veröffentlicht
|
||||
keine Provenance- oder SBOM-Attestierungen. Die OCI-Labels für Quellrepository,
|
||||
Commit und Anwendungsversion bleiben erhalten.
|
||||
|
||||
| Artefakt in GitHub Actions | Inhalt | Aufbewahrung |
|
||||
| --- | --- | --- |
|
||||
| `python-test-results` | `reports/pytest.xml` als JUnit-Datei, auch nach fehlgeschlagenen Tests, sofern erzeugt | 7 Tage |
|
||||
| `container-build` | `build.env` nach erfolgreichem Verify-Job | 7 Tage |
|
||||
| `container-deploy` | `build.env` und `deploy.env` nach erfolgreichem Publish-Job | 30 Tage |
|
||||
|
||||
Die Aufbewahrung wird im Workflow mit `retention-days` gesetzt und ist durch
|
||||
die übergeordneten GitHub-Einstellungen begrenzt. Die JUnit-Datei wird als
|
||||
Download bereitgestellt; der Workflow installiert keinen zusätzlichen
|
||||
Testberichtsdienst. Auf der Übersicht des jeweiligen Laufs unter **Artifacts**
|
||||
das gewünschte Archiv herunterladen und entpacken.
|
||||
[Workflow-Artefakte](https://docs.github.com/en/actions/tutorials/store-and-share-data),
|
||||
[Artefakte herunterladen](https://docs.github.com/en/actions/how-tos/manage-workflow-runs/download-workflow-artifacts).
|
||||
|
||||
`build.env` enthält den temporären lokalen Image-Tag, Commit und
|
||||
Anwendungsversion. Dieser `ci-…`-Tag wird nicht veröffentlicht und beim
|
||||
Jobende lokal entfernt. `deploy.env` enthält ausschließlich die
|
||||
Deploymentreferenz `PROVISIONER_IMAGE=ghcr.io/netivra/proxmox-ais@sha256:…`.
|
||||
Die Dateien enthalten keine Zugangsdaten. `deploy.env` wird auf dem Zielserver
|
||||
nicht automatisch eingelesen; seine Image-Zeile in die dortige `.env` übernehmen.
|
||||
|
||||
## GitHub einrichten
|
||||
|
||||
Ein eigener CI-Runner ist nicht erforderlich. Alle Jobs verwenden
|
||||
GitHub-gehostete Linux-amd64-Runner mit `ubuntu-24.04`. Der Workflow richtet
|
||||
Python 3.13 über `actions/setup-python` und Node.js 24 über `actions/setup-node`
|
||||
ein. Docker und Buildx werden vom Runner bereitgestellt und vor dem Build
|
||||
geprüft. Bash, OpenSSL und der OpenSSH-Client werden dort ebenfalls verwendet.
|
||||
Diese Build-Umgebung ist
|
||||
unabhängig vom AIS-Host-Runner für die Postinstallation auf Proxmox-Hosts.
|
||||
[GitHub-gehostete Runner](https://docs.github.com/en/actions/reference/runners/github-hosted-runners).
|
||||
|
||||
Im Repository unter **Settings → Actions → General** GitHub Actions aktivieren
|
||||
und die im Workflow verwendeten Actions von `actions/*` zulassen. Diese sind
|
||||
im Workflow auf vollständige Commit-SHAs festgelegt. Es werden
|
||||
keine selbst angelegten Repository-Secrets oder CI-Variablen benötigt.
|
||||
Der Workflow verwendet standardmäßig `contents: read`; nur
|
||||
`container-publish` erhält zusätzlich `packages: write` und verwendet das
|
||||
automatisch bereitgestellte `GITHUB_TOKEN` für die Anmeldung an `ghcr.io`.
|
||||
[Actions-Einstellungen](https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/enabling-features-for-your-repository/managing-github-actions-settings-for-a-repository).
|
||||
|
||||
GHCR-Pakete sind bei der ersten Veröffentlichung standardmäßig privat. Ein
|
||||
bereits existierendes Paket muss mit diesem Repository verbunden sein und
|
||||
dessen Actions Schreibzugriff haben. In den Paketeinstellungen unter
|
||||
**Manage Actions access** gegebenenfalls `Netivra/Proxmox-AIS` mit Schreibrecht
|
||||
hinzufügen. Dort auch die gewünschte Paketsichtbarkeit festlegen.
|
||||
[GHCR und GITHUB_TOKEN](https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-container-registry#authenticating-in-a-github-actions-workflow),
|
||||
[Paketzugriff und Sichtbarkeit](https://docs.github.com/en/packages/learn-github-packages/configuring-a-packages-access-control-and-visibility).
|
||||
|
||||
## Standardbranch und Release-Tags schützen
|
||||
|
||||
**Vor der ersten Veröffentlichung müssen aktive Schutzregeln für die
|
||||
veröffentlichten Refs eingerichtet sein.** Der Workflow und das Skript
|
||||
verlangen `github.ref_protected == true`. GitHub setzt dieses Merkmal, wenn
|
||||
Branchschutz oder ein passendes Ruleset für den auslösenden Ref konfiguriert
|
||||
ist. Ohne Schutz wird nur geprüft.
|
||||
[GitHub-Ref-Kontext](https://docs.github.com/en/actions/reference/workflows-and-actions/contexts#github-context).
|
||||
|
||||
Unter den Repository-Einstellungen für Rulesets zwei Regeln anlegen und
|
||||
jeweils **Enforcement status: Active** wählen:
|
||||
|
||||
| Ruleset | Ziel | Vorgesehene Regeln |
|
||||
| --- | --- | --- |
|
||||
| Standardbranch | **Include default branch**, etwa `main` | Pull Request und Review verlangen; Löschen und Force-Push verhindern; erfolgreiche Statuschecks verlangen |
|
||||
| Releases | Tags mit dem Muster `v*` | Erstellung, Aktualisierung und Löschung beschränken; nur Release-Verantwortliche in die Bypass-Liste aufnehmen |
|
||||
|
||||
Für Pull Requests die Statuschecks `python-tests`, `javascript-check`,
|
||||
`container-policy` und `container-verify` nach ihrem ersten Lauf als
|
||||
verpflichtend auswählen. `container-publish` ist bei Pull Requests absichtlich
|
||||
übersprungen und wird deshalb nicht als Pflichtprüfung eingerichtet.
|
||||
Das Tag-Ruleset schützt alle `v*`-Tags; die engere Versionsprüfung übernimmt
|
||||
zusätzlich das CI-Skript. Release-Verantwortliche setzen Tags auf einen
|
||||
geprüften Commit mit der passenden Projektversion. Ein Tag auf einem Commit
|
||||
des geschützten Standardbranches ist selbst noch kein geschützter Tag.
|
||||
[Rulesets anlegen](https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-rulesets/creating-rulesets-for-a-repository),
|
||||
[Verfügbare Schutzregeln](https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-rulesets/available-rules-for-rulesets).
|
||||
|
||||
Die Regeln und Paketberechtigungen im GitHub-Projekt sind Teil der Einrichtung;
|
||||
sie werden durch den Commit der Workflow-Datei nicht automatisch angelegt.
|
||||
Welche Rulesets verfügbar sind, hängt von Repository-Sichtbarkeit und
|
||||
GitHub-Tarif ab. Die CI-Abfragen ersetzen keine restriktiven Schreibrechte
|
||||
auf Repository und Paket; Änderungen an Workflow und CI-Skripten im Review prüfen.
|
||||
[Ruleset-Verfügbarkeit](https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-rulesets/creating-rulesets-for-a-repository).
|
||||
|
||||
## Erster Lauf und Release
|
||||
|
||||
Nach dem Push der Workflow-Datei unter **Actions** den Lauf öffnen.
|
||||
Python- und JavaScript-Prüfung sowie der passende Container-Job müssen
|
||||
erfolgreich sein. Für einen geschützten Standardbranch zusätzlich prüfen,
|
||||
dass das GHCR-Paket `sha-<Commit>` und `edge` enthält und das Artefakt
|
||||
`container-deploy` mit `deploy.env` bereitsteht. Ein lokaler Test ersetzt
|
||||
diesen ersten GitHub-Lauf samt GHCR-Anmeldung und Push nicht.
|
||||
|
||||
Für ein Release zuerst `[project].version` auf die gewünschte Version setzen
|
||||
und den geprüften Commit übernehmen. Anschließend durch ein für das
|
||||
Release-Ruleset berechtigtes Konto den passenden Tag erstellen und pushen.
|
||||
Im vorhandenen Checkout heißt der GitHub-Remote `GH-AIS`; in anderen Checkouts
|
||||
den Namen mit `git remote -v` prüfen und im Befehl entsprechend ersetzen.
|
||||
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 GH-AIS v0.1.0
|
||||
```
|
||||
|
||||
Der Release-Lauf muss zusätzlich den Image-Tag `0.1.0` erzeugen. Für einen
|
||||
manuellen Branch-Lauf unter **Actions** den Workflow und **Run workflow**
|
||||
wählen. Dafür muss die Workflow-Datei bereits auf dem Standardbranch liegen.
|
||||
Ein manueller Lauf veröffentlicht nur, wenn dieselben Ref-Schutz- und
|
||||
Versionsbedingungen erfüllt sind.
|
||||
[Workflow manuell starten](https://docs.github.com/en/actions/how-tos/manage-workflow-runs/manually-run-a-workflow).
|
||||
|
||||
Branch-Push und Pull Request können für denselben Quellstand getrennte Läufe
|
||||
erzeugen. Pull Requests werden im Merge-Kontext geprüft; ihre Tests führen
|
||||
keinen Registry-Push aus. Die Jobs laden keine produktiven Deployment-Zugänge.
|
||||
|
||||
## Fehlersuche und Deployment
|
||||
|
||||
Bei übersprungenem Publish-Job zuerst Ereignis, Standardbranch, Tagformat und
|
||||
aktive Schutzregeln prüfen. Bei einer Versionsabweichung müssen Git-Tag und
|
||||
`pyproject.toml` aufeinander abgestimmt werden. Bei `denied` oder `unauthorized`
|
||||
im Publish-Job die Organisationsrichtlinien, `packages: write` und den
|
||||
Actions-Zugriff auf das GHCR-Paket kontrollieren. Fehlt `container-deploy`,
|
||||
die Logs des Build-, Smoke- und Push-Schritts prüfen; vor erfolgreicher
|
||||
Veröffentlichung steht kein Deployment-Digest bereit.
|
||||
|
||||
Zum Deployment [compose.yaml](../compose.yaml) und
|
||||
[config/deployment.env.example](../config/deployment.env.example) auf den
|
||||
Zielserver kopieren und die Image-Zeile aus `deploy.env` verwenden.
|
||||
Die [Deployment-Anleitung](deployment.md) beschreibt GHCR-Anmeldung,
|
||||
Erstinitialisierung, HTTPS-Prüfung, Updates und Rollback. Für private Pakete
|
||||
benötigt das Deploymentkonto einen Personal Access Token (classic) mit
|
||||
`read:packages`; öffentliche Pakete lassen sich anonym laden.
|
||||
Die aktuelle Anleitung steht unter [Gitea Actions und Container Registry](gitea-actions.md).
|
||||
Der Workflow liegt in [.gitea/workflows/ci.yml](../.gitea/workflows/ci.yml).
|
||||
|
||||
Reference in New Issue
Block a user