Modul-Versionierung nach SemVer in Magento 2
AI generated
M2
di.xml
Magento 2 · SemVer · Composer · Release-Management
Modul-Versionierung nach SemVer
Breaking Changes richtig kommunizieren

Eine hochgezählte Versionsnummer ohne erkennbares Muster ist für andere Entwickler wertlos, weil niemand mehr weiß, ob ein Update gefahrlos eingespielt werden kann. SemVer macht aus einer Zahl ein Versprechen: MAJOR, MINOR und PATCH sagen Consumern eines Magento-Moduls präzise, was sich geändert hat, bevor sie auch nur einen Blick in den Code werfen müssen.

15 Min. Lesezeit module.xml · composer.json · Changelog Magento 2.4.8 · PHP 8.4

1. Warum SemVer für eigene Magento-Module zählt

SemVer, Semantic Versioning, ist ein einfaches Versprechen mit drei Zahlen: MAJOR.MINOR.PATCH. Für ein eigenes Magento-2-Modul, das in mehreren Kundenprojekten eingesetzt wird, ist diese Modul-Versionierung kein akademisches Detail, sondern die einzige verlässliche Kommunikationsschnittstelle zwischen dem Modulautor und den Teams, die es einbinden. Ohne SemVer bleibt nur die Option, jedes Update manuell zu prüfen, was bei mehreren Projekten und mehreren Modulen schnell unpraktikabel wird.

In der Praxis zeigt sich der Wert besonders bei Agenturen, die dasselbe Modul in zehn oder mehr Shops pflegen. Ein Composer-Update, das versehentlich eine Breaking Change als PATCH-Release ausliefert, kann an einem Freitagnachmittag mehrere Live-Shops gleichzeitig brechen. Konsequente SemVer-Versionierung reduziert dieses Risiko drastisch, weil Consumer über Versionsconstraints entscheiden können, wie viel Risiko sie bei einem Update eingehen wollen.

Das gilt umso mehr, je automatisierter der eigene Deployment-Prozess ist. Wenn Composer-Updates über CI-Pipelines ohne manuellen Zwischenschritt eingespielt werden, ist eine verlässliche SemVer-Versionierung keine Komfortfunktion mehr, sondern eine harte Voraussetzung dafür, dass Automatisierung überhaupt sicher betrieben werden kann.

Wichtig ist die Abgrenzung zu Magentos eigener Modulversionierung im Core: Adobe folgt für Core-Module einer eigenen, an Magento-Releases gekoppelten Logik. Für eigene Module, die unabhängig von Magento-Hauptversionen releast werden, gilt reines SemVer nach den offiziellen Regeln von semver.org, unabhängig davon, wie Magento intern versioniert.

Dieser Unterschied ist besonders relevant, wenn ein eigenes Modul von einer bestimmten Magento-Version abhängt. Die eigene Modul-Versionierung und die Magento-Kompatibilität sind zwei getrennte Achsen: eine neue MINOR-Version des eigenen Moduls kann zusätzliche Magento-Kompatibilität mitbringen, ohne dass sich an der öffentlichen Schnittstelle des Moduls selbst etwas ändert.

Ein weiterer Vorteil, der oft übersehen wird, ist die Rolle von SemVer bei der Onboarding-Geschwindigkeit neuer Teammitglieder. Wer eine unbekannte Modulversion in einem Projekt vorfindet, kann allein anhand der Versionsnummer sofort einschätzen, wie riskant ein Update wäre, ohne erst den kompletten Änderungsverlauf lesen zu müssen. Diese Vorhersagbarkeit ist ein unterschätzter Produktivitätsgewinn in jedem Team, das mehr als ein oder zwei Personen umfasst.

2. Die drei Zahlen: MAJOR, MINOR, PATCH richtig lesen

Bei SemVer hat jede der drei Zahlen eine feste Bedeutung, die nicht verhandelbar ist. PATCH (die dritte Zahl) steht für rückwärtskompatible Bugfixes, ohne neue Funktionalität. MINOR (die zweite Zahl) steht für neue, rückwärtskompatible Funktionalität, etwa eine zusätzliche optionale Methode in einem Service Contract. MAJOR (die erste Zahl) steht für inkompatible Änderungen, die bestehenden Code brechen können, etwa eine geänderte Methodensignatur oder ein entferntes Interface.

