Kai Ole Hartwig
6 Min. Lesezeit
Niedrig
Von

pinup: Warum ich meinen Renovate-Runner durch ein Go-Binary ersetzt habe

Renovate hat bei mir über Jahre Merge-Requests für meine Repositories geöffnet, zuletzt für rund 200. Zuverlässig, soweit man das sehen konnte. Trotzdem habe ich es im September abgelöst. Nicht wegen der Updates, die es gemacht hat. Sondern wegen der Updates, die es nicht gemacht hat, ohne es zu sagen.

Der Nachfolger heißt pinup. Ein statisches Go-Binary, das die vorhandene Renovate-Konfiguration liest, vor jeder Änderung einen Plan schreibt und für jedes zurückgehaltene Update den Grund nennt. Es ist Open Source, unter Apache-2.0.

01 — Renovate lief. Genau das war das Problem

Mein Setup war nicht klein. Sieben Scan-Partitionen im Stundentakt, eine Fast-Lane für eigene Releases, eine default.json mit 88 KB und 25 Custom Managern. Jeder Stundenlauf kostete 40 Minuten Wall-Zeit und 128 Runner-Minuten. Dazu kam ein Node-Sidecar für die apk-Datenquelle, die Renovate nicht kennt.

Teuer war aber etwas anderes. Die Fehler waren still. Eine automatische Migration der Konfiguration verpackte die fileMatch-Regexe doppelt. Danach lief kein einziger Custom Manager mehr. Eine Gruppenregel verglich den Composer-Namen, Renovate prüfte aber den internen Paketnamen. Die Gruppe griff also nie, und die Merge-Requests stritten sich um dieselbe composer.lock. Ein anderes Lock wurde ein Jahr lang gar nicht aktualisiert.

Keiner dieser Fehler hat einen roten Job erzeugt. Renovate war jedes Mal grün. Ich habe sie gefunden, weil erwartete Updates ausblieben, nicht weil mir etwas gemeldet wurde.

02 — Ein Plan vor dem ersten geschriebenen Byte

Renovate sagt, was es getan hat. Es sagt nicht, was es nicht getan hat und warum. Genau diese Lücke schließt pinup.

Jeder Lauf erzeugt zuerst einen maschinenlesbaren Plan. pinup whatif hört dort auf, pinup run macht weiter. Jedes zurückgehaltene Update trägt im Plan seinen Grund, die Regel, die es hält, und den Zeitpunkt, an dem die Sperre fällt.

 

lodash 4.17.20 -> 4.17.21  ready
redis 20.13.4 -> 28.1.0  dependencyDashboardApproval packageRules[3]

 

Die erste Zeile wird beim nächsten Lauf ein Branch. Die zweite sagt, welche Regel das Major-Update hält und wo sie steht. Mit --now rechnet pinup den Plan für einen anderen Zeitpunkt. So prüfe ich einen Zeitplan oder ein minimumReleaseAge, ohne darauf zu warten.

Was ein Versionslabel verschweigt

Zwei weitere Dinge sieht pinup, die mir vorher gefehlt haben. Ein Tag, dessen Digest sich geändert hat, ist kein Update. Bei latest ist das normal. Bei v2.10.0 wurde eine veröffentlichte Version überschrieben, und der Plan sagt, welcher Fall vorliegt.

Bei Helm-Charts fragt ein Analyzer, was sich wirklich geändert hat: die App-Version, weggefallene Values-Keys, Subcharts und die Images, die das Chart selbst setzt. Diese Images stehen in keiner Datei meines Repositories, also hätte sie sonst niemand gepinnt. Daraus entsteht ein Effective-Label neben dem deklarierten. Lockern darf es einen Automerge nur, wo eine Regel ihm ausdrücklich vertraut.

03 — Umstieg ohne eine geänderte Zeile Konfiguration

pinup liest die vorhandene renovate.json: extends, Presets, packageRules, Custom Regex Manager, Schedules, minimumReleaseAge, Lock-File-Maintenance, postUpgradeTasks, OSV-Alerts und das Dependency-Dashboard. pinup migrate zeigt Schlüssel für Schlüssel, was eine Konfiguration nutzt und was pinup davon unterstützt.

Branch-Namen und Titel der Merge-Requests sind dieselben wie bei Renovate. Offene Branches übernimmt pinup. Beim Wechsel entstand kein einziger doppelter Merge-Request.

Erst vergleichen, dann umschalten

Vor der Umstellung lief pinup im Shadow-Modus. Es verglich seine Pläne Lauf für Lauf mit den Merge-Requests, die Renovate offen hatte. Ein Kontroll-Repository, das bewusst abweichen muss, verhindert, dass sich der Vergleich selbst bestätigt. Erst als beide übereinstimmten, habe ich umgeschaltet.

