Dependency Update Checker für Composer und npm in Bash
AI generated
$_
#!/
Bash · Composer · npm · Real World
Dependency Update Checker für Composer und npm
veraltete und unsichere Pakete automatisch erkennen

Ein Dependency Update Checker sammelt regelmäßig den Stand veralteter Pakete über mehrere Repositories hinweg und macht Sicherheitslücken sichtbar, bevor sie in einem Audit unangenehm auffallen. Dieser Artikel zeigt, wie ein solcher Dependency Update Checker composer outdated und npm outdated per jq auswertet, Versionssprünge klassifiziert und die Ergebnisse automatisch als Report verschickt.

18 Min. Lesezeit composer outdated · npm outdated · jq · Slack Webhook Bash 4.x · 5.x · Composer 2.x · npm 10.x

1. Warum ein Dependency Update Checker sich lohnt

Abhängigkeiten veralten in fast jedem Projekt schneller, als Teams es aktiv nachverfolgen. Ohne einen festen Prozess bleibt die Erkenntnis, dass ein Paket monatelang keine Sicherheitsupdates erhalten hat, oft dem Zufall überlassen, etwa wenn ein externer Pentest die Lücke findet. Ein Dependency Update Checker schließt diese Lücke, indem er regelmäßig und automatisiert prüft, welche Pakete veraltet sind und wie groß der Rückstand tatsächlich ist.

Für Projekte, die sowohl PHP mit Composer als auch JavaScript mit npm einsetzen, wie es bei Magento- oder Hyvä-basierten Shops üblich ist, deckt ein einheitlicher Dependency Update Checker beide Ökosysteme gleichzeitig ab. Statt zwei getrennte Werkzeuge zu pflegen, kombiniert ein Bash-Skript die Ausgabe von composer outdated und npm outdated zu einem gemeinsamen, konsistenten Report.

Der eigentliche Wert eines Dependency Update Checkers entsteht erst durch Automatisierung: Ein wöchentlicher Lauf, der die Ergebnisse per Slack oder E-Mail verschickt, macht veraltete Abhängigkeiten sichtbar, ohne dass jemand aktiv daran denken muss, die Prüfung manuell anzustoßen.

2. composer outdated und npm outdated als Datenquelle

Sowohl Composer als auch npm bringen eingebaute Befehle mit, die veraltete Pakete auflisten: composer outdated --format=json und npm outdated --json. Ein Dependency Update Checker nutzt diese strukturierte JSON-Ausgabe statt die menschenlesbare Tabellenform zu parsen, was deutlich robuster gegenüber Formatänderungen zwischen Versionen ist.

Wichtig ist, beide Befehle mit dem Rückgabewert-Verhalten korrekt zu behandeln: npm outdated gibt absichtlich einen Nicht-Null-Exit-Code zurück, sobald veraltete Pakete gefunden werden, was unter set -e das Skript sofort beenden würde. Ein sauberer Dependency Update Checker fängt diesen speziellen Exit-Code deshalb explizit ab, statt sich von set -e überraschen zu lassen.


#!/usr/bin/env bash
# collect-outdated.sh — gather raw outdated package data from both ecosystems
set -euo pipefail

collect_composer_outdated() {
  local project_dir="$1"
  (cd "$project_dir" && composer outdated --direct --format=json 2>/dev/null) || true
}

collect_npm_outdated() {
  local project_dir="$1"
  # npm outdated exits 1 when packages are outdated — this is expected, not a failure
  (cd "$project_dir" && npm outdated --json 2>/dev/null) || true
}

readonly PROJECT_DIR="${1:?Usage: collect-outdated.sh <project-dir>}"

collect_composer_outdated "$PROJECT_DIR" > /tmp/composer-outdated.json
collect_npm_outdated "$PROJECT_DIR" > /tmp/npm-outdated.json

echo "[OK] Raw outdated data collected for ${PROJECT_DIR}" >&2

3. JSON-Ausgabe mit jq strukturiert auslesen

Die rohe JSON-Ausgabe beider Werkzeuge hat unterschiedliche Strukturen: Composer liefert ein Objekt mit einem installed Array, npm liefert ein flaches Objekt mit dem Paketnamen als Schlüssel. Ein Dependency Update Checker normalisiert beide Formate mit jq auf eine gemeinsame, einheitliche Zeilenstruktur mit Paketname, aktueller Version und verfügbarer Version.