Der häufigste Fehler bei der Modul-Versionierung ist, MINOR-Releases für Änderungen zu verwenden, die eigentlich MAJOR sein müssten, weil ein Entwickler die Auswirkung einer Änderung unterschätzt. Ein zusätzlicher Pflichtparameter in einer öffentlichen Methode wirkt intern klein, ist aber für jeden Consumer, der diese Methode aufruft, ein Breaking Change und gehört zwingend in ein MAJOR-Release.

Der umgekehrte Fehler, ein zu vorsichtiges MAJOR-Release für eine eigentlich harmlose Erweiterung, kommt seltener vor, verursacht aber unnötige Reibung: Consumer-Teams zögern MAJOR-Updates aus Gewohnheit eher hinaus, selbst wenn der tatsächliche Migrationsaufwand gering wäre. Eine ehrliche Einschätzung der Versionsstufe spart deshalb auf beiden Seiten Zeit.

Eine hilfreiche Faustregel: Bei Unsicherheit lieber eine Versionsstufe höher gehen als zu niedrig. Ein unnötiges MAJOR-Release kostet Consumer nur eine bewusste Update-Entscheidung. Ein fälschlich als MINOR oder PATCH deklarierter Breaking Change kostet im schlimmsten Fall einen kaputten Live-Shop, weil das Composer-Update automatisiert und ungeprüft eingespielt wurde.

Ein Sonderfall ist Version 0.x.y, die SemVer als initiale Entwicklungsphase definiert, in der sich auch MINOR-Releases inkompatibel verhalten dürfen. Für produktiv eingesetzte Magento-Module ist diese Phase nur in der allerersten internen Erprobung sinnvoll. Sobald ein Modul in einem echten Kundenprojekt läuft, sollte die erste stabile Version 1.0.0 vergeben werden, damit ab diesem Zeitpunkt die vollen SemVer-Garantien greifen.

Auch Pre-Release-Kennzeichnungen wie 2.4.0-beta.1 oder 2.4.0-rc.2 sind Teil des SemVer-Standards und eignen sich gut, um neue Funktionen vor dem eigentlichen Release in ausgewählten Projekten zu erproben. Composer behandelt solche Pre-Release-Versionen standardmäßig als instabil und löst sie nur auf, wenn ein Consumer sie explizit über minimum-stability zulässt, was ungewollte Auto-Updates auf unfertige Versionen zuverlässig verhindert.

3. module.xml setup_version und composer.json Version

In Magento 2 existieren zwei unabhängige Versionsbegriffe, die häufig verwechselt werden. Die setup_version in module.xml steuert ausschließlich, ob Magentos Setup-Mechanismus Schema- und Data-Patches erneut ausführt, wenn sich die Version erhöht. Sie hat mit SemVer als externem Versionsversprechen nichts zu tun und muss nicht denselben Regeln folgen, auch wenn es sinnvoll ist, sie synchron zur Composer-Version zu halten.

Die Version in composer.json wiederum ist bei modernen Composer-Paketen meist gar nicht als statisches Feld vorhanden, sondern wird von Composer aus dem Git-Tag abgeleitet, wenn das Paket über ein VCS-Repository eingebunden wird. Das bedeutet: die eigentliche SemVer-Versionsnummer eines Moduls lebt praktisch im Git-Tag, nicht in einer Textzeile in composer.json.

Wird ein statisches version-Feld dennoch in composer.json gepflegt, etwa bei Paketen, die über einen privaten Satis-Server ausgeliefert werden, muss dieses Feld bei jedem Release manuell synchron zum Git-Tag gehalten werden. Ein Auseinanderdriften der beiden Werte ist eine häufige, aber leicht vermeidbare Fehlerquelle, die sich mit einem einfachen CI-Check vor jedem Release zuverlässig verhindern lässt.


