Files
Proxmox-AIS-Server/docs/github-actions.md
T
BartelLuis 06c3474636
CI / javascript-check (push) Successful in 51s
CI / container-policy (push) Successful in 2s
CI / container-verify (push) Canceled after 0s
CI / container-publish (push) Canceled after 0s
CI / python-tests (push) Canceled after 6m59s
feat: add Proxmox provisioning service with CI and deployment tooling
2026-09-14 20:09:12 +02:00

12 KiB

GitHub Actions und Container Registry

Der Workflow 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.

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 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 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 ein linux/amd64-Image und prüfen es mit dem Container-Smoke-Test. 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.

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, Artefakte herunterladen.

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.

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.

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, Paketzugriff und Sichtbarkeit.

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.

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, Verfügbare Schutzregeln.

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.

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:

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.

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 und config/deployment.env.example auf den Zielserver kopieren und die Image-Zeile aus deploy.env verwenden. Die Deployment-Anleitung 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.