Abhängigkeiten aktualisieren
Das Ziel ist ein Projekt, dessen Abhängigkeiten aktuell und frei von bekannten Sicherheitslücken sind, bereitgestellt als eine Änderung, der der Benutzer vertrauen kann: jeder Schritt durch die eigenen Prüfungen des Projekts verifiziert und jeder riskante Schritt isoliert, damit er eigenständig überprüft oder rückgängig gemacht werden kann.
Abhängigkeitsarbeit scheitert auf zwei typische Weisen. Die eine ist das „Big-Bang“-Upgrade, bei dem alles auf einmal aktualisiert wird, etwas kaputt geht und niemand sagen kann, welches Update die Ursache war. Die andere ist ein „Fix“, der das Problem verbirgt, wie z. B. --force, --legacy-peer-deps, das Lockern eines Versionsbereichs oder das Unterdrücken eines Hinweises. Der folgende Workflow wurde entwickelt, um beides zu vermeiden.
0. Entscheiden, was gefragt wurde
- Nur prüfen („gibt es Sicherheitslücken?“, „was ist veraltet?“): Schritte 1–3 durchführen, melden und anhalten. Keine Dateien ändern.
- Aktualisieren (der Standard für „aktualisiere meine Abhängigkeiten“, „behebe die Audit-Warnungen“, „halte Pakete aktuell“): den gesamten Workflow durchführen.
- Ein Paket („aktualisiere vite auf v8“): Schritte 1–2 durchführen, dann Schritt 6 für dieses Paket (zusammen mit allen Paketen, die damit verschoben werden müssen), dann 7–8.
1. Vorbereitung
-
Lesen Sie die Mitwirkenden-Dokumente des Repositorys (
AGENTS.md,CLAUDE.md,CONTRIBUTING.md) und die CI-Konfiguration (.github/workflows/*), um die Verifikationsbefehle (Lint, Typprüfung, Test, Build) und die Commit-Message-Konvention zu erfahren. Verwenden Sie das, was das Repository tatsächlich in CI ausführt. Wenn nichts dokumentiert ist, verwenden Sie die im Manifest definierten Skripte. -
Stellen Sie sicher, dass der Arbeitsbaum sauber ist. Wenn nicht, anhalten und nachfragen. Das Mischen von uncommitteten Änderungen des Benutzers in Abhängigkeits-Commits verursacht echten Schaden.
-
Erkennen Sie die Ökosysteme anhand ihrer Lockfiles und Manifeste (ein Repository kann mehrere haben):
Dateien Referenz package-lock.json,pnpm-lock.yaml,yarn.lock,bun.lockreferences/node.mdrequirements*.txt,pyproject.toml,uv.lock,poetry.lock,Pipfile.lockreferences/python.mdCargo.toml/Cargo.lockreferences/rust.mdgo.mod/go.sumreferences/go.mdalles andere (Gemfile.lock, composer.lock, …) das eigene Tool des Ökosystems verwenden, plus scripts/osv_check.pyfür das AuditLesen Sie die passende Referenzdatei. Sie listet die genauen Befehle und die Fallstricke des jeweiligen Ökosystems auf.
-
Finden Sie die Laufzeitversion, die das Projekt anvisiert:
.nvmrc,engines,.python-version,requires-python,rust-version, diego-Direktive oder die Version in CI. Manche Pakete müssen der Laufzeit folgen, nicht der neuesten Version. Beispielsweise sollte@types/nodeder Node-Hauptversion entsprechen, die das Projekt verwendet. Ein Upgrade auf eine neuere Node-Hauptversion würde Code erlauben, der APIs nutzt, die in der Produktion abstürzen. Behandeln Sie „neueste“ als Kandidaten, nicht als Ziel. -
Führen Sie die Verifikationsbefehle vor Änderungen aus und notieren Sie das Ergebnis. Wenn etwas bereits fehlschlägt, müssen Sie das jetzt wissen. Andernfalls geben Sie einem Upgrade die Schuld für einen Fehler, der bereits vorhanden war, oder liefern einen roten Branch aus. Wenn die Baseline rot ist, teilen Sie dies dem Benutzer mit und fragen Sie, ob fortgefahren werden soll.
2. Inventur
Sammeln Sie zwei Listen mit den Tools des Ökosystems (siehe Referenz):
- Sicherheitslücken: das native Audit-Tool. Wenn es nicht installiert ist und nicht temporär ausgeführt werden kann, verwenden Sie den integrierten Scanner:
python3 <skill-verzeichnis>/scripts/osv_check.py <lockfile>...(fragt osv.dev ab; nur Standardbibliothek). Die Durchführung des OSV-Scans zusätzlich zum nativen Tool ist günstig und oft lohnenswert, da native Tools manchmal Hinweise in verschachtelten oder duplizierten Kopien eines Pakets übersehen. - Veraltete Pakete: aktuell → gewünscht (innerhalb des deklarierten Bereichs) → neueste.
Ermitteln Sie für jede Sicherheitslücke, welche direkte Abhängigkeit das anfällige Paket nach sich zieht und welche Version dieser direkten Abhängigkeit den Fehler behebt. Benutzer handeln bei direkten Abhängigkeiten. Ein transistiver Paketname allein ist nicht handlungsleitend.
3. Planen und melden
Sortieren Sie alles in drei Eimer und zeigen Sie den Plan als kurze Tabelle an, bevor Sie Änderungen vornehmen:
- Sicherheitsfixes: alles, was einen Hinweis entfernt. Am dringendsten. Wenn der Fix ein Major-Upgrade erfordert, ist es ein Major (Eimer 3), aber listen Sie es dort zuerst auf und sagen Sie, dass es sicherheitsgetrieben ist.
- Sichere Updates: Patch/Minor innerhalb von Semver (bei 0.x-Paketen zählt ein Minor als Breaking Change).
- Majors: alles andere, jeweils eine Zeile. Gruppieren Sie Pakete, die zusammen verschoben werden müssen (ein Framework und seine Plugins, ein Tool und seine Typdefinitionen, Pakete, die eine Peer-Abhängigkeit teilen), und behandeln Sie jede Gruppe als eine Einheit.
Die Schweregrad ist für die Reihenfolge wichtig, und die Erreichbarkeit ist für die Erklärung wichtig. Ein kritischer Hinweis in einem Dev-only-Test-Runner ist immer noch eine Reparatur wert, aber sagen Sie klar, dass es Dev-only ist, anstatt den Benutzer zu beunruhigen. Bei Nur-Prüfung-Anfragen ist dieser Bericht das Ergebnis. Fügen Sie den Schweregrad, die Hinweis-ID, den Abhängigkeitspfad und die Fixversion hinzu.
4. Branch
Erstellen Sie chore/deps-YYYY-MM-DD (heutiges Datum) vom aktualisierten Standard-Branch, es sei denn, der Benutzer befindet sich bereits auf einem für diese Arbeit erstellten Branch.
5. Sicherheitsfixes und sichere Updates
- Wenden Sie in-range-Sicherheitsfixes an, führen Sie die Verifikationsbefehle erneut aus und committen Sie.
- Wenden Sie die sicheren Patch-/Minor-Updates gemeinsam an, führen Sie die Verifikationsbefehle erneut aus und committen Sie. Wenn die Verifikation fehlschlägt, teilen Sie: machen Sie die Hälfte des Batches rückgängig und versuchen Sie es erneut, bis Sie den Übeltäter gefunden haben, ziehen Sie ihn dann heraus und behandeln Sie ihn wie einen Major.
Lassen Sie den Paketmanager das Lockfile schreiben. Bearbeiten Sie Lockfiles niemals von Hand.
6. Majors, eine Einheit nach der anderen
Führen Sie für jede Major-Einheit in dieser Reihenfolge durch (sicherheitsgetrieben zuerst, dann grundlegende Tools vor Dingen, die von ihnen abhängen, z. B. der Compiler vor dem Linter-Plugin, das auf ihm peer-t):
- Lesen Sie, was sich geändert hat. Finden Sie die Migrationsanleitung oder die Versionshinweise für jeden Major, den Sie überspringen (v2→v5 bedeutet, v3, v4 und v5 zu lesen). Gute Quellen sind die
CHANGELOG.mddes Projekts, GitHub-Releases und die „Migrations“-Seite der Dokumentationsseite. Extrahieren Sie die Breaking Changes, die dieses Codebase betreffen: grep nach den entfernten oder umbenannten APIs und Konfigurationsschlüsseln. - Überprüfen Sie Peers. Stellen Sie sicher, dass die neue Version die Peer- und Engine-Anforderungen aller Komponenten um sie herum erfüllt. Manchmal kann der neueste Major noch nicht übernommen werden, weil ein Plugin nicht mitgezogen ist. Nehmen Sie dann die neueste Version, die funktioniert, und notieren Sie, was den Rest blockiert.
- Upgraden und fixen. Aktualisieren Sie die Einheit, wenden Sie die Migration an (Konfigurationsumbenennungen, API-Änderungen, Codemods, falls das Projekt sie liefert), und führen Sie die Verifikationsbefehle erneut aus, bis sie bestehen. Fixen Sie den Code ordentlich. Schwächen Sie keine Tests, fügen Sie keine
skips hinzu und unterdrücken Sie keine Typfehler mitanyoder@ts-ignore-ähnlichen Auswegen, um grün zu werden. - Committen Sie die Einheit separat, mit den Migrationsnotizen im Body.
- Wissen, wann man aufhören muss. Wenn eine Einheit ein großes Refactoring oder eine Produktentscheidung benötigt (entfernte Funktion, geändertes Laufzeitverhalten, das Sie nicht verifizieren können), oder Sie sie nicht mit vertretbarem Aufwand grün bekommen, machen Sie sie sauber rückgängig (
git checkout -- .zurück zum letzten Commit) und notieren Sie sie als zurückgestellt, mit dem spezifischen Blocker. Ein zurückgestellter Major mit einem klaren Grund ist ein gutes Ergebnis. Ein halb fertiger Major ist es nicht.
7. Erneut verifizieren und auditieren
Führen Sie die vollständigen Verifikationsbefehle und das Audit erneut im endgültigen Zustand aus. Jeder Hinweis sollte jetzt entweder behoben oder erklärt sein. Für einen Hinweis, den Sie nicht beheben konnten:
- Wenn er transitiv ist und das Elternpaket noch keinen Fix veröffentlicht hat, ist ein Override/Resolution, das die gepatchte transitive Version festlegt, nur akzeptabel, wenn diese Version semver-kompatibel mit dem ist, was das Elternpaket erwartet. Verifizieren Sie es und notieren Sie es im PR, damit es später jemand entfernt.
- Wenn keine gepatchte Version existiert, sagen Sie das und bewerten Sie, ob der anfällige Codepfad in diesem Projekt erreichbar ist.
- Verwenden Sie niemals Ignorieren/Erlauben-Mechanismen, um das Audit stillschweigend zu bestehen.
8. Ausliefern
Commits folgen der Konvention des Repositorys. Wenn das Repository Conventional Commits verwendet und nichts Spezifischeres sagt, verwenden Sie:
fix(deps): ...für einen Sicherheitsfix für eine Laufzeitabhängigkeitbuild(deps): ...für Upgrades und für Sicherheitsfixe für Dev-only-Tools- die Zusammenfassung nennt das Paket und das Ziel, z. B.
build(deps): bump vitest to v5. Der Body listet die behobenen Hinweise und alle vorgenommenen Migrationsänderungen auf.
Pushen Sie und öffnen Sie einen PR (gh pr create), es sei denn, der Benutzer hat etwas anderes verlangt oder es gibt kein Remote. Verwenden Sie diesen Body:
## Zusammenfassung
<ein oder zwei Sätze: was sich bewegt hat, wie viele Hinweise behoben wurden>
## Sicherheit
| Hinweis | Schweregrad | Paket (Pfad) | Behoben durch |
|---|---|---|---|
## Aktualisierungen
| Paket | Von | Nach | Typ | Anmerkungen |
|---|---|---|---|---|
<Typ = Sicherheit / Patch / Minor / Major; Anmerkungen = vorgenommene Migrationsänderungen>
## Zurückgestellt
| Paket | Neueste | Warum nicht jetzt |
|---|---|---|
<blockierter Peer, erfordert Refactoring, Laufzeitbindung, ...; „keine“ wenn leer>
## Verbleibende Hinweise
<keine, oder jeder mit Grund und Erreichbarkeitsbewertung>
## Verifikation
<die genauen Befehle, die im endgültigen Commit ausgeführt wurden, und ihr Ergebnis>
Beenden Sie mit einer kurzen Chat-Zusammenfassung: den PR-Link, die Anzahl der behobenen vs. verbleibenden Hinweise und die zurückgestellten Majors mit einzeiligen Gründen.