Diese Normalisierung ist der entscheidende Schritt, der später alle weiteren Auswertungen, von der Versionsklassifizierung bis zur Report-Generierung, unabhängig vom ursprünglichen Ökosystem macht. Der Dependency Update Checker muss ab diesem Punkt nicht mehr wissen, ob ein Paket aus Composer oder npm stammt.


#!/usr/bin/env bash
# normalize.sh — unify composer and npm outdated output into one line format
set -euo pipefail

normalize_composer() {
  jq -r '.installed[]? | [.name, .version, .latest, "composer"] | @tsv' \
    /tmp/composer-outdated.json
}

normalize_npm() {
  jq -r 'to_entries[]? | [.key, .value.current, .value.latest, "npm"] | @tsv' \
    /tmp/npm-outdated.json
}

{
  normalize_composer
  normalize_npm
} > /tmp/normalized-outdated.tsv

echo "[OK] Normalized $(wc -l < /tmp/normalized-outdated.tsv) outdated packages" >&2

4. Versionssprünge klassifizieren

Nicht jedes veraltete Paket ist gleich dringend. Ein Dependency Update Checker sollte den Versionssprung nach Semantic Versioning einordnen: Ein Patch-Update ist meist risikolos, ein Minor-Update sollte zeitnah geprüft werden, ein Major-Update erfordert oft manuelle Anpassungen und einen eigenen Testlauf. Diese Klassifizierung hilft Teams, sich zuerst auf die wirklich relevanten Änderungen zu konzentrieren, statt bei zwanzig Patch-Updates den Überblick zu verlieren.

Die Berechnung erfolgt, indem der Dependency Update Checker die erste Ziffer der aktuellen und der verfügbaren Version vergleicht. Weicht sie ab, handelt es sich um ein Major-Update. Bleibt die erste Ziffer gleich, aber die zweite weicht ab, ist es ein Minor-Update. Alles andere gilt als Patch-Update.


#!/usr/bin/env bash
# classify.sh — categorize version jumps as patch, minor, or major
set -euo pipefail

classify_bump() {
  local current="$1" latest="$2"
  local cur_major cur_minor lat_major lat_minor

  IFS='.' read -r cur_major cur_minor _ <<< "${current#v}"
  IFS='.' read -r lat_major lat_minor _ <<< "${latest#v}"

  if [[ "$cur_major" != "$lat_major" ]]; then
    echo "major"
  elif [[ "$cur_minor" != "$lat_minor" ]]; then
    echo "minor"
  else
    echo "patch"
  fi
}

while IFS=$'\t' read -r name current latest source; do
  bump="$(classify_bump "$current" "$latest")"
  printf '%s\t%s\t%s\t%s\t%s\n' "$name" "$current" "$latest" "$source" "$bump"
done < /tmp/normalized-outdated.tsv > /tmp/classified-outdated.tsv

5. Bekannte Sicherheitslücken einbeziehen

Neben reinen Versionsständen liefert ein vollständiger Dependency Update Checker auch Informationen zu bekannten Sicherheitslücken. composer audit --format=json und npm audit --json liefern jeweils eine Liste betroffener Pakete mit Schweregrad. Diese Information sollte im Report deutlich hervorgehoben werden, unabhängig davon, ob das betroffene Paket sonst als geringfügig veraltet eingestuft wurde.

Ein wichtiger Unterschied zur reinen Versionsprüfung: Ein Paket kann sicherheitskritisch sein, obwohl der Versionssprung selbst nur ein Patch-Update ist. Ein guter Dependency Update Checker behandelt Sicherheitslücken deshalb als eigene, priorisierte Kategorie, die unabhängig von der Bump-Klassifizierung immer zuerst im Report erscheint.


#!/usr/bin/env bash
# audit.sh — pull known security advisories from both ecosystems
set -euo pipefail

audit_composer() {
  local project_dir="$1"
  (cd "$project_dir" && composer audit --format=json 2>/dev/null) || true
}

audit_npm() {
  local project_dir="$1"
  (cd "$project_dir" && npm audit --json 2>/dev/null) || true
}

readonly PROJECT_DIR="${1:?Usage: audit.sh <project-dir>}"

echo "=== Composer security advisories ==="
audit_composer "$PROJECT_DIR" | jq -r '.advisories // {} | to_entries[]? | .key'

echo "=== npm security advisories ==="
audit_npm "$PROJECT_DIR" | jq -r '.vulnerabilities // {} | to_entries[]? | "\(.key): \(.value.severity)"'