<!-- app/code/Mironsoft/LoyaltyPoints/etc/module.xml -->
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
    <module name="Mironsoft_LoyaltyPoints" setup_version="2.3.0">
        <sequence>
            <module name="Magento_Sales"/>
            <module name="Magento_Customer"/>
        </sequence>
    </module>
</config>

Praktisch bedeutet das: bei jedem Data- oder Schema-Patch muss setup_version erhöht werden, damit bin/magento setup:upgrade den Patch erkennt und ausführt. Der Composer-Tag hingegen wird unabhängig davon gesetzt, sobald ein Release fertig ist. Beide Werte synchron zu halten ist keine Magento-Anforderung, aber gute Praxis, weil es Verwirrung im Team vermeidet, wenn "Version 2.3.0" an zwei Stellen unterschiedlich aussieht.

Ein häufiger Anfängerfehler ist, setup_version bei einer reinen Code-Änderung ohne Schema- oder Data-Patch trotzdem zu erhöhen, in der Annahme, das entspreche der neuen Composer-Version. Das ist unschädlich, aber unnötig: setup_version muss ausschließlich dann steigen, wenn tatsächlich ein neuer Patch in Setup/Patch/Schema oder Setup/Patch/Data hinzukommt, den Magento beim nächsten setup:upgrade ausführen soll.

4. Wann ist eine Änderung ein Breaking Change?

Die schwierigste Entscheidung in der Modul-Versionierung ist die korrekte Klassifizierung einer Änderung. Ein Breaking Change liegt immer dann vor, wenn bestehender Consumer-Code, der gegen die alte Version geschrieben wurde, nach dem Update nicht mehr fehlerfrei kompiliert oder sich zur Laufzeit anders verhält als vorher dokumentiert. Das betrifft öffentliche Klassen, Interfaces, deren Methodensignaturen, Konstruktor-Parameter bei per Dependency Injection instanziierten Klassen und veröffentlichte Events.

Nicht jede Änderung an einer Klasse ist automatisch breaking. Eine als private markierte Methode zu ändern, betrifft keinen externen Consumer. Eine neue, optionale Methode zu einem Interface hinzuzufügen, ist streng genommen ebenfalls breaking, weil jede existierende Implementierung des Interfaces plötzlich unvollständig ist, sofern PHP keine Default-Implementierung für Interface-Methoden erlaubt. Genau solche Grenzfälle sind es, die eine bewusste Breaking-Change-Analyse vor jedem Release nötig machen, statt sich auf Bauchgefühl zu verlassen.

Auch Änderungen am Verhalten ohne Änderung der Signatur zählen zur Modul-Versionierung-Analyse. Wenn eine Methode bisher null zurückgab und künftig eine leere Collection zurückgibt, kompiliert bestehender Code zwar weiterhin, verhält sich aber möglicherweise anders, etwa wenn ein Consumer explizit auf null statt auf Leere prüft. Solche semantischen Breaking Changes sind schwerer zu erkennen als reine Signaturänderungen und verdienen deshalb besondere Aufmerksamkeit im Review.


<?php
declare(strict_types=1);

namespace Mironsoft\LoyaltyPoints\Api;

/**
 * Version 2.x - non-breaking: adding an optional parameter with a default value
 * keeps existing callers compiling and behaving the same way.
 */
interface PointsCalculatorInterface
{
    public function calculate(float $orderTotal, int $customerId, bool $includeBonus = false): int;
}

/**
 * Version 3.0 - BREAKING: removing a parameter or changing its type
 * forces every implementation and every caller to be updated. This
 * requires a MAJOR version bump, never MINOR or PATCH.
 */
interface PointsCalculatorInterfaceV3
{
    public function calculate(float $orderTotal, string $customerId): int;
}

5. Versionsnummer erhöhen: der Release-Workflow

Ein reproduzierbarer Release-Prozess ist die Grundlage jeder verlässlichen SemVer-Praxis. Der Ablauf beginnt mit einer bewussten Entscheidung über die Versionsstufe, gefolgt von der Aktualisierung des Changelogs, dem Setzen des Git-Tags und dem Push in das private Repository, aus dem Composer das Paket auflöst. Ohne diese Reihenfolge entstehen Releases, bei denen der Code bereits im Hauptbranch liegt, aber kein Tag existiert, was zu inkonsistenten Composer-Auflösungen führt.

