Semantic Release and Conventional Commits¶
Einordnung ins Overtime-Projekt
Damit Overtime-Images in der GitOps-Historie eindeutig und nachvollziehbar versioniert sind, statt nur über SHA-Tags identifiziert zu werden, wird Semantic Release auf Basis von Conventional Commits eingesetzt.
1. Kontext & Problemstellung (Deutsch)¶
Für ein verlässliches Deployment und einfache Rollbacks im fiktiven B2B-Kollaborations-Projekt Overtime benötigen Container-Images stabile und aussagekräftige Versions-Tags. Ein reiner Git-SHA-Tag (wie a3f9c12) bietet zwar technische Rückverfolgbarkeit, liefert den Betreibern und Auditoren jedoch keinerlei fachlichen Kontext über den Umfang der Änderung (Breaking Change, Feature, Bugfix).
Die manuelle Pflege von Changelogs und das händische Hochzählen von Versionsnummern (Versioning) sind fehleranfällig und werden unter Zeitdruck oft vernachlässigt. Um den strengen Anforderungen an Nachvollziehbarkeit und automatisierte Deployments gerecht zu werden, müssen Versionsnummern deterministisch aus der Code-Historie abgeleitet und Release Notes vollständig automatisch generiert werden.
2. Architecture Decision Record (English)¶
ADR-014: Semantic Release and Conventional Commits¶
Status¶
Accepted
Context and Problem Statement¶
Container images need stable, meaningful version tags for deployment and rollback. A SHA-only tag (a3f9c12) is traceable but carries no information about the scope of the change (breaking, feature, fix). Manually maintaining a changelog and bumping version numbers is error-prone and often skipped under time pressure. Release notes for auditors and operators must accurately reflect what changed between deployments without manual intervention.
Decision Drivers¶
- Deterministic Versioning: Version bumping rules must be deterministic and derived directly from commit messages, entirely removing human judgement.
- Automated Audit Trail: Changelogs and release notes must be generated automatically.
- Unambiguous GitOps State: Image tags in the GitOps repository must be unique, ordered, and semantically meaningful to make rollbacks unambiguous.
- Strict Release Gating: Version tags must only be created on the
mainbranch after successful Merge Request reviews, never directly from feature branches. Only versioned builds should make it into production.
Considered Options¶
- Manual Versioning — A human edits
pyproject.tomland manually creates a git tag. This is frequently forgotten, inconsistent, and lacks an automated changelog. - Date-based Tags (
2025-06-18) — Unique and ordered, but carry no semantic meaning regarding the impact of the release. They also do not solve the changelog problem. - Semantic Release — Automatically reads commit messages, derives the next semantic version (SemVer), creates the tag, and generates the changelog. Fully automated.
Decision Outcome¶
Chosen: Semantic Release driven by Conventional Commits.
Commit messages across all Overtime repositories must follow the Conventional Commits format to drive the automated release process.
Conventional Commits Specification¶
Commit messages follow this strict format:
| Commit Type | SemVer Bump | Example |
|---|---|---|
fix: |
Patch (0.0.x) |
fix: handle missing phone field in pii scrubber |
feat: |
Minor (0.x.0) |
feat: add correlation ID to outbound HTTP calls |
feat!:, fix!: or BREAKING CHANGE: in footer |
Major (x.0.0) |
feat!: overhaul API responses or any commit with a BREAKING CHANGE: footer |
chore:, docs:, refactor:, test:, ci: |
None | No release is created, avoiding release noise |
Consequences & Trade-offs¶
Positive Consequences¶
- Automated Traceability: Every image in the GitOps repository either has a SHA tag (short-lived, branch build) or a SemVer tag (release-ready, accompanied by an SBOM, security scan, and release notes).
- Structured Changelogs: Release notes are automatically structured by commit type and published as GitLab Releases — no manual changelog maintenance is required.
- Clean Rollbacks: A rollback in the
overtime-gitopsrepository is a simplegit revertto a specific SemVer tag, and the GitLab release notes describe exactly what was included in that version. - Reduced Noise: Commits labeled as
chore:orci:do not trigger releases, preventing version inflation from dependency updates or pipeline tweaks.
Negative Consequences / Trade-offs¶
- Strict Enforcement Required: Conventional Commits must be strictly enforced by team convention or pre-commit hooks (e.g.,
commitlint). Semantic Release produces garbage output if commit messages are freeform. - Token Management: The
@semantic-release/gitlabplugin requires aGL_TOKEN(a Personal Access Token) on the GitLab Free tier. If the token owner leaves the organization, the token must be manually rotated. - Pipeline Overhead: The Semantic Release job runs on every merge to the
mainbranch, even if there are no releasable commits (e.g., onlydocs:changes). It exits cleanly but still incurs the minor overhead of initializing a Node.js environment.
3. Pipeline Implementation & Code Snippet (English)¶
The tagging process and release generation are tightly integrated into the CI/CD pipeline. Semantic Release evaluates the commits on the main branch and creates a standard v{major}.{minor}.{patch} tag (e.g., v1.3.0).
This newly created tag automatically triggers a subsequent Tag Pipeline, which executes the following crucial steps:
- Builds and pushes the final release image explicitly tagged with the Semantic Version.
- Generates the SBOM and runs Trivy vulnerability and license scans specifically for this release image.
- Exposes manual deployment gating buttons for both the Test and Production environments.
.semantic-release:
stage: release
image: node:24.17.0@sha256:032e78d7e54e352129831743737e3a83171d9cc5b5896f411649c597ce0b11ea
before_script:
- npm install --no-save semantic-release @semantic-release/commit-analyzer @semantic-release/release-notes-generator @semantic-release/gitlab
script:
- npx semantic-release
rules:
- if: $CI_COMMIT_BRANCH == "main"
Configuration (.releaserc.json)¶
The following configuration file is placed in the repository root to define the branch rules and load the necessary plugins for GitLab integration:
{
"branches": ["main"],
"tagFormat": "v${version}",
"plugins": [
"@semantic-release/commit-analyzer",
"@semantic-release/release-notes-generator",
"@semantic-release/gitlab"
]
}
Note on CI Variables: To authenticate with the GitLab API and create the release and tag, a
GL_TOKEN(GitLab Access Token with theapiscope) must be stored as a masked and protected CI/CD variable within the GitLab project settings. Group/project access tokens are natively supported but require a paid GitLab Premium tier.
4. Compliance Einordnung (Deutsch)¶
Das detaillierte Mapping auf BSI IT-Grundschutz, CRA und CIS Benchmarks wird später ergänzt.