Dependabot ist keine Wartungsstrategie

#automatisierte Abhängigkeits-Updates

Gründer & Lead Developer

Experte für Softwareentwicklung und Legacy-Code-Optimierung

LinkedIn

Die meisten Teams, die Dependabot oder Renovate aktivieren, behandeln das als Ziellinie und nicht als Startpunkt. Das Tool öffnet einen Pull Request, sobald eine neue Paketversion verfügbar ist, und der Rückstand veralteter Abhängigkeiten sieht gelöst aus. Ein paar Wochen später hat dasselbe Team vierzig offene Pull Requests, niemand hat seit längerem etwas zusammengeführt, und die automatisierten Abhängigkeits-Updates, die die Codebasis aktuell halten sollten, erzeugen ein eigenes Wartungsproblem: eine lange Liste ungeprüfter Änderungen, für die niemand Zeit hat.

Das ist kein Fehler der Tools. Dependabot und Renovate tun genau das, wofür sie gebaut wurden: Paketmanifeste beobachten, neue Releases erkennen und einen Pull Request öffnen. Was sie nicht tun, ist, die Änderung gegen Ihre tatsächliche Anwendung zu testen, zu beurteilen, ob ein Versionssprung sicher ist, oder irgendetwas zusammenzuführen. Dieser Teil erforderte immer schon einen Menschen, und viele Teams führen die Automatisierung ein, ohne zu planen, wer diese Person sein soll und wann sie die Arbeit erledigt.

Was Dependabot und Renovate wirklich gut können

Beide Tools lösen dasselbe Problem: Jemand muss merken, dass ein Paket eine neue Version veröffentlicht hat. Bevor es automatisierte Abhängigkeits-Updates gab, bedeutete das, dass ein Entwickler regelmäßig npm outdated oder composer outdated ausführte und Versionsnummern von Hand verglich, meist nicht oft genug. Dependabot, fest in GitHub integriert, und Renovate, das als Bot mit mehr Konfigurationsmöglichkeiten läuft, beobachten beide Ihre Manifestdateien und öffnen in dem Moment einen Pull Request, in dem eine neue Version veröffentlicht wird.

Renovate gibt Ihnen in der Regel mehr Kontrolle darüber, wie Updates gruppiert und geplant werden, was wichtig wird, sobald ein Projekt mehr als eine Handvoll Abhängigkeiten hat. Dependabot ist einfacher zu aktivieren und ist eng mit GitHubs eigenen Sicherheitshinweisen verzahnt, was es zu einer vernünftigen Standardwahl für eine kleinere Codebasis macht. Keines der beiden Tools ist in einem absoluten Sinne besser. Die Entscheidung zwischen Dependabot und Renovate läuft meist darauf hinaus, wie viel Konfigurationsaufwand ein Team bereit ist zu pflegen, gegenüber wie viel Kontrolle es über Gruppierung und Timing haben möchte.

Was beide richtig machen, ist das Erkennen. Ein Sicherheitspatch für ein Paket, von dem Sie abhängen, erscheint, und innerhalb eines Tages haben Sie einen Pull Request, der darauf hinweist. Das ist eine echte Verbesserung gegenüber niemandem, der es sechs Monate lang nicht merkt, was auf vielen Codebasen üblich war, bevor es eines der beiden Tools gab.

Wo die Warteschlange zu wachsen beginnt

Das Problem zeigt sich im nächsten Schritt. Ein Pull Request von Dependabot oder Renovate sieht in GitHub genau so aus wie einer, den ein Entwickler von Hand öffnen würde, aber niemand hat ihn geschrieben, und niemand ist automatisch dafür verantwortlich, ihn zu prüfen. Wenn Ihre CI-Pipeline eine vollständige Testsuite ausführt, gibt Ihnen ein bestandener Check etwas Vertrauen. Wenn nicht, oder wenn die Suite nur einen Teil der Anwendung abdeckt, bedeutet dieses grüne Häkchen weniger, als es aussieht.

Die meisten Teams starten mit guten Absichten. Die ersten automatisierten Pull Requests werden schnell geprüft und zusammengeführt. Dann wird ein Sprint hektisch, drei offene Pull Requests werden zu fünfzehn, und fünfzehn Versionssprünge zu prüfen fühlt sich wie eine größere Aufgabe an als einen zu prüfen, also wird es auf nächste Woche verschoben. Nächste Woche hat ihre eigenen fünfzehn. Nach ein paar Monaten hat das Repository eine Wand offener Pull Requests, die niemand anfassen will, weil ein Zusammenführen außerhalb der richtigen Reihenfolge riskiert, eine Abhängigkeit über eine andere zu ziehen, die noch nicht getestet wurde, und der Stapel ist selbst zu einer Risikoquelle geworden.

An diesem Punkt haben automatisierte Abhängigkeits-Updates das Problem auf eine bestimmte Weise verschlimmert. Bevor es die Automatisierung gab, lag ein altes Paket einfach ruhig da, veraltet, aber stabil. Jetzt gibt es einen Stapel halb geprüfter Änderungen, von denen jede eine Breaking Change einführen könnte, und die Lücke zu schließen bedeutet, sie in der richtigen Reihenfolge abzuarbeiten, statt einfach die wichtigste herauszupicken.

Die Teile, die kein Tool für Sie übernehmen kann