Besonders wichtig ist, den Tag erst zu setzen, wenn der Code tatsächlich release-fertig ist, inklusive aktualisiertem Changelog. Ein nachträglich verschobener Tag zerstört das Vertrauen in die Modul-Versionierung, weil Composer den Inhalt einer bereits aufgelösten Version zwischenspeichert und ein verschobener Tag zu widersprüchlichem Verhalten zwischen verschiedenen Projekten führen kann, die zu unterschiedlichen Zeitpunkten installiert haben.

Ein zusätzlicher Sicherheitsschritt ist ein automatisierter CI-Job, der bei jedem Tag-Push prüft, ob das Changelog tatsächlich einen Eintrag für die neue Version enthält, und den Release andernfalls blockiert. Diese kleine Automatisierung verhindert zuverlässig den häufigen menschlichen Fehler, einen Tag zu setzen und das Changelog-Update im Trubel des Releases zu vergessen.


#!/usr/bin/env bash
set -euo pipefail

# 1. Update CHANGELOG.md with the new version block before tagging
# 2. Commit the changelog and any final release adjustments
git add CHANGELOG.md
git commit -m "Release v2.3.0"

# 3. Create an annotated tag matching SemVer exactly (leading "v" is a common convention)
git tag -a v2.3.0 -m "v2.3.0: add optional bonus points calculation"

# 4. Push commit and tag together
git push origin main
git push origin v2.3.0

# 5. Verify the tag is resolvable by Composer against the private repository
bin/cli composer show mironsoft/loyalty-points --all | grep "2.3.0"

6. Versionsbeschränkungen in composer.json

Consumer eines Moduls steuern ihr Update-Risiko über Versionsconstraints in ihrer eigenen composer.json. Der Constraint ^2.3 erlaubt alle Versionen ab 2.3.0 bis ausschließlich 3.0.0, folgt also exakt dem SemVer-Versprechen: MINOR- und PATCH-Updates werden automatisch akzeptiert, MAJOR-Updates nicht. Der Constraint ~2.3.0 ist enger und erlaubt nur PATCH-Updates innerhalb von 2.3.x. Eine exakte Version wie 2.3.0 ohne Operator erlaubt gar keine automatischen Updates.

Die Wahl des richtigen Constraints hängt vom Vertrauen in die Modul-Versionierung des jeweiligen Anbieters ab. Für gut gepflegte, diszipliniert versionierte Module ist ^2.3 die richtige Wahl, weil es Sicherheitsupdates automatisch durchlässt, ohne Breaking Changes zu riskieren. Bei Modulen mit unklarer Versionierungshistorie ist die engere ~2.3.0-Bindung oder sogar eine exakte Version die sicherere Wahl, bis Vertrauen in die Release-Disziplin aufgebaut wurde.

Regelmäßige composer outdated-Läufe machen sichtbar, welche Constraints in der Praxis welche Updates zulassen, bevor ein Sicherheitsupdate überhaupt verfügbar ist. Ergänzt um automatisierte Dependabot- oder Renovate-Pull-Requests lässt sich diese Prüfung sogar vollständig automatisieren, sodass MINOR- und PATCH-Updates ohne manuellen Aufwand regelmäßig vorgeschlagen werden, während MAJOR-Updates bewusst als eigener Planungspunkt sichtbar bleiben.

Für Module, die über einen privaten Composer-Server verteilt werden, lohnt sich zusätzlich ein zentrales Dashboard, das für alle Consumer-Projekte anzeigt, welche Version eines Moduls aktuell im Einsatz ist. So wird auf einen Blick sichtbar, welche Projekte auf veralteten Versionen mit möglichen Sicherheitslücken laufen und aktiv zum Update angestoßen werden sollten.


{
  "require": {
    "mironsoft/loyalty-points": "^2.3",
    "mironsoft/gift-cards": "~1.4.0",
    "mironsoft/legacy-import": "1.0.2"
  },
  "repositories": [
    { "type": "composer", "url": "https://satis.mironsoft.de" }
  ]
}

