Upgrades
Migration bei einer Breaking Change
Jede Änderung, die eine Anpassung in deinem Code erfordert, steht mit Vorher-Nachher-Beispiel im Migrationsleitfaden des betroffenen Packages:
- Migrationsleitfaden @mittwald/flow-react-components
– deckt auch
@mittwald/flow-remote-react-componentsab - Migrationsleitfaden @mittwald/ext-bridge
Die Einträge sind nach Version absteigend sortiert und nennen jeweils die Version, ab der die Änderung greift. Suche die Version, von der du kommst, und arbeite dich nach oben durch. Was dabei überhaupt als Breaking Change zählt und eine neue Major-Version erzwingt, beschreibt Versionierung & Stabilität.
Nutze die Codemod-CLI
Ein Befehl hebt alle Flow-Abhängigkeiten auf die Zielversion, installiert und führt den Codemod jeder Migration bis zu dieser Version aus:
Ohne Argument geht es auf die nächste Minor innerhalb deiner Major.
upgrade patch bleibt auf deiner Minor, upgrade major überquert eine
Major-Grenze, und eine exakte Version oder ein Dist-Tag (next) gehen genau
dorthin.
Der Befehl ändert Dateien direkt und bricht auf einem unsauberen Git-Stand ab.
Der Befehl kennt keine untere Grenze: er listet auch Migrationen, die vor deiner aktuellen Version erschienen sind. Nichts hält fest, welche davon dein Projekt schon durchgeführt hat – und ein zweiter Durchlauf eines Codemods ändert nichts.
Ein Codemod, der durchgelaufen ist, ist allerdings kein Beweis: jeder Codemod ist bewusst eng gefasst und lässt liegen, was er aus dem Code nicht sicher entscheiden kann – ein gespreadetes Prop, eine Component, die über einen eigenen Wrapper re-exportiert wird, ein dynamischer Zugriff. Einen Fehler meldet er dafür nicht. Prüfe nach einem Upgrade deshalb auch die Migrationen mit Codemod am Code nach, nicht nur die ohne.
Er ersetzt den Migrationsleitfaden nicht: die meisten Einträge haben keinen
Codemod. Welche das für deinen Bereich sind, listet der Befehl am Ende auf –
oder vorab, ohne etwas zu verändern, mit list und derselben Revision:
list ohne Argument zeigt den gesamten Katalog, offline. Mit einer Revision
liest es dieselbe Version aus deinem package.json und zeigt genau den Bereich,
den upgrade mit dieser Revision anfassen würde – ein echter Trockenlauf.
Einen einzelnen Codemod führst du über seine ID aus:
Lass einen Agenten das Upgrade machen
Was die CLI offen lässt, kann ein Coding-Agent übernehmen: die Migrationen ohne
Codemod – das sind die meisten – und die Stellen, die ein Codemod übersprungen
hat. list --json liefert ihm dafür pro Migration das Feld apply: die
Anweisung, was zu ändern ist, knapp genug für einen Katalog und präzise genug
zum Ausführen.
Kopiere den folgenden Prompt in deinen Agenten. Er sucht zuerst, wo Flow
überhaupt deklariert ist – in einem Monorepo ist das meist mehr als ein Package,
und list wie upgrade lesen immer nur die package.json des Verzeichnisses,
in dem sie laufen. Dann klärt er auf, welche Zielversionen zur Wahl stehen und
was jede davon an Arbeit bedeutet, und fragt dich, welche es sein soll. Danach
geht er jede Migration im Bereich am Code nach – auch die mit Codemod – und
ändert nur, wo er das alte Muster wirklich findet.
Was dabei offen bleibt, gibt er dir nicht als Hausaufgabe zurück. Genau die Punkte, die eine Entscheidung brauchen, sind die, bei denen er den Diff gelesen hat und du nicht – deshalb legt er sie dir gesammelt vor, jeweils mit den Optionen und einer Empfehlung, setzt deine Antwort um und lässt die Checks erneut laufen. Das wiederholt sich, bis nichts mehr offen ist. Er hört vorher nur auf, wenn etwas wirklich nicht hier entschieden werden kann – eine Design-Entscheidung, eine Freigabe, ein Zugang – und sagt dann, worauf es wartet und wer es tun muss.
Der Prompt ist englisch, weil alles, worauf er zeigt, englisch ist: die
CLI-Ausgabe, die apply-Felder und der Migrationsleitfaden.
Zwei Dinge, die der Prompt bewusst nicht tut: Er lässt den Agenten nicht auf
einem unsauberen Git-Stand starten, damit ein missglückter Lauf ein
git checkout bleibt. Und er lässt ihn nichts an deinen peerDependencies
ändern – was deine eigenen Consumer installieren dürfen, ist deine Entscheidung.
Optional: erzähl uns, was nicht getragen hat
Ganz unabhängig vom Upgrade: der folgende Prompt ist ein zweiter, eigener Baustein. Du kopierst ihn – wenn du magst – direkt nach dem Upgrade in dieselbe Session. Der Agent hat den Lauf dann noch im Kontext und schreibt daraus einen Bericht auf zwei Ebenen. Nicht kopieren ist die Absage; am Upgrade ändert das nichts.
Der Prompt selbst. Ein Schritt in der falschen Reihenfolge. Eine Annahme, die auf dein Projekt nicht zutrifft. Eine Stelle, an der der Agent raten musste oder zwei Anweisungen sich widersprachen. Eine Situation, zu der der Prompt schweigt. Eine Anweisung, die Arbeit gekostet und nichts geändert hat.
Die einzelne Migration. Ein apply, das ohne Raten nicht ausführbar war.
Eine Stelle, die ein Codemod liegen gelassen hat, obwohl er sie hätte
entscheiden können. Eine Migration ohne Codemod, die mechanisch entscheidbar
wäre. Ein apply, das eine Umbenennung beschreibt, obwohl sich auch die
Signatur geändert hat. Ein Codemod, der abgestürzt ist. Und der wertvollste
Fall: ein Bruch, den deine Checks gefunden haben und für den es gar keinen
Katalogeintrag gibt.
Beide Ebenen sehen wir sonst nicht. Ob eine Migration verständlich beschrieben ist und ob der Upgrade-Prompt trägt, zeigt sich erst an einer echten Codebase – nicht an unserer. Ein Bericht als Issue hilft uns deshalb wirklich weiter: er fließt in den Katalog und in den Prompt zurück, und das nächste Upgrade ist für alle etwas weniger Handarbeit. Ein Paste genügt, und eine Antwort schuldest du niemandem.
Der Agent reicht ihn nicht selbst ein. Er legt ihn dir vor und sagt dir, was du damit tun kannst – du entscheidest, was rausgeht. Code-Beispiele reduziert er auf die kleinste anonymisierte Form, aber prüfen musst du das selbst.
Deprecation-Warnungen sind der Vorlauf
Wird ein Pfad deprecated, bleibt er funktionsfähig und meldet sich zur Laufzeit
per console.warn. Diese Warnungen sind die Vorwarnzeit vor der nächsten
Major-Version – behandle sie als Aufgabenliste, nicht als Rauschen. Um sie
zentral einzusammeln, etwa im Error-Tracking, umschließe deine Anwendung mit
einem DeprecationWarningProvider und gib ihm einen onWarning-Handler:
Direkt nach einem Release
Ein Release veröffentlicht die Packages nacheinander, nicht gleichzeitig.
Für einige Minuten liegt in der npm-Registry deshalb für die schon
veröffentlichten Packages die neue Version, für die restlichen noch die alte.
Beim Release 1.0.6 lagen zwischen dem ersten und dem letzten Package rund 25
Minuten.
Du triffst dieses Fenster leicht, denn ein Update betrifft immer mehrere
Packages: alle @mittwald/flow-*-Packages teilen sich eine gemeinsame Version,
und @mittwald/flow-react-components fordert @mittwald/flow-icons-pro als
Peer-Dependency in exakt derselben Version. Ziehst du in diesem Fenster alle
Flow-Abhängigkeiten auf die neue Version, schlägt die Installation für das
Package fehl, das noch nicht dran war:
pnpm meldet dasselbe als ERR_PNPM_NO_MATCHING_VERSION.
Das ist keine Lücke im Release: sobald der Release-Lauf durch ist, haben alle Packages dieselbe Version. Direkt nach einem Release ist dieser Fehler fast immer das Veröffentlichungsfenster und nichts anderes.