# pipelines Geteilte CI/CD-Bausteine für die Gitea-Instanz `git.jk-dev.de`. Die Workflows hier werden nicht selbst ausgelöst, sondern von anderen Repositories über `uses:` aufgerufen (`on: workflow_call`). ## Bausteine ### `.gitea/workflows/docker-build-push.yml` Baut ein Docker-Image und schiebt es als Multi-Arch-Manifest (`linux/amd64,linux/arm64`) in eine Registry, vorgabegemäß `git.jk-dev.de`. Läuft auf einem Runner mit dem Label `ubuntu-docker`. Gepusht wird unter fünf Tags: ``` //:latest //: //: //:. //:.. ``` Der Checkout holt Submodule mit; die Zugangsdaten dafür und für die Registry kommen zur Laufzeit aus 1Password Connect. Mit `push: 'false'` entfällt der Push — der Baustein baut dann nur. Damit nutzt die CI eines Projekts dieselbe Bau-Logik wie das Deployment, statt sie zu duplizieren. Siehe [Prüfmodus](#prüfmodus-ohne-push). #### Eingaben | Eingabe | Pflicht | Vorgabe | Bedeutung | | ---------------------- | ------- | ------------------------- | --------- | | `container-name` | ja | — | Name des Images | | `dockerfile` | ja | — | Pfad zum Dockerfile | | `docker-context` | ja | — | Build-Kontext | | `image-owner` | ja | — | Eigentümer-Segment des Images, also der mittlere Teil von `//` | | `push` | nein | `'true'` | Zeichenkette `'true'` oder `'false'`. Ob das Image gepusht wird. Bei `'false'` werden keine Zugangsdaten aus 1Password geholt und es findet kein Registry-Login statt — siehe [Prüfmodus](#prüfmodus-ohne-push) | | `registry` | nein | `git.jk-dev.de` | Registry, für die getaggt und — beim Push — bei der angemeldet wird | | `version-number` | nein | `0.0.0` | Vollständige Version, wird als Tag gesetzt | | `version-number-major` | nein | `0` | Major-Anteil für die mitwandernden Tags | | `version-number-minor` | nein | `0` | Minor-Anteil | | `version-number-patch` | nein | `0` | Patch-Anteil | | `timeout-minutes` | nein | `45` | Harte Grenze für den Build-Job | | `platforms` | nein | `linux/amd64,linux/arm64` | Zielplattformen der Manifest-Liste | | `build-args` | nein | — | Zusätzliche Build-Argumente, ein `NAME=wert` je Zeile | Dass `image-owner` Pflicht ist und `registry` nicht, ist Absicht: Der Eigentümer ist je Projekt verschieden und soll nie stillschweigend geraten werden — genau das war der Fehler des früher fest verdrahteten `suer`, unter dem die Images aller Projekte landeten. Die Registry ist dagegen praktisch immer dieselbe. `push` ist eine Zeichenkette und kein Boolean — und das ist Absicht. Auf dieser Gitea-Version (gemessen an 1.27.0) werden **boolesche `workflow_call`-Eingaben nicht an den aufgerufenen Workflow durchgereicht**: Weder ihre Vorgabe noch ein ausdrücklich übergebenes `push: true` kamen an, `inputs.push` blieb leer, und der Baustein baute immer im Prüfmodus — bei grünem Lauf. Alle Eingaben vom Typ `string` kamen im selben Lauf korrekt an. Details in [Issue #4](https://git.jk-dev.de/workflow-util/pipelines/issues/4). Deshalb bitte immer in Anführungszeichen schreiben: `push: 'true'` bzw. `push: 'false'`. Ein unquotiertes `push: false` ist im YAML ein Boolean und wird verschluckt. > **Brechende Änderung gegenüber `v1`.** Aufrufer, die `push` als YAML-Boolean > übergeben, müssen auf `@v2` wechseln und dabei auf die Schreibweise mit > Anführungszeichen umstellen. Wer `@v1` weiterverwendet, behält das alte > Verhalten samt Fehler. Die vier Versionsangaben dienen ausschließlich der Tag-Liste. Sie sind keine Pflicht mehr, damit ein Prüflauf keine Platzhalter erfinden muss; wer pusht, übergibt sie wie bisher. Ihre Vorgabe ist bewusst `0.0.0` und nicht leer — die Tag-Liste wird auch ohne Push gebildet, und ein leerer Wert ergäbe das ungültige `…/:`. #### Aufrufbeispiel ```yaml jobs: image: uses: workflow-util/pipelines/.gitea/workflows/docker-build-push.yml@v2 with: version-number: 2026.09.1 version-number-major: '2026' version-number-minor: '09' version-number-patch: '1' container-name: bk-dev-website dockerfile: ./Dockerfile docker-context: . image-owner: bekemeyer-klein push: 'true' secrets: inherit ``` `secrets: inherit` ist notwendig — der Workflow braucht `OP_CONNECT_TOKEN` aus dem aufrufenden Repository. #### Prüfmodus ohne Push Mit `push: 'false'` baut der Baustein nur und veröffentlicht nichts. Es werden dann keine Zugangsdaten aus 1Password geholt und es findet kein Registry-Login statt. Die CI eines Projekts nutzt damit dieselbe Bau-Logik wie das Deployment, statt sie zu duplizieren. Weder Secrets noch Versionsangaben sind dafür nötig: ```yaml jobs: build-check: uses: workflow-util/pipelines/.gitea/workflows/docker-build-push.yml@v2 with: container-name: bk-dev-website dockerfile: ./Dockerfile docker-context: . image-owner: bekemeyer-klein push: 'false' ``` Die Anführungszeichen sind nicht kosmetisch: `push: false` ohne sie ist ein YAML-Boolean und kommt im Baustein nicht an (siehe oben). Es griffe dann die Vorgabe `'true'`, der Lauf versuchte also trotz `push: false` zu veröffentlichen — sofern Gitea die Typabweichung nicht ohnehin als Fehler zurückweist. > **Private Submodule funktionieren in diesem Modus nicht.** > Der Checkout-Token stammt aus demselben 1Password-Schritt, der ohne Push > übersprungen wird. Der Checkout fällt deshalb auf den Standard-Token des Jobs > zurück. Der genügt für das ausführende Repository, nicht aber für die > Submodule in eigenen privaten Repositories — deren Klon scheitert mit > `Repository not found`. Projekte **mit** privaten Submodulen können > `push: false` daher nicht verwenden; für Projekte ohne Submodule ist der > Modus unproblematisch. `secrets: inherit` kann hier entfallen. Es zu belassen schadet nicht — der Workflow greift ohne Push auf kein Secret zu. #### Voraussetzungen im aufrufenden Repository | Name | Art | Zweck | | ------------------ | -------- | ----- | | `OP_CONNECT_HOST` | Variable | Adresse des 1Password-Connect-Servers im Cluster. Nur beim Push nötig | | `OP_CONNECT_TOKEN` | Secret | Zugang zu diesem Connect-Server. Nur beim Push nötig | | `DOCKER_HOST` | Variable | Nur nötig, wenn der Runner-Daemon rootless läuft und sein Socket nicht unter `/var/run/docker.sock` liegt (dann z. B. `unix:///run/user/1000/docker.sock`). Ist die Variable nicht gesetzt, nutzt Docker seinen Default. | Die eigentlichen Zugänge für Checkout und Registry liegen in 1Password (`GitHub-Actions/jlab-git-checkout-token`, `GitHub-Actions/jlab-registry-access`) und müssen in Gitea nicht hinterlegt werden. ## Auf einen Tag zeigen, nicht auf `@main` Aufrufe bitte immer an einen Tag binden: ```yaml uses: workflow-util/pipelines/.gitea/workflows/docker-build-push.yml@v2 # so uses: workflow-util/pipelines/.gitea/workflows/docker-build-push.yml@main # nicht so ``` Mit `@main` ändert jede Anpassung hier unangekündigt das Verhalten sämtlicher Projekte — und der Fehler zeigt sich dann dort, wo niemand etwas geändert hat. Ein Tag macht das Übernehmen einer neuen Fassung zu einer bewussten Entscheidung im jeweiligen Projekt. Änderungen hier bekommen deshalb einen neuen Tag. Bricht eine Änderung bestehende Aufrufe, wird der Major-Anteil erhöht. `v2` ist genau so ein Fall: Die Umstellung von `push` auf `type: string` bricht Aufrufe, die den Wert als YAML-Boolean übergeben. `v1` bleibt unverändert stehen; wer umstellt, wechselt auf `@v2` und schreibt `push: 'true'` bzw. `push: 'false'`.