Dependency Update Bot – Lokalisierte Version (DE)
Durchsucht Ihr Projekt nach veralteten Paketen. Führt ein Sicherheitsaudit durch. Ruft Changelogs ab. Fasst Breaking Changes zusammen. Erstellt einen PR pro Risikogruppe.
Wichtige Regel: Aktualisieren Sie nur Pakete, die der Befehl outdated des Paketmanagers tatsächlich meldet. Raten Sie niemals Versionsnummern oder erfinden Sie sie. Wenn ein Changelog nicht abgerufen werden kann, notieren Sie die Lücke, anstatt Inhalt zu erfinden.
Schritt 1: Überprüfung der Einrichtung
echo "GEMINI_API_KEY: ${GEMINI_API_KEY:+gesetzt}"
echo "GITHUB_TOKEN: ${GITHUB_TOKEN:-nicht gesetzt, Changelog-Abruf auf 60/Std. ratenbegrenzt}"
gh auth status 2>/dev/null | head -1 || echo "gh: nicht authentifiziert"
Wenn GEMINI_API_KEY fehlt: Anhalten. Dem Benutzer mitteilen: „GEMINI_API_KEY ist erforderlich. Holen Sie ihn unter aistudio.google.com ab. Fügen Sie ihn Ihrer .env-Datei hinzu.“
Wenn gh nicht authentifiziert ist: Anhalten. Dem Benutzer mitteilen: „GitHub CLI muss authentifiziert sein. Führen Sie aus: gh auth login“
Paketmanager erkennen:
ls package.json 2>/dev/null && echo "npm"
ls requirements.txt pyproject.toml 2>/dev/null && echo "pip"
ls Cargo.toml 2>/dev/null && echo "cargo"
ls go.mod 2>/dev/null && echo "go"
ls Gemfile 2>/dev/null && echo "ruby"
Wenn mehrere gefunden werden, fragen: „Gefunden: [Liste]. Welche soll ich scannen? (all / npm / pip / cargo / go / ruby)“
Schritt 2: Veraltete Pakete erkennen
npm:
npm outdated --json --long 2>/dev/null | python3 -c "
import sys, json
data = json.load(sys.stdin)
for name, info in data.items():
print(json.dumps({'name': name, 'current': info.get('current','?'), 'latest': info.get('latest','?'), 'dep_type': info.get('type','dependencies')}))
"
pip:
pip list --outdated --format=json 2>/dev/null | python3 -c "
import sys, json
for p in json.load(sys.stdin):
print(json.dumps({'name': p['name'], 'current': p['version'], 'latest': p['latest_version']}))
"
Cargo (Rust):
cargo outdated --format json 2>/dev/null || \
cargo outdated 2>/dev/null | grep -v "^---" | tail -n +3 | head -30
# Falls cargo-outdated nicht installiert: cargo install cargo-outdated
Go-Module:
go list -u -m -json all 2>/dev/null | python3 -c "
import sys, json
decoder = json.JSONDecoder()
buf = sys.stdin.read()
pos = 0
while pos < len(buf):
try:
obj, idx = decoder.raw_decode(buf, pos)
if obj.get('Update'):
print(json.dumps({'name': obj['Path'], 'current': obj['Version'], 'latest': obj['Update']['Version']}))
pos += idx
except: break
"
Ruby (Bundler):
bundle outdated --parseable 2>/dev/null | python3 -c "
import sys
for line in sys.stdin:
parts = line.strip().split()
if len(parts) >= 4:
print('{\"name\":\"' + parts[0] + '\",\"current\":\"' + parts[3].strip('()') + '\",\"latest\":\"' + parts[1] + '\"}')
"
Wenn alle leer zurückkommen: „Alle Pakete sind auf dem neuesten Stand.“ Anhalten.
Vor dem Fortfahren die Anzahl angeben: „Gefunden: X veraltete Pakete.“
Schritt 3: Nach Risikostufe klassifizieren
Versionssprung parsen (aktuell → neueste):
- MAJOR: erste Ziffer geändert (1.x.x → 2.x.x)
- MINOR: zweite Ziffer geändert (1.2.x → 1.3.x)
- PATCH: dritte Ziffer geändert (1.2.3 → 1.2.4)
python3 -c "
def classify(current, latest):
try:
c = [int(x) for x in current.lstrip('v').split('.')[:3]]
l = [int(x) for x in latest.lstrip('v').split('.')[:3]]
if l[0] > c[0]: return 'major'
if len(l) > 1 and len(c) > 1 and l[1] > c[1]: return 'minor'
return 'patch'
except: return 'unknown'
"
Die Aufschlüsselung angeben: „Patch: X Pakete. Minor: Y Pakete. Major: Z Pakete.“
Schritt 4: Sicherheitsaudit
Führen Sie vor dem Erstellen von PRs einen CVE-Scan durch. Dies bestimmt die Dringlichkeit.
npm:
npm audit --json 2>/dev/null | python3 -c "
import sys, json
d = json.load(sys.stdin)
vulns = d.get('vulnerabilities', {})
for pkg, info in vulns.items():
sev = info.get('severity', 'unknown')
via = [v.get('title','') for v in info.get('via',[]) if isinstance(v, dict)]
print(f' [{sev.upper()}] {pkg}: {via[0] if via else \"siehe npm audit\"}')
" 2>/dev/null || echo "Keine Schwachstellen gefunden oder npm audit nicht verfügbar"
pip:
pip-audit --format=json 2>/dev/null | python3 -c "
import sys, json
for vuln in json.load(sys.stdin):
print(f' [{vuln.get(\"aliases\",[\"\"])[0]}] {vuln[\"name\"]} {vuln[\"version\"]}: {vuln[\"description\"][:80]}')
" 2>/dev/null || echo "pip-audit nicht installiert. Führen Sie aus: pip install pip-audit"
Cargo:
cargo audit 2>/dev/null | grep -E "^(ID|Package|Severity|URL)" | head -30 \
|| echo "cargo-audit nicht installiert. Führen Sie aus: cargo install cargo-audit"
Eskalationsregel: Wenn ein PATCH- oder MINOR-Update ein kritisches oder hohes CVE aufweist, wird es auf MAJOR-Priorität hochgestuft: Es erhält einen eigenen PR und die CVE-Details werden in den PR-Text aufgenommen.
Sicherheitsergebnisse vor dem Fortfahren melden:
Sicherheitsaudit: [N] Schwachstellen gefunden
[KRITISCH] lodash 4.17.19: Prototype Pollution (CVE-2021-23337)
[HOCH] axios 0.21.1: Server-Side Request Forgery (CVE-2021-3749)
Wenn keine Schwachstellen: „Sicherheitsaudit: sauber.“
Schritt 5: Changelogs abrufen
Für jedes Paket nacheinander Quellen versuchen. Bei der ersten, die Inhalt zurückgibt, anhalten.
Quelle 1: GitHub Releases API
Repo-URL aus der Registrierung abrufen:
# npm
curl -s "https://registry.npmjs.org/{PACKAGE}/latest" \
| python3 -c "import sys,json; d=json.load(sys.stdin); r=d.get('repository',{}); print(r.get('url','') if isinstance(r,dict) else str(r))"
# pip
curl -s "https://pypi.org/pypi/{PACKAGE}/json" \
| python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('info',{}).get('home_page','') or d.get('info',{}).get('project_urls',{}).get('Source',''))"
Die letzten 5 Releases abrufen:
AUTH_HEADER=""
[ -n "$GITHUB_TOKEN" ] && AUTH_HEADER="-H \"Authorization: Bearer $GITHUB_TOKEN\""
curl -s $AUTH_HEADER \
"https://api.github.com/repos/{OWNER}/{REPO}/releases?per_page=5" \
| python3 -c "import sys,json; [print(json.dumps({'tag':r.get('tag_name',''),'body':r.get('body','')[:1500]})) for r in json.load(sys.stdin)]"
Nur Releases zwischen der aktuellen und der neuesten Version behalten.
Quelle 2: npm-Registry README (Fallback)
curl -s "https://registry.npmjs.org/{PACKAGE}" \
| python3 -c "import sys,json; print(json.load(sys.stdin).get('readme','')[:3000])"
Quelle 3: PyPI-Beschreibung (letzter Ausweg für pip)
curl -s "https://pypi.org/pypi/{PACKAGE}/json" \
| python3 -c "import sys,json; print(json.load(sys.stdin).get('info',{}).get('description','')[:2000])"
Wenn keine Quelle Inhalt zurückgibt: „Kein Changelog gefunden“ notieren und fortfahren.
Schritt 6: Zusammenfassung mit Gemini
Eine Anfrage pro Risikogruppe. Sicherheitsergebnisse für alle von CVE betroffenen Pakete einbeziehen:
cat > /tmp/deps-summary-request.json << 'ENDJSON'
{
"system_instruction": {
"parts": [{
"text": "You are a developer writing a GitHub PR description for a dependency update. Given a list of packages being updated and their raw changelog content, write a concise PR body in Markdown. Rules: For each package, list only what changed between the OLD version and the NEW version. Use bullet points. Flag breaking changes with a BREAKING prefix. Flag CVE fixes with a SECURITY prefix and include the CVE ID. Keep each package section to 3-5 bullets maximum. If no changelog was found for a package, write 'No changelog available.' Do not use em dashes. Do not use these words: seamless, robust, leverage, transform, innovative. Output only the Markdown PR body, no commentary."
}]
},
"contents": [{
"parts": [{
"text": "PACKAGES_AND_CHANGELOGS_HERE"
}]
}],
"generationConfig": {
"temperature": 0.2,
"maxOutputTokens": 2048
}
}
ENDJSON
curl -s -X POST \
"https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=$GEMINI_API_KEY" \
-H "Content-Type: application/json" \
-d @/tmp/deps-summary-request.json \
| python3 -c "import sys,json; d=json.load(sys.stdin); print(d['candidates'][0]['content']['parts'][0]['text'])"
Schritt 7: PRs erstellen
Ein PR pro nicht leerer Risikogruppe. Ein PR pro Paket für Major-Updates (einzelne Überprüfung erforderlich).
1. Branch erstellen:
BRANCH="deps/{RISK}-updates-$(date +%Y%m%d)"
git checkout -b "$BRANCH"
2. Paketdatei aktualisieren:
npm:
npm install {package}@{latest_version} --save-exact
# devDependencies:
npm install {package}@{latest_version} --save-dev --save-exact
pip:
python3 -c "
import re, sys
pkg, version, filename = sys.argv[1], sys.argv[2], sys.argv[3]
with open(filename) as f: content = f.read()
pattern = rf'^{re.escape(pkg)}[>=<!\s].*$'
new_content = re.sub(pattern, f'{pkg}=={version}', content, flags=re.MULTILINE|re.IGNORECASE)
if new_content == content: new_content = content + f'\n{pkg}=={version}'
open(filename, 'w').write(new_content)
" "{PACKAGE}" "{LATEST}" "requirements.txt"
Cargo:
# Cargo.toml-Versionsfeld für das Paket bearbeiten, dann:
cargo update {package}
Go:
go get {module}@{latest_version}
go mod tidy
Ruby:
bundle update {gem_name}
3. Committen:
git add -A
git commit -m "chore(deps): update {RISK} dependencies $(date +%Y-%m-%d)"
4. PR erstellen:
cat > /tmp/dep-pr-body-{RISK}.md << 'ENDMD'
PR_BODY_FROM_GEMINI
ENDMD
gh pr create \
--title "chore(deps): update {RISK} dependencies" \
--body-file /tmp/dep-pr-body-{RISK}.md \
--label "dependencies" \
--base main
Major-Updates erhalten das Label dependencies,breaking-change. CVE-behebende Updates erhalten das Label dependencies,security.
Nach jedem PR zu main zurückkehren: git checkout main
Schritt 8: Diagnosemodus
Auslöser: Wenn ein Paketinstallationsbefehl während der Ausführung fehlschlägt, den Diagnosemodus starten, anstatt anzuhalten.
Den Fehlertyp erkennen:
| Fehlermuster | Wahrscheinliche Ursache | Vorgeschlagene Lösung |
|---|---|---|
peer dep conflict | Inkompatibilität der Peer-Abhängigkeiten | Konfliktpaar anzeigen, --legacy-peer-deps-Flag oder Downgrade vorschlagen |
ERESOLVE | npm-Auflösungskonflikt | npm install --legacy-peer-deps nur für das betroffene Paket ausführen |
version not found | Version existiert nicht in der Registrierung | Registrierung mit npm view {pkg} versions überprüfen |
python requires | Python-Versionsinkompatibilität | Erforderliche Python-Version notieren, Paket überspringen |
cargo E0463 | Rust-Edition-Inkompatibilität | Zur manuellen Überprüfung kennzeichnen |
Eine Diagnosezusammenfassung anzeigen:
Installation fehlgeschlagen für {package}: {Fehlertyp}
Wahrscheinliche Ursache: {Erklärung}
Vorgeschlagene Lösung: {spezifischer Befehl oder Aktion}
Verbleibende Pakete: Fortfahren mit {N} erfolgreichen Paketen.
Den gesamten Durchlauf nicht anhalten, wenn ein Paket fehlschlägt. Mit den erfolgreichen Paketen fortfahren.
Schritt 9: Ausgabeübersicht
## Dependency Update Zusammenfassung: [YYYY-MM-DD]
### Sicherheit
[KRITISCH] lodash: CVE-2021-23337 behoben in 4.17.21: PR #42
[HOCH] axios: CVE-2021-3749 behoben in 0.21.4: PR #42
| Risikostufe | Pakete | PR |
|-------------|--------|-----|
| Patch | lodash 4.17.19→4.17.21, axios 0.21.1→0.21.4 | #42 |
| Minor | express 4.17.1→4.18.2 | #43 |
| Major | react 17.0.2→18.2.0 | #44 |
PRs erstellt: 3
Pakete ohne Changelog: some-obscure-pkg (kein GitHub-Repo in der Registrierung)
Installationsfehler: keine
Nächste Aktion: Major-Update-PRs vor dem Mergen einzeln überprüfen.