Am Montag stand AutoBrew auf Version 2.4. Am Mittwoch war v2.5.0 live, und vor dem Wochenende hatte ich v2.5.1 und v2.5.2 schon hinterhergeschickt. Drei Releases in fünf Tagen klingt nach Chaos, war aber das Gegenteil: eine Reihe neuer Funktionen, ein Layout-Fehler, der sofort behoben werden musste, und eine Aufräumaktion, die ich schon länger vor mir hergeschoben hatte. Hier steht ohne Beschönigung, was diese Woche in meiner macOS-App-Entwicklung passiert ist.
AutoBrew v2.5: Was sich für Nutzer ändert
Neuer Versuch nach fehlgeschlagenem Upgrade
Diese Funktion wollte ich am dringendsten. Bisher galt: Schlägt ein Homebrew-Upgrade fehl, schreibt AutoBrew einen Fehlereintrag, und das war es. Wann er es noch einmal versucht, musste der Nutzer selbst entscheiden. Für eine App, die im Hintergrund läuft und automatisch aktualisieren soll, ist das grundsätzlich falsch.
v2.5 hat jetzt eine Retry-Logik mit gestaffelten Wartezeiten: Nach einem fehlgeschlagenen Upgrade versucht AutoBrew es nach einer Stunde erneut, dann nach vier Stunden, dann nach zwölf. Das klingt einfach, war in der Umsetzung aber knifflig. Der Retry-Zustand muss Neustarts der App überstehen, denn ein fehlgeschlagenes Upgrade darf nicht in Vergessenheit geraten, nur weil der Mac kurz geschlafen hat. Ich speichere den Zustand jetzt dauerhaft pro Cask-Bezeichner. Beim nächsten Start arbeitet die Retry-Logik zuerst die offene Warteschlange ab, bevor sie neue Upgrades anstößt.
Snapshots mit Blick auf den freien Speicher
Die Snapshot-Engine aus v2.4 hatte einen blinden Fleck: Sie hat vor jedem Upgrade einen Snapshot angelegt, auch wenn kaum noch Speicher frei war. Auf vollen Laptops konnte der Snapshot selbst das System an den Rand bringen.
v2.5 prüft jetzt vor jedem Snapshot den freien Platz auf dem Volume mit dem Home-Verzeichnis. Liegt er unter dem eingestellten Schwellwert, standardmäßig 10 GiB, überspringt die App den Snapshot für dieses Cask und teilt dem Nutzer in einer Benachrichtigung den Grund mit. Das Upgrade selbst läuft trotzdem durch. In der Update-Verlaufsansicht ist der Button zum Zurücksetzen für diesen einen Eintrag deaktiviert, mit einem Hinweis auf den Grund. Den Schwellwert kann man einstellen: Wem 10 GiB zu vorsichtig sind, der setzt ihn herunter.
Diese Lösung gefällt mir. Sie ist vorsichtig und nachvollziehbar und lässt dem Nutzer die Kontrolle. Es gibt weder stilles Versagen noch ein rabiates Blockieren.
Widget mit Sofort-Aktion
Das große Widget zeigt jetzt einen direkten Link “Jetzt ausführen”, der einen manuellen Upgrade-Durchlauf startet. Das klingt nach einem kleinen Detail, ist aber die erste Stelle in AutoBrew, an der etwas außerhalb des Popups in der Menüleiste wirklich interaktiv ist. Technisch läuft das über das URL-Scheme, das ich in v2.4 eingeführt habe: Das Widget ruft intern dieselbe Route auf wie das CLI. Gekostet hat mich das weniger als eine Stunde, und es war am Ende das beste Argument dafür, das URL-Scheme damals sauber zu abstrahieren.
Zwei Patches und eine Aufräumaktion
v2.5.1: der Layout-Fehler in den Sammlungen
v2.5.0 war keine drei Stunden live, als der erste Fehlerbericht kam. Die Ansicht der Sammlungen im BrewStore hat bei schmalen Fenstern eine zweite, verschachtelte Seitenleiste gezeichnet. Die innere Liste wurde auf wenige Pixel zusammengedrückt und der Platzhaltertext abgeschnitten. Das sah aus wie ein früher Beta-Build.
Die Ursache: Ich hatte dort eine NavigationSplitView eingebettet, wo ein flaches HStack-Layout völlig gereicht hätte. Bei verschachtelten NavigationSplitView-Instanzen ist SwiftUI manchmal nachsichtig, hier war es das nicht. Die Korrektur in v2.5.1 war ein Austausch von zwei Minuten, das Problem zu erkennen hat länger gedauert. Genau solche Fehler sieht man erst, wenn echte Nutzer eine Fenstergröße verwenden, die man im Simulator nie ausprobiert hat.
v2.5.2: drei tote Symbole entfernt
v2.5.2 ist reine Haushaltspflege. In der Codebasis hatten sich drei Symbole angesammelt, die niemand mehr aufgerufen hat: AppLogger (alle Aufrufer erzeugen Logger(subsystem:category:) direkt, die Wrapper-Klasse war überflüssig), der Enum-Case Severity.other in DoctorReport (nie zugewiesen, nie abgefragt) und zwei Properties in RestoreWizardStore, nämlich sourceURL und restoreList, die beim Laden des Bundles zwar geschrieben, aber nie gelesen wurden.
Toter Code ist in Swift besonders ärgerlich, weil der Compiler nicht immer warnt: Properties, die nur geschrieben werden, sind syntaktisch völlig korrekt. Ich habe mir angewöhnt, vor jedem Minor-Release einmal die Funktion “Find Call Hierarchy” in Xcode durchzugehen und alles ohne Aufrufer zu löschen. Das wird nie eine große Funktion, aber es hält die Codebasis lesbar.
Signing in der CI bereinigt
Neben den Releases habe ich die CI-Pipeline aufgeräumt. Anfang der Woche lag in GitHub Actions noch ein Secret keychain-password, das sich mit den Secrets von match überschnitten hat. Seit match v1.3.0 deckt MATCH_PASSWORD das ab. Der zusätzliche Wert war überflüssig und hat auf dem Runner gelegentlich zu widersprüchlichen Zuständen im Schlüsselbund geführt.
Außerdem habe ich kurz versucht, die Pipeline mit automatischem Signing laufen zu lassen, und das dann wieder rückgängig gemacht. Automatisches Signing und Provisioning-Profile für Hilfswerkzeuge vertragen sich in Xcode nicht so leicht, wie die Dokumentation es nahelegt. Ich bin zu manuellem Signing mit Profil zurückgekehrt. Die Versuchung, das zu vereinfachen, ist groß. Es funktioniert jetzt aber verlässlich, und das ist mehr wert als eine elegantere YAML-Datei.
Was das für Ihre eigene App bedeutet
Wenn Sie überlegen, eine macOS-App entwickeln zu lassen, zeigt AutoBrew gut, wie ein Einzelprojekt über Monate reift. Nicht jede Woche bringt viele neue Funktionen. Manchmal liegt der Wert in einem Layout-Fehler, der sofort behoben wird, oder in drei Zeilen totem Code weniger. Verlässlichkeit entsteht durch diese kleinen Schritte genauso wie durch neue Funktionen. Wenn Sie wissen möchten, wie so ein Entwicklungsprozess für Ihr Projekt aussähe, schauen Sie bei den Leistungen vorbei.
Die aktuellen Release Notes zu v2.5.0 bis v2.5.2 finden Sie direkt auf der AutoBrew-Seite bei GitHub.