Table of Contents
- Gemessenes Verhalten dieser Forge
- Boolesche workflow_call-Eingaben kommen nicht an
- Ein fehlendes Secret lässt die Job-Erzeugung scheitern, nicht den Job
- Wandernde Action-Verweise
- Eine Repository-Variable erreicht einen fremd aufgerufenen Workflow
- Der Scanner-Download kommt durch — 59 MiB in etwa drei Sekunden
- node24 ist im Runner-Image vorhanden
Gemessenes Verhalten dieser Forge
Eigenheiten der Gitea-Instanz, an der diese Bausteine hängen. Alles hier ist gemessen, nicht aus einer Dokumentation übernommen, und jedes Stück hat einmal Zeit gekostet. Die Seite steht quer zu den Bausteinen, weil keine dieser Eigenheiten nur einen davon betrifft.
Gemeinsames Muster, das sie teuer macht: Keiner dieser Fehler ist rot. Der Lauf bleibt grün oder sieht harmlos aus, und erst viel später sucht jemand das Ergebnis dort, wo es hätte landen sollen.
Es stehen auch Bestätigungen hier, nicht nur Fallen. Eine Eigenheit, die sich als harmlos herausgestellt hat, kostet ungeschrieben dasselbe wie eine gefährliche: Die nächste Person misst sie erneut, oder — schlimmer — baut einen Umweg um ein Problem, das es nicht gibt. Jeder Eintrag nennt deshalb den Lauf, an dem er gemessen ist.
Boolesche workflow_call-Eingaben kommen nicht an
Gemessen an Gitea 1.27.0, Issue #4.
Eine Eingabe vom Typ boolean erreicht den aufgerufenen Workflow nicht. Weder
ihre Vorgabe noch ein ausdrücklich übergebener Wert: inputs.push blieb leer.
Der Baustein baute dadurch immer im Prüfmodus — bei grünem Lauf, mit einem
--push, das in der Kommandozeile einfach fehlte, und einer Warnung im
Protokoll, die niemand liest, solange nichts rot ist.
Zwei Läufe des ersten Abnehmers:
| Lauf | Aufruf | Ergebnis |
|---|---|---|
| 272 | push weggelassen, Vorgabe gesetzt |
kein --push, nichts veröffentlicht, Lauf grün |
| 276 | push: true ausdrücklich übergeben |
kein --push, nichts veröffentlicht, Lauf grün |
Die Eingrenzung ist das Belastbare daran: Im selben Lauf kamen alle Eingaben
vom Typ string korrekt an — Plattformen, Registry, Eigentümer, Container-Name
wurden alle richtig aufgelöst. push war die einzige boolesche Eingabe und die
einzige, die versagte.
Konsequenz für alle Bausteine hier: Jede Eingabe ist type: string, auch
eine, die inhaltlich ein Schalter ist. Werte dann als 'true' und 'false',
und im Aufruf in Anführungszeichen — ein unquotiertes push: false ist im YAML
ein Boolean und wird verschluckt.
Der Fehler war so langlebig, weil nirgends sichtbar war, was überhaupt ankommt.
Dagegen hilft nur eines, und docker-build-push hat es seitdem: ein
Diagnoseschritt, der den rohen Wert der Eingabe und den daraus abgeleiteten
Modus ausgibt. Rein informativ und so abgesichert, dass er den Job unter keinen
Umständen scheitern lässt.
Ein fehlendes Secret lässt die Job-Erzeugung scheitern, nicht den Job
Gemessen in jlab-cluster/helm-charts; dort festgehalten im README-Abschnitt
„Where this repo lives, and what a Gitea runner does differently" und als
Kommentar an der Secret-Deklaration von dessen install-test.yml.
Wiederverwendbare Workflows mit secrets: inherit funktionieren auf dieser
Instanz. Die Eigenheit: Fehlt ein Secret, das der aufgerufene Workflow als
required: true deklariert, scheitert nicht der Job, sondern seine
Erzeugung — der Lauf steht dann ohne Schritte da. Nichts in ihm benennt die
Ursache, und man debuggt mit Vorliebe das Falsche: das Workflow-YAML, den
Runner, die Action.
Daraus folgt, dass required an einem Secret eine echte Entscheidung ist und
keine Formalie:
- Braucht jeder Aufrufer das Secret, ist
required: truerichtig — so hält es publish-helm-chart, denn ohne Connect-Token kann niemand veröffentlichen. Dass der Lauf ohne Schritte dasteht, ist dann der verständliche Fall: Es fehlt genau diese Voraussetzung. - Braucht nur ein Teil des Bausteins es, muss es
required: falsesein. Im Herkunfts-Repository hängt das Token an genau einem Zweig einer Matrix; mitrequired: trueverlöre ein Pull Request aus einem Fork — der keine Secrets trägt — die gesamte Prüfung, jedes Chart auf einmal, ohne dass etwas die Ursache nennt. Optional deklariert scheitert nur der eine Zweig, und zwar laut an einem Wächter, der das fehlende Tresor-Feld benennt.
Dieselbe Linie wie an jeder anderen Stelle dieses Repositories: Wenn etwas fehlen kann, soll es laut und benannt fehlen, nicht still.
Wandernde Action-Verweise
Issue #5, Punkt 1.
Ein Verweis auf einen Zweig statt auf eine Hauptversion holt bei jedem Lauf den jeweils neuesten Stand. Eine Änderung dort ändert das Verhalten aller Projekte, ohne dass hier etwas angefasst wurde — und der Fehler zeigt sich bei einem Aufrufer, der nichts geändert hat.
Das ist dieselbe Mechanik, wegen der das README von Aufrufern verlangt, auf einen Tag statt auf den Hauptzweig zu zeigen: Ein beweglicher Verweis macht aus dem Übernehmen einer neuen Fassung eine unbeobachtete Nebenwirkung statt einer Entscheidung. Nach innen gilt die Regel genauso wie nach außen, sonst ist die Sorgfalt an der Aufrufgrenze wertlos.
In docker-build-push steht noch ein solcher Verweis — die Buildx-Action zeigt
auf einen Zweig, während die übrigen Actions auf Hauptversionen gepinnt sind.
Festgehalten als bekannte Schwachstelle unter
docker-build-push, damit sie nicht erneut entdeckt werden
muss.
Eine Repository-Variable erreicht einen fremd aufgerufenen Workflow
Gemessen in jlab-cluster/helm-charts, Lauf 375 (Push auf main), an
sonar-analysis.
vars.<NAME> wird in einem Workflow, der per uses: aus einem anderen
Repository geholt wird, im Kontext des Aufrufers aufgelöst. Dass es so
dokumentiert ist, war bekannt; auf dieser Forge-Fassung gemessen war es nicht.
Der Beleg ist indirekt und trotzdem eindeutig: sonar-analysis prüft
vars.SONAR_HOST_URL in einem Wächter und bricht vor dem Scan ab, wenn der
Wert leer ist. In Lauf 375 ist der Wächter durchgelaufen und der Scanner
gestartet — bei leerer Variable hätte es den Scan nie gegeben. Dasselbe gilt für
das uses: selbst: Der Baustein liegt in diesem Repository, der Aufruf kam aus
einem anderen, und er wurde aufgelöst.
Damit ist dieselbe Frage für OP_CONNECT_HOST in
publish-helm-chart beantwortet. Gleiche Gitea-Fassung,
gleicher Mechanismus: eine Repository-Variable, gelesen in einem aus einem
fremden Repository aufgerufenen Workflow. Dort muss nichts zweites gemessen
werden, und der vorgesehene Ausweg — die Adresse als Eingabe übergeben, im
Aufrufer ausgewertet, wie es für das Eigentümer-Segment schon getan wurde —
wird nicht gebraucht.
Was an der Publish-Strecke offen bleibt, ist etwas anderes und nur das: der Upload selbst hat nie stattgefunden. Kein Chart ist durch den geteilten Baustein veröffentlicht worden.
Der Scanner-Download kommt durch — 59 MiB in etwa drei Sekunden
Gemessen in jlab-cluster/helm-charts, Lauf 375.
SonarSource/sonarqube-scan-action lädt den Sonar-Scanner-CLI zur Laufzeit von
binaries.sonarsource.com und prüft dessen GPG-Signatur. Archiv und Signatur,
rund 59 MiB, waren in etwa drei Sekunden da.
Das war die erwartete Stelle für den ersten Fehlschlag, und zwar mit
Vorgeschichte: Auf demselben Runner kam einmal eine 17-MB-Datei nicht durch,
weil die Docker-Brücke mit MTU 1500 gegen ein Pod-Netz mit MTU 1450 lief —
kleine Antworten passten in ein Paket, die große nicht, und der Fehlschlag sah
nach einem kaputten Spiegel aus, nicht nach Netz. Festgehalten im README von
jlab-cluster/helm-charts, Abschnitt „What a GitHub runner had been providing
quietly".
Die knotenseitige Behebung hält, und sie hält beim Dreifachen der damaligen Größe. Ein Download in dieser Größenordnung ist auf diesem Runner kein Risiko mehr und braucht keinen Zwischenspeicher und keinen eigenen Spiegel.
node24 ist im Runner-Image vorhanden
Gemessen in jlab-cluster/helm-charts, Lauf 375.
SonarSource/sonarqube-scan-action deklariert runs: using: node24 und ist
damit eine JavaScript-Action, keine Docker-Action. Sie lief. Zwei Folgen:
- JavaScript-Actions mit
node24sind hier benutzbar. Fehlte die Laufzeitumgebung, scheiterte die Action mit einer Meldung über sich selbst und nicht über das Image — deshalb stand die Frage vorher aufgeschrieben. runs-on: ubuntu-latestgenügt für so eine Action. Das Labelubuntu-docker, das den Docker-Socket mitbringt, braucht nur, wer wirklich eine Docker-Action oder einen Build ausführt.