7. Breaking Changes kommunizieren: Changelog und Deprecation

Eine korrekte Versionsnummer allein reicht nicht, wenn niemand nachlesen kann, was sich konkret geändert hat. Ein gepflegtes CHANGELOG.md nach dem Keep-a-Changelog-Format dokumentiert für jede Version die Kategorien Added, Changed, Deprecated, Removed und Fixed. Für Modul-Versionierung ist besonders die Kategorie Breaking wichtig, oft als eigener, hervorgehobener Abschnitt direkt unter der neuen MAJOR-Version, mit konkreten Migrationsschritten für Consumer.

Vor einer entfernenden MAJOR-Änderung ist eine Deprecation-Phase in der vorherigen MINOR-Version die fairere Praxis. Eine Methode wird mit @deprecated markiert, weiterhin funktionsfähig gehalten, und erst im nächsten MAJOR-Release tatsächlich entfernt. Das gibt Consumern Zeit, ihren Code anzupassen, bevor ein Update erzwungen wird, und ist der entscheidende Unterschied zwischen einer respektvollen und einer überraschenden Breaking Change.

Gute Praxis ist außerdem, im Changelog auf konkrete Zeilen im Migrationsleitfaden zu verweisen, statt nur "Breaking Changes, siehe Code" zu schreiben. Wer als Modulanbieter Vertrauen aufbauen will, investiert in diese Kommunikation genauso viel wie in den eigentlichen Code, weil SemVer ohne verständliche Begleitinformation nur die halbe Sicherheit bietet.

Ein oft unterschätztes Mittel ist ein automatisiertes Upgrade-Skript, das gemeinsam mit einer MAJOR-Version veröffentlicht wird und einfache Migrationsschritte, etwa das Umbenennen von Konfigurationsschlüsseln, automatisch übernimmt. Für Consumer, die zehn oder mehr Shops mit demselben Modul betreiben, reduziert ein solches Skript den Migrationsaufwand erheblich und macht auch größere Breaking Changes praktisch handhabbar.

8. SemVer zwischen mehreren eigenen Modulen

Sobald mehrere eigene Module voneinander abhängen, etwa ein Loyalty-Modul, das auf ein gemeinsames Core-Modul aufsetzt, wird SemVer zur Grundlage für stabile Abhängigkeitsketten. Jedes abhängige Modul deklariert in seiner composer.json einen Constraint gegen die benötigte Version des Core-Moduls, und ein MAJOR-Release des Core-Moduls muss bewusst durch die gesamte Modulkette hindurch nachgezogen werden, statt stillschweigend zu brechen.

Ein häufiges Problem in Multi-Modul-Projekten ist Constraint-Divergenz: Modul A verlangt ^2.0 des Core-Moduls, Modul B verlangt bereits ^3.0, weil es eine neuere Funktion nutzt. Composer kann diesen Konflikt nicht auflösen, und das Projekt bleibt blockiert, bis Modul A ebenfalls auf Version 3 aktualisiert wird. Konsequente Modul-Versionierung mit klaren, regelmäßig aktualisierten Constraints in allen eigenen Modulen verhindert, dass solche Blockaden erst spät im Projekt sichtbar werden.

Hilfreich ist außerdem eine zentrale Übersicht, welches eigene Modul welche Version welcher Abhängigkeit voraussetzt, etwa als einfache Tabelle im internen Wiki oder als automatisiert generierter Bericht aus allen composer.json-Dateien der Modulfamilie. Diese Übersicht macht sichtbar, bevor ein Release geplant wird, welche Consumer-Module durch ein bevorstehendes MAJOR-Update des Core-Moduls betroffen sind, und verhindert, dass ein Upgrade erst im laufenden Deployment auf einen unerwarteten Constraint-Konflikt trifft.

Ein weiterer Aspekt, der in wachsenden Modulfamilien oft unterschätzt wird, ist die Reihenfolge von Releases. Wird das Core-Modul zuerst auf eine neue MAJOR-Version gehoben, bevor alle abhängigen Module nachgezogen wurden, entstehen zwangsläufig temporäre Inkompatibilitäten in Projekten, die automatisiert aktualisieren. Ein fester Release-Kalender, der Core-Updates und die Migration abhängiger Module bewusst bündelt, reduziert diese Reibung erheblich und macht die Modul-Versionierung über die gesamte Modulfamilie hinweg vorhersehbar.