6. Einen lesbaren Report generieren

Rohe TSV-Zeilen sind für den Alltag ungeeignet. Ein Dependency Update Checker sollte die klassifizierten Daten in ein lesbares Markdown-Dokument überführen, gegliedert nach Sicherheitslücken zuerst, dann Major-, Minor- und zuletzt Patch-Updates. Diese Reihenfolge spiegelt die tatsächliche Dringlichkeit wider und erspart es Lesenden, die relevanten Zeilen selbst aus einer langen Liste herauszusuchen.

Die Markdown-Ausgabe eines Dependency Update Checkers lässt sich direkt als Kommentar in ein GitLab- oder GitHub-Issue posten, was den Report sofort in den bestehenden Team-Workflow einbindet, ohne ein zusätzliches Dashboard betreiben zu müssen.


#!/usr/bin/env bash
# generate-report.sh — turn classified data into a readable markdown report
set -euo pipefail

{
  echo "# Dependency Update Report — $(date +%F)"
  echo
  for bump in major minor patch; do
    echo "## ${bump^} updates"
    echo
    echo "| Package | Current | Latest | Source |"
    echo "|---|---|---|---|"
    awk -F'\t' -v b="$bump" '$5 == b { printf "| %s | %s | %s | %s |\n", $1, $2, $3, $4 }' \
      /tmp/classified-outdated.tsv
    echo
  done
} > dependency-report.md

echo "[OK] Report written to dependency-report.md" >&2

7. Benachrichtigung per Slack Webhook

Ein Report, der nur als Datei auf der Festplatte liegt, wird selten aktiv angeschaut. Ein Dependency Update Checker gewinnt erst durch aktive Benachrichtigung an Wert, etwa über einen Slack Incoming Webhook, der eine Kurzzusammenfassung mit Anzahl der Sicherheitslücken und Major-Updates direkt in den Team-Channel postet.

Für die Nachricht selbst reicht ein einfacher curl Aufruf mit einem JSON-Payload. Wichtig ist, die Nachricht kompakt zu halten und nur auf den vollständigen Report zu verlinken, statt die gesamte Tabelle in den Chat zu quetschen, was die Übersicht eher verschlechtert als verbessert.


#!/usr/bin/env bash
# notify-slack.sh — post a compact summary to a Slack channel
set -euo pipefail

readonly WEBHOOK_URL="${SLACK_WEBHOOK_URL:?Set SLACK_WEBHOOK_URL}"

security_count="$(grep -c "CVE" dependency-report.md || true)"
major_count="$(awk -F'\t' '$5 == "major"' /tmp/classified-outdated.tsv | wc -l)"

payload=$(jq -n \
  --arg sec "$security_count" \
  --arg maj "$major_count" \
  '{ text: ("Dependency check: \($sec) security advisories, \($maj) major updates pending. See dependency-report.md for details.") }')

curl -sf -X POST -H 'Content-Type: application/json' -d "$payload" "$WEBHOOK_URL" > /dev/null
echo "[OK] Slack notification sent"

8. Automatisierung als Cronjob und CI-Job

Damit der Dependency Update Checker tatsächlich regelmäßig läuft, gehört er entweder in einen Cronjob auf dem Deployment-Server oder als geplanten Job in die CI-Pipeline. Ein wöchentlicher Lauf, etwa jeden Montagmorgen, gibt dem Team genug Vorlauf, um vor dem nächsten Release-Fenster auf kritische Updates zu reagieren.

Wichtig für den Dependency Update Checker im CI-Kontext: Der Job sollte den Build niemals fehlschlagen lassen, nur weil veraltete Pakete gefunden wurden, es sei denn, es handelt sich um eine kritische Sicherheitslücke. Die Aufgabe ist informativ, nicht blockierend, sonst verliert das Team schnell die Geduld mit ständig roten Pipelines wegen unkritischer Patch-Updates.

9. Dependency Update Checker im Vergleich

Es gibt SaaS-Lösungen wie Dependabot oder Renovate, die ähnliche Aufgaben automatisiert und sogar mit automatischen Pull Requests lösen. Ein selbst gebauter Dependency Update Checker in Bash bietet dagegen volle Kontrolle über Format, Kanal und Kriterien, ohne Abhängigkeit von einem externen Dienst oder dessen Rate Limits.