Ein Bot kann Ihnen sagen, dass ein Paket von Version 3.2 auf Version 4.0 gesprungen ist. Er kann Ihnen nicht sagen, ob dieser Sprung eine Funktionssignatur geändert hat, die Ihr Code aufruft, einen Standardwert veraltet hat, auf den sich Ihre Anwendung verlässt, oder einen Fehler behoben hat, von dem Ihr Code versehentlich abhing. Ein Changelog zu lesen und zu entscheiden, ob ein Major-Versionssprung sicher zusammengeführt werden kann, ist Beurteilungsarbeit, und das erfordert, die Anwendung zu kennen, nicht nur das Paket.

Dasselbe gilt für die Priorisierung. Ein Sicherheitspatch für eine Authentifizierungsbibliothek und ein routinemäßiger Minor-Versionssprung für ein Formatierungs-Tool können beide als Pull Requests erscheinen, die in einer GitHub-Benachrichtigungsliste sehr ähnlich aussehen. Jemand muss sich jeden einzeln ansehen und entscheiden, welcher diese Woche wichtig ist und welcher auf den regulären Zyklus warten kann. GitHubs Sicherheitshinweise markieren den Schweregrad einigermaßen gut, aber der Schweregrad allein sagt Ihnen nicht, wie ein Paket in Ihrer Anwendung tatsächlich genutzt wird, und nur jemand, der die Codebasis kennt, kann beides gegeneinander abwägen.

Dann gibt es noch das eigentliche Testen. Automatisierte Testsuites fangen einen bedeutenden Anteil von Regressionen ab, aber die meisten Anwendungen haben keine so tiefe Testabdeckung, dass sie alles abfangen, was ein Abhängigkeits-Update kaputt machen könnte, besonders Grenzfälle, wie die Anwendung eine Bibliothek aufruft. Jemand muss sich die Änderung trotzdem ansehen und entscheiden, ob eine manuelle Prüfung sich lohnt, bevor etwas ausgeliefert wird.

Wie ein funktionierender Zyklus statt dessen aussieht

Die Lösung ist nicht, Dependabot oder Renovate abzuschalten. Es ist, die Pull Requests, die sie öffnen, als Input für einen Prozess zu behandeln, nicht als den Prozess selbst. Ein monatlicher Zyklus funktioniert für die meisten Anwendungen, die nichts ungewöhnlich Sensibles verarbeiten: ein fester Tag jeden Monat, an dem jemand jeden offenen Abhängigkeits-Pull-Request durchgeht, die Routine-Updates gruppiert, alles markiert, das wie eine Breaking Change aussieht, und zusammenführt, was sicher ist. Sicherheitspatches werden aus diesem Zyklus herausgezogen und auf einer eigenen, schnelleren Uhr behandelt, meist innerhalb von ein bis zwei Tagen, nachdem der Hinweis öffentlich wurde, statt auf den monatlichen Durchlauf zu warten.

Das ist nahe an dem Ansatz, den wir beschrieben haben, als es um die Frage ging, was ein Software-Wartungsvertrag umfassen sollte: ein fester Rhythmus, ein definierter Testschritt und eine separate, schnellere Spur für alles Sicherheitsrelevante. Automatisierte Abhängigkeits-Updates fügen sich als Input in diesen Zyklus ein, nicht als Ersatz dafür. Das Tool sagt Ihnen, was sich geändert hat. Der Zyklus entscheidet, was damit zu tun ist.

Wenn Ihr Repository bereits den Stapel ungeprüfter Pull Requests hat, den dieser Beitrag beschreibt, ist der schnellste Weg heraus meist nicht, zu versuchen, alles auf einmal zusammenzuführen. Beginnen Sie mit Sicherheitspatches und arbeiten Sie sich dann rückwärts durch die ältesten Routine-Updates, da diese am ehesten schon von einer neueren Version abgelöst wurden. Eine saubere Warteschlange, die durch regelmäßige Überprüfung sauber gehalten wird statt durch einen unbeaufsichtigten Bot, ist das eigentliche Ziel. Wir haben auch darüber geschrieben, warum Abhängigkeits-Updates überhaupt erst aufgeschoben werden, was einen Blick wert ist, wenn der Stapel in Ihrem Repository weniger wie ein frischer Rückstand aussieht und mehr wie etwas, das sich seit einem Jahr aufbaut.

Wer das verantworten sollte

In einem kleinen Team fällt das meist demjenigen zu, der bereits die Deployments verantwortet, mit einer Kalendererinnerung, damit der monatliche Durchlauf tatsächlich stattfindet, statt in einem hektischen Sprint untergeht. In einem größeren Team lohnt es sich, jemanden konkret zu benennen, denn „wer auch immer Zeit hat" bedeutet meist, dass es niemand tut. Wenn Ihr Team nicht die Kapazität hat, das konsequent zu übernehmen, passt es natürlich in ein laufendes Code-Qualitäts-Consulting-Engagement, bei dem jemand außerhalb des Sprint-Zyklus dafür verantwortlich ist, dass die Abhängigkeits-Warteschlange nicht unkontrolliert wächst.

In jedem Fall hat das Tool seinen Job bereits erledigt, sobald es einen Pull Request öffnet. Was danach passiert, liegt weiterhin bei Ihnen. Wenn Sie eine zweite Meinung dazu möchten, wie Ihre aktuelle Abhängigkeits-Warteschlange aussieht, oder Hilfe beim Aufbau eines Zyklus, der sie tatsächlich leer hält, schreiben Sie uns an hello@wolf-tech.io oder schauen Sie auf wolf-tech.io vorbei.