Für besonders große Modulfamilien lohnt sich zusätzlich ein automatisierter Dependency-Graph, der bei jedem geplanten Release visualisiert, welche Module direkt oder transitiv von einer Versionsänderung betroffen wären. Ein solches Werkzeug macht auch für neue Teammitglieder sofort sichtbar, warum bestimmte Releases in einer festen Reihenfolge erfolgen müssen und andere unabhängig voneinander veröffentlicht werden können.

9. SemVer-Disziplin im Vergleich zu anderen Ansätzen

Nicht jedes Projekt startet mit sauberer SemVer-Versionierung. Viele gewachsene Agentur-Codebasen nutzen anfangs freilaufende Versionsnummern oder Datum-basierte Schemata. Der Unterschied in der praktischen Sicherheit für Consumer ist erheblich, besonders sobald ein Modul in mehr als einem Projekt eingesetzt wird.

Der folgende Vergleich zeigt, warum sich der zusätzliche Prozessaufwand von SemVer in der Praxis auszahlt, sobald mehr als ein Team oder mehr als ein Projekt von einem Modul abhängt. Gerade die Spalte zur Breaking-Change-Erkennung macht deutlich, dass die anderen Ansätze strukturell keine verlässliche Frühwarnung bieten können, unabhängig davon, wie sorgfältig einzelne Releases im Detail vorbereitet wurden.

Ansatz Breaking-Change-Erkennung Consumer-Sicherheit Aufwand
SemVer diszipliniert Explizit über Versionsstufe Hoch, Constraints steuern Risiko Mittel, braucht Review-Disziplin
Freilaufende Nummer Nicht erkennbar Niedrig, jedes Update ist ein Risiko Gering, aber trügerisch
Datum-basiert Nicht erkennbar Niedrig, kein Constraint-Schutz möglich Gering
Nur setup_version, kein Tag Nur für Setup-Patches sichtbar Niedrig, Composer ignoriert setup_version Gering

Der Umstieg von einem freilaufenden Schema auf diszipliniertes SemVer lohnt sich bereits ab dem zweiten Projekt, das ein Modul einbindet. Der einmalige Aufwand, eine erste saubere Major-Version zu definieren und Constraints in allen Consumer-Projekten nachzuziehen, zahlt sich bei jedem folgenden Release aus, weil Updates dann automatisiert und risikobewusst statt manuell und unsicher erfolgen können.

Selbst ein nachträglicher Umstieg mitten im Lebenszyklus eines Moduls ist machbar. Der übliche Weg ist, die aktuelle, freilaufende Version als neue Major-Version 1.0.0 zu deklarieren, ab diesem Zeitpunkt konsequent SemVer-Regeln anzuwenden und in der Release-Ankündigung transparent zu machen, dass ab dieser Version verbindliche Versionierung gilt. Consumer können sich dann bewusst entscheiden, ob und wann sie auf das neue Schema wechseln.

Diese Ankündigung sollte immer auch eine kurze Erklärung enthalten, warum der Umstieg erfolgt und welchen konkreten Nutzen er für Consumer-Teams bringt. Reine technische Formalie ohne erkennbaren Mehrwert wird von vielbeschäftigten Teams gerne ignoriert, während ein klar kommunizierter Sicherheitsgewinn die Akzeptanz für den neuen Prozess spürbar erhöht.

Mironsoft

Release-Management, SemVer-Disziplin und stabile Composer-Abhängigkeiten

Modul-Updates ohne böse Überraschungen?

Wir führen SemVer-Disziplin in eure eigenen Magento-2-Module ein, von der ersten sauberen Major-Version über den Release-Workflow bis zum verständlichen Changelog für alle Consumer-Projekte.

Versionsaudit

Bestehende Module auf SemVer-Konformität prüfen und korrigieren

Release-Workflow

Tagging, Changelog und Deprecation-Prozess sauber aufsetzen