Ansatz Automatische PRs Kontrolle über Format Geeignet für
Bash Dependency Update Checker Nein, nur Reporting Vollständig Interne Reports, Slack-Integration
Dependabot Ja, automatisch Begrenzt konfigurierbar GitHub-native Projekte
Renovate Ja, automatisch Umfangreich konfigurierbar Große Monorepos, viele Ökosysteme
Manuelle Prüfung Nein Keine Struktur Sehr kleine Projekte

Für Teams, die selbst entscheiden möchten, wann und wie ein Update eingespielt wird, ist ein Dependency Update Checker ohne automatische PRs oft die bewusstere Wahl, gerade in sensiblen Produktionsumgebungen wie Magento-Shops mit vielen kundenspezifischen Erweiterungen.

Mironsoft

Shell-Automatisierung, Abhängigkeitsmanagement und Sicherheits-Tooling

Ein Dependency Update Checker für eure Projekte?

Wir bauen einen maßgeschneiderten Dependency Update Checker für Composer und npm, mit Sicherheits-Audit, Klassifizierung und automatischer Slack-Benachrichtigung.

Skript-Entwicklung

Individueller Dependency Update Checker für euren Stack

Sicherheits-Audit

Bekannte Sicherheitslücken in Composer- und npm-Paketen erkennen

Reporting

Wöchentliche Berichte mit Slack- oder E-Mail-Anbindung

10. Zusammenfassung

Ein Dependency Update Checker in Bash kombiniert die eingebauten Befehle composer outdated und npm outdated zu einer einheitlichen, priorisierten Übersicht über veraltete Pakete. Klassifizierung nach Semantic Versioning und die Einbeziehung von Sicherheits-Audits sorgen dafür, dass die wirklich dringenden Fälle nicht in einer langen Liste untergehen.

Der entscheidende Hebel liegt in der Automatisierung: Ein Dependency Update Checker, der wöchentlich läuft und Ergebnisse aktiv per Slack meldet, verhindert, dass veraltete Abhängigkeiten monatelang unbemerkt bleiben. Für Teams mit mehreren PHP- und JavaScript-Projekten reduziert das den manuellen Prüfaufwand erheblich, ohne die Kontrolle über den Update-Zeitpunkt an eine externe SaaS-Lösung abzugeben.

Dependency Update Checker in Bash — Das Wichtigste auf einen Blick

Datenquelle

composer outdated --format=json und npm outdated --json als strukturierte Basis.

Normalisierung

jq vereinheitlicht beide Formate zu einer gemeinsamen Zeilenstruktur, unabhängig vom Ökosystem.

Priorisierung

Sicherheitslücken zuerst, danach Major, Minor und Patch, jeweils klassifiziert nach Semantic Versioning.

Benachrichtigung

Kompakte Slack-Nachricht mit Link zum vollständigen Markdown-Report, wöchentlich per Cron oder CI.

11. FAQ: Dependency Update Checker für Composer und npm

1Was ist ein Dependency Update Checker?
Ein Skript, das veraltete und unsichere Abhängigkeiten erkennt, klassifiziert und als Report zusammenfasst.
2Warum JSON statt Tabellenform?
JSON bleibt über Versionen hinweg strukturell stabiler als die menschenlesbare Ausgabe.
3Warum meldet npm outdated einen Fehler?
Absichtliches Verhalten bei gefundenen veralteten Paketen, muss im Skript explizit abgefangen werden.
4Wie werden beide Formate zusammengeführt?
Über jq, das beide JSON-Strukturen auf eine gemeinsame Zeilenstruktur normalisiert.
5Wie werden Versionssprünge klassifiziert?
Nach Semantic Versioning in Major, Minor und Patch anhand der abweichenden Versionsziffer.
6Wie fließen Sicherheitslücken ein?
Über composer audit und npm audit, immer priorisiert vor der reinen Versionsklassifizierung.
7Soll der CI-Build fehlschlagen?
Nur bei kritischen Lücken, ansonsten bleibt die Prüfung rein informativ.
8Wie erfährt das Team vom Ergebnis?
Über eine kompakte Slack-Nachricht mit Link zum vollständigen Report.
9Wie oft sollte er laufen?
Wöchentlich, um genug Vorlauf vor dem nächsten Release-Fenster zu geben.
10Besser als Dependabot?
Nicht grundsätzlich, aber mit voller Kontrolle über Format und Benachrichtigung ohne externen Dienst.