diff --git a/.gitea/workflows/docker-build-push.yml b/.gitea/workflows/docker-build-push.yml index 4fe5005..158ba1d 100644 --- a/.gitea/workflows/docker-build-push.yml +++ b/.gitea/workflows/docker-build-push.yml @@ -28,16 +28,37 @@ on: required: false default: '0' type: string + # Bewusst `type: string` und nicht `boolean` — siehe Issue #4. Auf dieser + # Gitea-Version (gemessen an 1.27.0) kommt eine boolesche + # workflow_call-Eingabe im aufgerufenen Workflow gar nicht an: weder ihre + # Vorgabe noch ein ausdruecklich uebergebenes `push: true`. `inputs.push` + # war in beiden Faellen leer, der Baustein baute immer im Pruefmodus und + # meldete dabei Erfolg. Alle Eingaben vom Typ string desselben Laufs + # (platforms, registry, image-owner, container-name) kamen korrekt an; + # push war die einzige boolesche und die einzige, die versagte. + # + # Wer das beim naechsten Aufraeumen "korrekt" auf boolean zurueckstellt, + # holt den Fehler still zurueck: nichts wird veroeffentlicht, und der + # Lauf bleibt gruen. + # + # Die Bedingung `inputs.push && inputs.push != 'false'` musste dafuer + # nicht angefasst werden. Sie wurde seinerzeit ausdruecklich so gebaut, + # dass sie Boolean und String vertraegt (Begruendung am + # 1Password-Schritt), und traegt die Umstellung unveraendert: 'true' ist + # truthy und ungleich 'false', 'false' ist truthy aber gleich 'false'. push: description: >- - Whether the built image is pushed. With push: false no credentials are - fetched from 1Password and no registry login happens, so the workflow - doubles as a build check. Caveat: the checkout token comes from the - same 1Password step, so without push the checkout falls back to the - job token — which cannot clone private submodules. + Whether the built image is pushed, as the string 'true' or 'false'. + Deliberately a string, not a boolean: boolean workflow_call inputs do + not reach the called workflow on this Gitea version (see issue #4). + With push: 'false' no credentials are fetched from 1Password and no + registry login happens, so the workflow doubles as a build check. + Caveat: the checkout token comes from the same 1Password step, so + without push the checkout falls back to the job token — which cannot + clone private submodules. required: false - default: true - type: boolean + default: 'true' + type: string container-name: required: true type: string @@ -113,6 +134,24 @@ jobs: # gesetzt, bleibt die Variable leer und Docker nutzt seinen Default. DOCKER_HOST: ${{ vars.DOCKER_HOST }} steps: + # Issue #4 blieb so lange unbemerkt, weil nirgends sichtbar war, was + # ueberhaupt ankommt — und weil ein Lauf ohne Push genauso gruen aussieht + # wie einer mit. Der Schritt macht beides sichtbar: den rohen Wert der + # Eingabe und den daraus abgeleiteten Modus. Gleiches Muster wie + # "Docker-Socket ermitteln": rein informativ, mit `|| true` abgesichert, + # damit er den Job unter keinen Umstaenden scheitern laesst. + # + # Der Wert wird ueber die Umgebung gereicht statt in die Kommandozeile + # interpoliert; so bleibt er auch dann harmlos, wenn ein Aufrufer etwas + # Unerwartetes uebergibt. + - name: Eingaben melden + env: + PUSH_ROH: ${{ inputs.push }} + PUSH_MODUS: ${{ (inputs.push && inputs.push != 'false') && 'veroeffentlichen' || 'nur bauen' }} + run: | + echo "push (roh): '${PUSH_ROH}'" || true + echo "Modus: ${PUSH_MODUS}" || true + # Der Token, den Gitea jedem Job stellt, taugt fuer zwei Dinge nicht: # Er gilt nur fuer das ausfuehrende Repository, waehrend die Submodule in # eigenen, privaten Repositories liegen — deren Klon scheitert an @@ -135,6 +174,12 @@ jobs: # Strings sind truthy), `inputs.push == 'true'` waere beim echten Boolean # true falsch (ein Vergleich ueber Typgrenzen laeuft ueber Zahlen, 'true' # wird dabei zu NaN). Die Kombination aus beidem deckt alle vier Faelle ab. + # + # Genau deshalb blieb sie bei der Umstellung von push auf `type: string` + # (Issue #4) unveraendert: sie war von Anfang an fuer beide Schreibweisen + # gebaut. 'true' ergibt wahr, 'false' ergibt falsch, ein leerer Wert + # ergibt falsch — und die Boolean-Faelle gelten unveraendert weiter, + # falls ein Aufrufer doch einmal ein YAML-Boolean uebergibt. - name: Zugangsdaten aus 1Password laden id: op-secrets if: ${{ inputs.push && inputs.push != 'false' }} diff --git a/README.md b/README.md index b682112..7b1568c 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ Gepusht wird unter fünf Tags: 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 +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). @@ -37,7 +37,7 @@ duplizieren. Siehe [Prüfmodus](#prüfmodus-ohne-push). | `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` | 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) | +| `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 | @@ -52,6 +52,23 @@ 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 @@ -63,7 +80,7 @@ Tag-Liste wird auch ohne Push gebildet, und ein leerer Wert ergäbe das ungülti ```yaml jobs: image: - uses: workflow-util/pipelines/.gitea/workflows/docker-build-push.yml@v1 + uses: workflow-util/pipelines/.gitea/workflows/docker-build-push.yml@v2 with: version-number: 2026.09.1 version-number-major: '2026' @@ -73,6 +90,7 @@ jobs: dockerfile: ./Dockerfile docker-context: . image-owner: bekemeyer-klein + push: 'true' secrets: inherit ``` @@ -81,7 +99,7 @@ dem aufrufenden Repository. #### Prüfmodus ohne Push -Mit `push: false` baut der Baustein nur und veröffentlicht nichts. Es werden +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. @@ -91,15 +109,21 @@ Weder Secrets noch Versionsangaben sind dafür nötig: ```yaml jobs: build-check: - uses: workflow-util/pipelines/.gitea/workflows/docker-build-push.yml@v1 + 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 + 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 @@ -129,7 +153,7 @@ und müssen in Gitea nicht hinterlegt werden. Aufrufe bitte immer an einen Tag binden: ```yaml -uses: workflow-util/pipelines/.gitea/workflows/docker-build-push.yml@v1 # so +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 ``` @@ -140,3 +164,8 @@ 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'`.