Constraint-Beratung

Composer-Constraints für Consumer-Projekte risikobewusst festlegen

10. Zusammenfassung

Diszipliniertes SemVer verwandelt die Versionsnummer eines Magento-Moduls von einer beliebigen Zahl in ein verlässliches Versprechen. PATCH für Bugfixes, MINOR für rückwärtskompatible Erweiterungen, MAJOR für Breaking Changes: diese drei Regeln, konsequent angewendet, geben jedem Consumer-Team die Möglichkeit, über Composer-Constraints selbst zu entscheiden, wie viel Update-Risiko akzeptabel ist. Die Trennung zwischen module.xml setup_version und der Composer-Version aus dem Git-Tag ist dabei ein häufiger Stolperstein, der sich mit klarer Prozessdisziplin leicht vermeiden lässt.

Der entscheidende Hebel liegt nicht in der Versionsnummer allein, sondern in der Kommunikation drumherum. Ein gepflegtes Changelog, eine Deprecation-Phase vor entfernenden Änderungen und ein reproduzierbarer Release-Workflow mit Git-Tags machen aus Modul-Versionierung ein Werkzeug, das Vertrauen zwischen Modulanbieter und Consumer-Teams aufbaut, statt es bei jedem Update aufs Spiel zu setzen.

Am Ende zahlt sich diszipliniertes SemVer nicht nur beim einzelnen Update aus, sondern über die gesamte Lebensdauer eines Moduls hinweg. Teams, die diese Praxis konsequent durchhalten, verbringen spürbar weniger Zeit mit ungeplanten Hotfixes nach fehlgeschlagenen Updates und deutlich mehr Zeit mit der eigentlichen Weiterentwicklung ihrer Module.

SemVer für Magento-Module: Das Wichtigste auf einen Blick

Die drei Zahlen

PATCH für Bugfixes, MINOR für kompatible Erweiterungen, MAJOR für Breaking Changes.

Zwei Versionsquellen

module.xml setup_version steuert Setup-Patches, der Git-Tag steuert die Composer-Version.

Release-Workflow

Changelog aktualisieren, Tag setzen, erst dann pushen und in Consumer-Projekten updaten.

Kommunikation

Deprecation vor Entfernung, verständliches Changelog statt nur Versionszahl.

11. FAQ: SemVer für Magento-Module

1Was bedeutet SemVer konkret?
MAJOR.MINOR.PATCH: PATCH für Bugfixes, MINOR für kompatible neue Funktionen, MAJOR für Breaking Changes.
2Ist setup_version dasselbe wie die Composer-Version?
Nein, setup_version steuert nur Setup-Patches, die Composer-Version kommt meist aus dem Git-Tag.
3Wann ist eine Änderung ein Breaking Change?
Wenn bestehender Consumer-Code danach nicht mehr fehlerfrei kompiliert oder sich anders verhält.
4Ist eine neue Interface-Methode ein Breaking Change?
Ja, strikt genommen, weil bestehende Implementierungen plötzlich unvollständig sind. Gehört in MAJOR.
5Was bedeutet ^2.3 in composer.json?
Erlaubt alle Versionen ab 2.3.0 bis ausschließlich 3.0.0, also MINOR- und PATCH-Updates.
6Wann ~2.3.0 statt ^2.3 nutzen?
Bei geringem Vertrauen in die Versionierungsdisziplin. Erlaubt nur PATCH-Updates.
7Wie funktioniert eine Deprecation-Phase?
Mit @deprecated markieren, funktionsfähig lassen, erst im nächsten MAJOR entfernen.
8Was gehört in ein gutes Changelog?
Added, Changed, Deprecated, Removed, Fixed, plus konkrete Migrationsschritte bei Breaking Changes.
9Warum kollidieren Constraints in Multi-Modul-Projekten?
Wenn zwei Module unterschiedliche Constraints gegen dieselbe Abhängigkeit deklarieren, etwa ^2.0 und ^3.0.
10Lohnt sich der Umstieg auf SemVer?
Ja, bereits ab dem zweiten Projekt, das ein Modul einbindet, zahlt sich der Umstieg klar aus.