Clean Room statt Fork

Renovate steht unter AGPL-3.0. Die Konfigurationssprache durfte ich übernehmen, den Code nicht lesen. pinup ist deshalb ein Clean-Room-Nachbau. Ich habe den gepinnten Renovate-Container ausgeführt und das Verhalten aus aufgezeichneten Ein- und Ausgabepaaren nachgebaut. Diese Paare sind heute die Testsuite. pinup selbst steht unter Apache-2.0, wie alle meine Go-Werkzeuge.

04 — Was sich gemessen geändert hat

Ein vollständiger Lauf über alle Repositories braucht jetzt 10,6 statt 40 Minuten Wall-Zeit und 75 statt 128 Runner-Minuten. pinup hat keine Laufzeitumgebung und zwei Fremdabhängigkeiten. Der Node-Sidecar ist weg.

Wichtiger ist die Kette dahinter. Am 25. September habe ich sie einmal von Anfang bis Ende gemessen, an einem echten Release dieses Blogs:

Uhrzeit (UTC)Schritt
07:02Release des Blog-Pakets 3.23.0
07:03pinup öffnet den Merge-Request in der Website-App
07:10Merge-Request gemergt, App-Release folgt
07:19pinup öffnet den Deploy-MR in der GitOps-Konfiguration
07:48pinup mergt den Deploy-MR
07:57Änderung live

Knapp eine Stunde vom Tag bis zur Produktion, ohne dass ich eingreifen musste. Ein zweites Release kam währenddessen nach. pinup hat den noch offenen Deploy-MR darauf hochgezogen, statt einen zweiten zu öffnen.

Häufige Fragen

Muss ich meine renovate.json für pinup anpassen?+

Nein. pinup liest die vorhandene Konfiguration so, wie sie ist. Vorher zeigt pinup migrate Schlüssel für Schlüssel, was die Konfiguration nutzt und was pinup davon unterstützt. Branch-Namen und Titel bleiben gleich, offene Branches werden übernommen.

Wie riskant ist der Umstieg von Renovate auf pinup?+

Er lässt sich in Stufen gehen. pinup whatif ändert nichts und braucht kein Token. Danach folgt ein --dry-run gegen ein echtes Projekt. Im Shadow-Modus vergleicht pinup seine Pläne mit den offenen Merge-Requests von Renovate. Umschalten lohnt sich erst, wenn beide übereinstimmen.

Läuft pinup auch mit GitHub?+

Ja. Seit September 2026 läuft pinup auf GitHub in einem ersten Produktions-Repository, einem Helm-Chart. Dort führt ein Workflow pinup als GitHub App aus und öffnet Pull Requests, bisher ohne Automerge. Automerge auf GitHub ist gegen einen Nachbau der API getestet. Der große Bestand mit rund 200 Repositories läuft auf GitLab.

Warum ist pinup kein Fork von Renovate?+

Renovate steht unter AGPL-3.0. Ein Fork hätte diese Lizenz geerbt. pinup ist ein Clean-Room-Nachbau: Das Verhalten wurde am gepinnten Renovate-Container beobachtet und aus aufgezeichneten Ein- und Ausgabepaaren nachgebaut. Kein Code wurde übernommen. Deshalb kann pinup unter Apache-2.0 stehen.

Fazit

pinup ersetzt nicht Renovates Konfigurationssprache, sondern seinen Runner. Die Regeln bleiben. Der Betrieb wird günstiger und vor allem ehrlicher: Wenn ein Update nicht kommt, steht im Plan, warum. Für mich war das der eigentliche Grund. Die gesparten Runner-Minuten sind der Bonus.

Code, Releases und Dokumentation liegen auf GitHub. Einen Überblick mit Quickstart gibt es auf der Projektseite zu pinup.

Ich stelle deinen Renovate-Betrieb auf pinup um. Oder sage dir, warum sich das für dein Setup nicht lohnt.

Konfigurations-Check mit pinup migrate, Shadow-Betrieb neben dem bestehenden Runner und ein Umstieg, bei dem kein Merge-Request doppelt entsteht.

Plattform-Betrieb statt Beratung auf Papier: Ich betreibe die Dependency-Automation auf Wunsch auch dauerhaft mit, inklusive der Regeln, die erklären, warum ein Update wartet.

Termin buchen →

Über den Autor

Foto von Kai Ole Hartwig.

Kai Ole Hartwig

Freiberuflicher DevSecOps-Berater · OnlyOle Consulting

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.