Nichts passiert ohne Grund
Ein Update, das nicht kommt, ist die teuerste Nachricht in der Dependency-Automation. Sie kommt nämlich gar nicht. Man merkt sie erst, wenn man ein bestimmtes Update erwartet und es ausbleibt.
pinup hat deshalb eine erste, strenge Meinung: Jedes zurückgehaltene Update nennt seinen Grund, die Regel, die es hält, und den Zeitpunkt, an dem die Sperre fällt. Abwesenheit ist nie einfach Abwesenheit.
01 — Die Meinung in einem Satz
Ein Update, das pinup findet und nicht umsetzt, steht trotzdem im Plan. Mit Grund.
Der Grund ist kein Freitext, sondern einer von gut einem Dutzend festen Werten: schedule, minimumReleaseAge, dependencyDashboardApproval, taskRefused, die beiden Limits und einige mehr. Dazu kommt die Herkunft: welche Datei, welche Regel. Bei zeitlichen Sperren kommt der Zeitpunkt dazu, an dem sie fallen.
"blocks": [{
"reason": "dependencyDashboardApproval",
"origin": { "source": "file:.pinup.yaml", "rule": 3 }
}]
Das Dependency-Dashboard sortiert dasselbe nach Grund: Freigaben zum Abhaken, Zeitfenster und Release-Alter mit ihrem Termin, alles andere unter „Held“ mit Grund, Regel und Datei, etwa taskRefused: … · held by packageRules[3] (file:.pinup.yaml). Wer wissen will, warum ein Update fehlt, liest eine Zeile statt eines Logs.
02 — Die Alternative: das Log
Renovate löst dieselbe Frage anders. Einiges steht im Dashboard: wartende Freigaben, Zeitfenster, Limits. Vieles andere steht im Debug-Log. Ein Post-Upgrade-Befehl, den die Liste erlaubter Befehle nicht zulässt, wird übersprungen, und der Branch geht trotzdem hinaus.
Für Renovate ist das richtig. Es bedient Tausende Setups mit sehr unterschiedlichen Regeln. Jeden übersprungenen Schritt sichtbar zu machen, würde viele Dashboards fluten. Und wer Renovate betreibt, hat das Log, mit allen Details.
In meinem Bestand hat genau das nicht gereicht. Bei rund 200 Repositories liest niemand Debug-Logs, wenn nichts rot ist. Und keiner dieser Fälle machte einen Job rot.
03 — Der Preis
Die Meinung kostet an drei Stellen.
Mehr Code in jeder Stufe. Jeder Filter, der ein Update aufhält, muss einen Grund liefern. Ein neuer Filter ohne eigenen Grund lässt sich nicht einbauen. Das macht jede Erweiterung etwas langsamer.
Längere Pläne. Der Plan enthält auch alles, was nicht passiert. Das ist gewollt, aber er wird dadurch deutlich größer als eine Liste der offenen Merge-Requests.
Ein Dashboard, das Disziplin braucht. Nicht jeder Grund ist für Menschen interessant. Eine Lock-Datei, die schon aktuell ist, wartet nicht, sie ist fertig. Solche Fälle muss das Dashboard auslassen, sonst meldet es jede Nacht ein Problem, wo keines ist.
04 — Der Anlass
Im alten Betrieb gab es drei stille Fehler, die diese Meinung ausgelöst haben. Eine automatische Migration verpackte Regexe doppelt, danach lief kein Custom Manager mehr. Eine Gruppenregel verglich den falschen Paketnamen und griff nie. Ein Lock blieb ein Jahr lang stehen. Keiner davon erzeugte einen roten Job. Mehr dazu im Beitrag zum Umstieg.
Und dann traf es pinup selbst
Am 25. September kamen die Updates für den PHP-Interpreter in meinen Wolfi-Paketen nicht. Diesmal musste ich nicht suchen. Eine Warnung im Plan nannte den Grund in einer Zeile: Die Regel mit allowedVersions enthielt einen Bereich in npm-Schreibweise, und pinup las ihn unter semver nicht.
Das war ein Fehler in pinup, nicht in der Konfiguration. Renovate fällt in diesem Fall auf die npm-Schreibweise zurück, pinup tat es nicht. Behoben war es noch am selben Tag. Der Unterschied zum alten Betrieb: Der Fehler war sichtbar, bevor ihn jemand vermisst hat.
Derselbe Fall zeigte auch eine Lücke. Schloss allowedVersions jede neuere Version aus, meldete der Plan die Abhängigkeit als aktuell. Seit pinup 0.47 steht dort stattdessen eine Zeile wie held by allowedVersions "/^8\.2\./" (packageRules[12]): 3 newer releases excluded, the newest 8.5.2. Sie nennt die Regel und die neueste Version hinter der Grenze, und das Dashboard zeigt sie auch.
Seit pinup 0.48 gilt das auch neben einem erlaubten Update. Das Dashboard zeigt hinter dem Update, welche neuere Version die Regel noch zurückhält.
05 — Die Durchsetzung
Eine Regel, die nur in der Dokumentation steht, hält nicht lange. Diese steht an drei Stellen im Code.
- Im Typ. Ein zurückgehaltenes Update trägt seine Sperren als Liste mit Grund und, wo es sie gibt, Herkunft und Zeitpunkt. Es gibt keinen Weg, ein Update ohne Grund zurückzuhalten.
- In den Golden-Tests. Sie vergleichen jeden Plan mit einer geprüften, abgelegten Erwartung. Eine Abhängigkeit ohne Update und ohne Grund für das Fehlen ist ein Testfehler.
- In einer festen Liste. Die Tests kennen jede Formulierung, mit der eine Stufe etwas überspringt. Eine neue Stufe mit neuer Formulierung fällt als roter Test auf und wird bewusst aufgenommen.
Dazu kommt pinup whatif --now. Damit rechne ich den Plan für einen anderen Zeitpunkt. So prüfe ich, ob ein Zeitfenster oder ein minimumReleaseAge tatsächlich fällt, wann es fallen soll.
Häufige Fragen
Zeigt Renovates Dashboard das nicht auch?+
Zum Teil. Wartende Freigaben, Zeitfenster und Limits stehen dort. Anderes steht nur im Debug-Log, etwa ein Post-Upgrade-Befehl, der nicht erlaubt ist. pinup hält ein solches Update mit Grund im Plan und im Dashboard.
Wie komme ich an den Plan?+
pinup whatif --repo . --config .pinup.yaml schreibt ihn als JSON, ohne Token und ohne Schreibzugriff. Wer eine renovate.json hat, gibt stattdessen --config renovate.json an. pinup run legt den Plan als Artefakt ab. Das Dependency-Dashboard zeigt die zurückgehaltenen Updates nach Grund sortiert.
Und was ist mit Versionen, die gar nicht erst gefunden werden?+
Die sind die Grenze dieser Meinung. Ein Plan kann nur über Abhängigkeiten sprechen, die ein Manager gelesen hat. Für den Rest gibt es den Abdeckungs-Scan. Darum geht es in Teil 3 der Serie.
Fazit
Ein Update, das nicht kommt, braucht einen Grund, den jemand lesen kann. Das kostet Code, längere Pläne und ein aufgeräumtes Dashboard. Dafür fallen Fehler auf, bevor jemand sie vermisst, auch die im Werkzeug selbst.
Nächste Woche geht es um Prüfungen, die nie rot waren, und warum man ihnen nicht trauen sollte. Die Übersicht aller Teile und die Begriffe, die öfter vorkommen, stehen im Auftakt der Serie.
Warum kommt dein Update nicht? Ich finde den Grund.
Ein Plan über deine Repositories mit pinup whatif, ohne Schreibzugriff: welche Updates zurückgehalten werden, von welcher Regel und bis wann.
Über den Autor

Kai Ole Hartwig
Programmiert seit 2002 – autodidaktisch gelernt, 2012 mit KO-Web selbständig gemacht. Über 100 Projekte, Fokus auf Security, Performance, Automatisierung und Qualität. Heute freiberuflich: DevSecOps-Beratung, Schulungen und Softwareentwicklung.
