Um Überblick über den Änderungsverlauf einer Software zu haben, bietet es sich an – vor allem beim Einsatz einer Quellcodeverwaltung wie GIT – den CHANGELOG automatisch zu generieren. Voraussetzung dafür ist es, dass die Commit-Messages entsprechend formuliert sind.

Nachfolgend ist eine beispielhafte Konfiguration beschrieben, wie mithilfe von GitLab CI/CD automatisch beim Push in den Main-Branch eine Datei CHANGELOG.md generiert wird. Infolgedessen wird auch automatisch eine Versionierung auf Basis von Semantic Versioning eingeführt.

Semantic Versioning

Bei der semantischen Versionierung besteht die Versionsnummer aus MAJOR.MINOR.PATCH. Dabei hat jeder Teil der Versionsnummer folgende Bedeutung:

  • MAJOR: Eine Erhöhung von MAJOR bedeutet, dass Änderungen erfolgt sind, die inkompatibel mit Vorgängerversionen sind (Breaking Changes)
  • MINOR: Es wurden neue Funktionen eingeführt, jedoch gibt es keine Inkompatibilitäten im Vergleich zur Vorgängerversion
  • PATCH: Es gibt lediglich Fehlerbehebungen ohne neue Funktionen

Ebenso gibt es Zusätze, die für Pre-Releases oder Ähnliches verwendet werden können. Dazu sei auf die Dokumentation verwiesen.

Commit Convention

Um automatisch einen CHANGELOG generieren zu können, muss eine bestimmte Konvention für Commit-Messages eingehalten werden. Für unser Beispiel wird Conventional Commits verwendet – selbstverständlich gibt es jedoch auch noch andere. Das nachfolgend beschriebene Setup unterstützt mehrere verschiedene Konventionen – grundsätzlich können auch eigene konfiguriert werden.

Die Grundzüge der Spezifikation sind folgende:

Die Commit-Nachricht sollte wie folgt aufgebaut sein:

<Typ>[optionaler Gültigkeitsbereich]: <Beschreibung>

[optionaler Textkörper]

[optionale Fußnoten]

Der Commit enthält die folgenden Strukturelemente, um den Benutzern Ihrer Bibliothek Ihre Absichten mitzuteilen:

  1. fix: ein Commit des Typs fix behebt einen Fehler in Ihrer Codebasis (dies entsprich einem PATCH in semantischer Versionierung).
  2. feat: ein Commit des Typs feat führt eine neue Funktion in Ihrer Codebasis ein (dies entspricht einem MINOR in semantischer Versionierung).
  3. BREAKING CHANGE: ein Commit mit BREAKING CHANGE: in der Fußzeile, oder einem angehängten ! nach dem Typ/Gültigkeitsbereich, führt tiefgreifende Änderungen an der API ein (dies entspricht einem MAJOR in semantischer Versionierung). Ein BREAKING CHANGE kann Teil eines Commits jeden Typs sein.
  4. Andere Typen als fix: und feat: sind erlaubt, z. B. erlaubt @commitlint/config-conventional (basierend auf the Angular conventionbuild:chore:ci:docs:style:refactor:perf:test:, und andere.
  5. Andere Fußzeilen als BREAKING CHANGE: <Beschreibung> können angegeben werden und folgen der Konvention ähnlich zum git Trailer Format.

Zusätzliche Typen sind in der konventionellen Commit-Spezifikation nicht vorgeschrieben und haben keine impliziten Auswirkungen auf die semantische Versionierung (sofern sie keinen BREAKING CHANGE enthalten). Ein Gültigkeitsbereich kann zusammen mit einem Commit Typen angegeben werden, um weitere kontextuelle Informationen in Klammern zu geben, z. B. feat(parser): add ability to parse arrays.

Quelle: conventionalcommits.org

GitLab Konfiguration

Unser Ziel ist es, bei jedem Commit in den Main-Branch automatisch zu Versionieren und die Datei CHANGELOG.md zu aktualisieren. Dafür setzen wir das Tool semantic-release ein.

Wir erstellen im Hauptverzeichnis die Konfigurationsdatei .releaserc

JSON
.releaserc

Mit branches definieren wir, für welche Branches ein release generiert werden soll. Über Plugins konfigurieren wir, dass die Commits-Messages mit der Konvention conventionalcommits ausgewertet werden sollen. Dementsprechend wird daraus die Versionierung abgeleitet (MAJOR, MINOR oder PATCH). Das Plugin release-notes-generator soll anschließend den changelog-Inhalt erzeugen. Die Erweiterung changelog schreibt diese schließlich in die Datei CHANGELOG.md und git erzeugt einen Commit mit der aktualisierten Datei. Über den Parameter message kann die Commit-Message definiert werden. Auffällig ist hier der Text [skip ci]. Damit wird GitLab angewiesen, für diesen Commit keine CI-Pipeline auszulösen – wir wollen schließlich keine neue Version nur weil die CHANGELOG-Datei erzeugt wurde.

Weiters muss noch über folgende Konfigurationsdatei die automatische Generierung bei Commits in den Main-Branch ausgelöst werden:

YAML
.gitlab-ci.yml

Über only: main wird definiert, dass dieser Teil nur für den Main-Branch ausgeführt werden soll. Im Abschnitt before_script werden die notwendigen Softwarekomponenten installiert. Mit script wird schlussendlich die Generierung ausgelöst.

Damit der Vorgang allerdings ausgeführt werden kann, muss noch ein Access-Token hinterlegt werden, mit dem die Commits durchgeführt werden können. Der Personal Access Token kann wie auch hier beschrieben generiert werden. In den Projekteinstellungen CI / CD im Bereich Variables muss dieser aber in diesem Fall unter dem Key GITLAB_TOKEN hinterlegt werden. Hier sollte ebenso Protected und Masked aktiviert werden.

Initial werden die beiden oberen Dateien in den Main-Branch mit beispielsweise folgender Commit-Message gepusht:

feat: Initial commit

Demo repository for an automated generation of CHANGELOG.md and semantic versioning

Der weitere Workflow ist nun folgender: In der laufenden Entwicklung wird in Branches gepusht. Anschließend wird ein Merge-Request erstellt, der nach dem Review in den Main-Branch gemerged wird. Damit alle relevanten Commit-Messages in den Changelog übernommen werden, dürfen die Commits nicht gesquashed werden.

Auf GitLab kann hier ein Demo-Repository mit obigem Beispiel geforked werden: philipp.doblhofer/automatic-changelog-demo

Schreib einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert